浏览代码

Merge branch 'master' into i/7822

Kamil Piechaczek 5 年之前
父节点
当前提交
eee94cef56
共有 46 个文件被更改,包括 449 次插入415 次删除
  1. 33 0
      .github/workflows/ckeditor5-integrations.yml
  2. 21 21
      CHANGELOG.md
  3. 2 2
      packages/ckeditor5-autoformat/tests/autoformat.js
  4. 3 3
      packages/ckeditor5-code-block/src/codeblockediting.js
  5. 2 2
      packages/ckeditor5-core/tests/commandcollection.js
  6. 8 8
      packages/ckeditor5-engine/docs/framework/guides/deep-dive/schema.md
  7. 1 1
      packages/ckeditor5-engine/src/controller/datacontroller.js
  8. 1 1
      packages/ckeditor5-engine/src/model/schema.js
  9. 1 1
      packages/ckeditor5-engine/tests/model/operation/operation.js
  10. 0 39
      packages/ckeditor5-engine/tests/model/operation/transform.js
  11. 1 1
      packages/ckeditor5-engine/tests/model/position.js
  12. 26 28
      packages/ckeditor5-engine/tests/model/schema.js
  13. 5 15
      packages/ckeditor5-engine/tests/model/selection.js
  14. 2 2
      packages/ckeditor5-engine/tests/tickets/ckeditor5-692.js
  15. 0 16
      packages/ckeditor5-engine/tests/view/documentselection.js
  16. 58 58
      packages/ckeditor5-engine/tests/view/domconverter/dom-to-view.js
  17. 1 1
      packages/ckeditor5-engine/tests/view/node.js
  18. 0 10
      packages/ckeditor5-engine/tests/view/selection.js
  19. 0 9
      packages/ckeditor5-engine/tests/view/styles/utils.js
  20. 1 1
      packages/ckeditor5-font/src/ui/colorui.js
  21. 1 1
      packages/ckeditor5-image/src/imageupload/ui/imageuploadpanelview.js
  22. 20 11
      packages/ckeditor5-link/src/linkui.js
  23. 36 24
      packages/ckeditor5-link/tests/linkui.js
  24. 10 12
      packages/ckeditor5-list/docs/_snippets/features/lists-basic.html
  25. 10 9
      packages/ckeditor5-list/docs/_snippets/features/lists-style.html
  26. 3 3
      packages/ckeditor5-list/docs/api/list.md
  27. 17 9
      packages/ckeditor5-list/docs/features/lists.md
  28. 2 2
      packages/ckeditor5-list/docs/features/todo-lists.md
  29. 48 41
      packages/ckeditor5-list/src/liststyleediting.js
  30. 3 15
      packages/ckeditor5-list/tests/listediting.js
  31. 92 4
      packages/ckeditor5-list/tests/liststyleediting.js
  32. 1 1
      packages/ckeditor5-list/tests/todolistediting.js
  33. 0 11
      packages/ckeditor5-page-break/tests/pagebreakediting.js
  34. 1 1
      packages/ckeditor5-restricted-editing/tests/restrictededitingmodeediting.js
  35. 2 2
      packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js
  36. 2 2
      packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js
  37. 1 1
      packages/ckeditor5-ui/tests/toolbar/toolbarview.js
  38. 0 3
      packages/ckeditor5-ui/tests/viewcollection.js
  39. 4 4
      packages/ckeditor5-utils/tests/config.js
  40. 1 1
      packages/ckeditor5-utils/tests/diff.js
  41. 4 4
      packages/ckeditor5-utils/tests/fastdiff.js
  42. 0 11
      packages/ckeditor5-watchdog/tests/utils/areconnectedthroughproperties.js
  43. 1 1
      packages/ckeditor5-word-count/src/wordcount.js
  44. 6 6
      scripts/docs/build-docs.js
  45. 2 1
      scripts/docs/buildapi.js
  46. 16 16
      scripts/switch-to-dev-dev.sh

+ 33 - 0
.github/workflows/ckeditor5-integrations.yml

@@ -0,0 +1,33 @@
+# This script triggers Travis that verifies whether projects that depend on CKEditor 5 build correctly.
+#
+# In order to integrate the action in a new repository, you need add a few secrets in the new repository.
+#   - INTEGRATION_CI_ORGANIZATION - a name of the organization that keeps the repository where the build should be triggered
+#   - INTEGRATION_CI_REPOSITORY - a name of the repository where the build should be triggered
+#   - INTEGRATION_CI_TRAVIS_TOKEN - an authorization token generated by Travis CLI: `travis --pro token`
+name: CKEditor 5 Integrations
+
+on:
+  push:
+    branches: [ master ]
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Trigger CI
+        env:
+          WORKFLOW_TRIGGER_REPOSITORY: ${{ github.repository }}
+          WORKFLOW_TRIGGER_COMMIT: ${{ github.sha }}
+          WORKFLOW_ORGANIZATION: ${{ secrets.INTEGRATION_CI_ORGANIZATION }}
+          WORKFLOW_REPOSITORY: ${{ secrets.INTEGRATION_CI_REPOSITORY }}
+          WORKFLOW_TRAVIS_TOKEN: ${{ secrets.INTEGRATION_CI_TRAVIS_TOKEN }}
+        run: |
+          export BUILD_MESSAGE="Repository: $WORKFLOW_TRIGGER_REPOSITORY\n\nCommit: https://github.com/$WORKFLOW_TRIGGER_REPOSITORY/commit/$WORKFLOW_TRIGGER_COMMIT."
+          export REQUEST_BODY="{\"request\": { \"branch\": \"master\", \"message\": \"$BUILD_MESSAGE\" } }"
+          curl -s -X POST \
+            -H "Content-Type: application/json" \
+            -H "Accept: application/json" \
+            -H "Travis-API-Version: 3" \
+            -H "Authorization: token $WORKFLOW_TRAVIS_TOKEN" \
+            -d "$REQUEST_BODY" \
+            "https://api.travis-ci.com/repo/$WORKFLOW_ORGANIZATION%2F$WORKFLOW_REPOSITORY/requests"

+ 21 - 21
CHANGELOG.md

@@ -9,24 +9,24 @@ We are happy to announce the release of CKEditor 5 v22.0.0.
 
 This release brings a few new features:
 
-* [List styles plugin](https://github.com/ckeditor/ckeditor5/issues/7801).
-* [Makrdown plugin](https://github.com/ckeditor/ckeditor5/issues/6007).
+* The [list style plugin](https://github.com/ckeditor/ckeditor5/issues/7801).
+* The [Markdown plugin](https://github.com/ckeditor/ckeditor5/issues/6007).
 * [Inserting image with URL](https://github.com/ckeditor/ckeditor5/issues/7794).
-* [New event-based conversion api](https://github.com/ckeditor/ckeditor5/issues/7336).
+* [A new event-based conversion API](https://github.com/ckeditor/ckeditor5/issues/7336).
 
 Please note that there are some **major breaking changes**. Be sure to review them before upgrading.
 
-<!-- TODO: Add a link to the blog post. -->
+Read more in the blog post: https://ckeditor.com/blog/ckeditor-5-v22.0.0-with-inserting-images-via-url-list-styles-and-markdown-plugin/
 
 ### Collaboration features
 
-The CKEditor 5 Collaboration features changelog can be found here: https://ckeditor.com/collaboration/changelog.
+The CKEditor 5 Collaboration Features changelog can be found here: https://ckeditor.com/collaboration/changelog.
 
 ### MAJOR BREAKING CHANGES [ℹ️](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/versioning-policy.html#major-and-minor-breaking-changes)
 
-* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: The `config.view` callback of `DowncastHelpers` takes a `DowncastConversionApi` instance instead of a `DowncastWriter`. An example migration snippet can be found in a [GitHub comment](https://github.com/ckeditor/ckeditor5/issues/7334#issuecomment-670450941). See [#7334](https://github.com/ckeditor/ckeditor5/issues/7334).
-* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: The `config.model` callback of `UpcastHelpers` takes a `UpcastConversionApi` instance instead of a `ModelWriter`. An example migration snippet can be found in a [GitHub comment](https://github.com/ckeditor/ckeditor5/issues/7334#issuecomment-670450941). See [#7334](https://github.com/ckeditor/ckeditor5/issues/7334).
-* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: The `config.view` parameter for upcast element-to-element conversion helpers configurations is now mandatory. You can retain previous "catch-all" behavior for upcast converter using `config.view = /[\s\S]+/` value.
+* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: The `view` and `model` callbacks of all one-way converter helpers (such as `editor.conversion.for( 'upcast' ).elementToElement()`, `editor.conversion.for( 'downcast' ).attributeToElement()`) now take the `conversionApi` as their second parameter. Previously, the second parameter was the downcast or upcast writer instance. Now, the writer needs to be retrieved from `conversionApi.writer`.<br><br>
+An example migration snippet can be found in a [GitHub comment](https://github.com/ckeditor/ckeditor5/issues/7334#issuecomment-670450941).
+* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: The `config.view` parameter for upcast element-to-element conversion helper configurations is now mandatory. You can retain the previous "catch-all" behavior for the upcast converter using the `config.view = /[\s\S]+/` value.
 
 ### MINOR BREAKING CHANGES [ℹ️](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/versioning-policy.html#major-and-minor-breaking-changes)
 
@@ -36,35 +36,35 @@ The CKEditor 5 Collaboration features changelog can be found here: https://ckedi
 ### Features
 
 * **[clipboard](https://www.npmjs.com/package/@ckeditor/ckeditor5-clipboard)**: Pasting a plain text will inherit selection attributes. Closes [#1006](https://github.com/ckeditor/ckeditor5/issues/1006). ([commit](https://github.com/ckeditor/ckeditor5/commit/2a163e389a6b22b1e5590fe6a2ed8204387d4350))
-* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Options passed to `Editor#getData()` and `DataController#get()` are now available in downcast conversion under `conversionApi.options` object. Closes [#7628](https://github.com/ckeditor/ckeditor5/issues/7628). ([commit](https://github.com/ckeditor/ckeditor5/commit/0a5d07e3c9a5cef51ebfb4a5819b5118ad9ae115))
-* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Added conversion API to upcast and downcast helpers. Closes [#7334](https://github.com/ckeditor/ckeditor5/issues/7334). ([commit](https://github.com/ckeditor/ckeditor5/commit/16c971198971b770d4e7aff4ea8eec7a88a6fcdb))
-* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Introduced `SchemaItemDefinition#isSelectable` and `SchemaItemDefinition#isContent` properties. Closes [#6432](https://github.com/ckeditor/ckeditor5/issues/6432). ([commit](https://github.com/ckeditor/ckeditor5/commit/579c1c851ca33c78de60c98777684f8ee5ceb26e))
-* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Introduced new upcast `ConversionApi` helper methods - `conversionApi.safeInsert()` and `conversionApi.updateConversionResult()`. New methods are intended to simplify writing event based element-to-element converters. Closes [#7336](https://github.com/ckeditor/ckeditor5/issues/7336). ([commit](https://github.com/ckeditor/ckeditor5/commit/8d84af1610089ea7916401ecf6f636c9d330b459))
+* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Options passed to `Editor#getData()` and `DataController#get()` are now available in downcast conversion under the `conversionApi.options` object. Closes [#7628](https://github.com/ckeditor/ckeditor5/issues/7628). ([commit](https://github.com/ckeditor/ckeditor5/commit/0a5d07e3c9a5cef51ebfb4a5819b5118ad9ae115))
+* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Added the conversion API to upcast and downcast helpers. Closes [#7334](https://github.com/ckeditor/ckeditor5/issues/7334). ([commit](https://github.com/ckeditor/ckeditor5/commit/16c971198971b770d4e7aff4ea8eec7a88a6fcdb))
+* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Introduced the `SchemaItemDefinition#isSelectable` and `SchemaItemDefinition#isContent` properties. Closes [#6432](https://github.com/ckeditor/ckeditor5/issues/6432). ([commit](https://github.com/ckeditor/ckeditor5/commit/579c1c851ca33c78de60c98777684f8ee5ceb26e))
+* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Introduced new upcast `ConversionApi` helper methods: `conversionApi.safeInsert()` and `conversionApi.updateConversionResult()`. The new methods are intended to simplify writing event-based element-to-element converters. Closes [#7336](https://github.com/ckeditor/ckeditor5/issues/7336). ([commit](https://github.com/ckeditor/ckeditor5/commit/8d84af1610089ea7916401ecf6f636c9d330b459))
 * **[image](https://www.npmjs.com/package/@ckeditor/ckeditor5-image)**: Introduced the insert image via URL feature. Closes [#7794](https://github.com/ckeditor/ckeditor5/issues/7794). ([commit](https://github.com/ckeditor/ckeditor5/commit/bb00c23f6234751666e859e6e5d7e909f194e375))
 * **[indent](https://www.npmjs.com/package/@ckeditor/ckeditor5-indent)**: Block indentation is now recognized as a formatting attribute. Closes [#2358](https://github.com/ckeditor/ckeditor5/issues/2358). ([commit](https://github.com/ckeditor/ckeditor5/commit/6b2cc25dd717eb22caf7189d8cf33511397179c0))
-* **[list](https://www.npmjs.com/package/@ckeditor/ckeditor5-list)**: Introduced the list styles feature that allows customizing the list marker. Closes [#7801](https://github.com/ckeditor/ckeditor5/issues/7801). ([commit](https://github.com/ckeditor/ckeditor5/commit/137dd2856aecaa8f9c023e6ca9d01592707137a0))
+* **[list](https://www.npmjs.com/package/@ckeditor/ckeditor5-list)**: Introduced the list style feature that allows customizing the list marker. Closes [#7801](https://github.com/ckeditor/ckeditor5/issues/7801). ([commit](https://github.com/ckeditor/ckeditor5/commit/137dd2856aecaa8f9c023e6ca9d01592707137a0))
 * **[markdown-gfm](https://www.npmjs.com/package/@ckeditor/ckeditor5-markdown-gfm)**: Introduced the `Markdown` plugin. Closes [#6007](https://github.com/ckeditor/ckeditor5/issues/6007). ([commit](https://github.com/ckeditor/ckeditor5/commit/7cd5fc198e1977ecefbf0e455f4b514b467e7775))
-* **[markdown-gfm](https://www.npmjs.com/package/@ckeditor/ckeditor5-markdown-gfm)**: The markdown data processor has been revamped and got the dependencies updated. Closes [#5988](https://github.com/ckeditor/ckeditor5/issues/5988). ([commit](https://github.com/ckeditor/ckeditor5/commit/3881349eae0c9a862e76487f8eb117d6ca3e38b0))
-* **[utils](https://www.npmjs.com/package/@ckeditor/ckeditor5-utils)**: Introduced the `Rect#getBoundingRect()` method that returns a `Rect` instance containing all the rectangles passed as argument. Closes [#7858](https://github.com/ckeditor/ckeditor5/issues/7858). ([commit](https://github.com/ckeditor/ckeditor5/commit/ccfaf5e54854cc8a62ebbc005e35676f77be37c4))
+* **[markdown-gfm](https://www.npmjs.com/package/@ckeditor/ckeditor5-markdown-gfm)**: The Markdown data processor was revamped and got the dependencies updated. Closes [#5988](https://github.com/ckeditor/ckeditor5/issues/5988). ([commit](https://github.com/ckeditor/ckeditor5/commit/3881349eae0c9a862e76487f8eb117d6ca3e38b0))
+* **[utils](https://www.npmjs.com/package/@ckeditor/ckeditor5-utils)**: Introduced the `Rect#getBoundingRect()` method that returns a `Rect` instance containing all the rectangles passed as an argument. Closes [#7858](https://github.com/ckeditor/ckeditor5/issues/7858). ([commit](https://github.com/ckeditor/ckeditor5/commit/ccfaf5e54854cc8a62ebbc005e35676f77be37c4))
 * **[utils](https://www.npmjs.com/package/@ckeditor/ckeditor5-utils)**: Introduced the `passive` option support in the `DomEmitterMixin#listenTo()` method. Closes [#7828](https://github.com/ckeditor/ckeditor5/issues/7828). ([commit](https://github.com/ckeditor/ckeditor5/commit/a7ef65c8246b9591a9a2081cfb19266de0c6194b))
-* **[widget](https://www.npmjs.com/package/@ckeditor/ckeditor5-widget)**: Keyboard vertical navigation in the text lines next to objects should move the caret to the position closest to the object. Closes [#7630](https://github.com/ckeditor/ckeditor5/issues/7630). ([commit](https://github.com/ckeditor/ckeditor5/commit/7984a14a411416634d64d405da2d6d18a314e947))
+* **[widget](https://www.npmjs.com/package/@ckeditor/ckeditor5-widget)**: Keyboard vertical navigation in text lines next to objects should move the caret to the position closest to the object. Closes [#7630](https://github.com/ckeditor/ckeditor5/issues/7630). ([commit](https://github.com/ckeditor/ckeditor5/commit/7984a14a411416634d64d405da2d6d18a314e947))
 
 ### Bug fixes
 
-* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Upcast conversion will now try to wrap text or inline elements in a paragraph in a place where is not allowed but a paragraph is allowed. Closes [#7753](https://github.com/ckeditor/ckeditor5/issues/7753), [#6698](https://github.com/ckeditor/ckeditor5/issues/6698). ([commit](https://github.com/ckeditor/ckeditor5/commit/5e857fd0ec6f4dc9e86dec0bf9c5b87289eedf8b))
+* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: Upcast conversion will now try to wrap text or inline elements in a paragraph in a place where they are not allowed but a paragraph is allowed. Closes [#7753](https://github.com/ckeditor/ckeditor5/issues/7753), [#6698](https://github.com/ckeditor/ckeditor5/issues/6698). ([commit](https://github.com/ckeditor/ckeditor5/commit/5e857fd0ec6f4dc9e86dec0bf9c5b87289eedf8b))
 * **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: The selection will no longer inherit attributes from an empty inline element. Closes [#7459](https://github.com/ckeditor/ckeditor5/issues/7459). ([commit](https://github.com/ckeditor/ckeditor5/commit/1ddb955cc667ad16b41521762f77b95382f467da))
-* **[link](https://www.npmjs.com/package/@ckeditor/ckeditor5-link)**: Fixed a case where the link balloon would point invalid place after browser scroll or resize. Closes [#7705](https://github.com/ckeditor/ckeditor5/issues/7705). ([commit](https://github.com/ckeditor/ckeditor5/commit/5158209e2a39884a3015e317f17f33a340e2502d))
+* **[link](https://www.npmjs.com/package/@ckeditor/ckeditor5-link)**: Fixed a case where the link balloon would point to an invalid place after the browser scroll or resize. Closes [#7705](https://github.com/ckeditor/ckeditor5/issues/7705). ([commit](https://github.com/ckeditor/ckeditor5/commit/5158209e2a39884a3015e317f17f33a340e2502d))
 * **[ui](https://www.npmjs.com/package/@ckeditor/ckeditor5-ui)**: Dropdown panels from the editor's main toolbar should always float above the contextual balloons from the editor's content. Closes [#7874](https://github.com/ckeditor/ckeditor5/issues/7874). ([commit](https://github.com/ckeditor/ckeditor5/commit/57d3f02958ad32b8c774dbdc38e1a1210e75af1f))
 * **[ui](https://www.npmjs.com/package/@ckeditor/ckeditor5-ui)**: Balloon toolbar should reposition and ungroup items correctly when the window resizes. Closes [#6444](https://github.com/ckeditor/ckeditor5/issues/6444). ([commit](https://github.com/ckeditor/ckeditor5/commit/32523780fa27146d4f74b538af4831d8b9683bd9))
-* **[utils](https://www.npmjs.com/package/@ckeditor/ckeditor5-utils)**: `Rect` utility returns wrong sizes in case of a sequenced range. Closes [#7838](https://github.com/ckeditor/ckeditor5/issues/7838). ([commit](https://github.com/ckeditor/ckeditor5/commit/ccfaf5e54854cc8a62ebbc005e35676f77be37c4))
+* **[utils](https://www.npmjs.com/package/@ckeditor/ckeditor5-utils)**: The `Rect` utility returns wrong sizes in case of a sequenced range. Closes [#7838](https://github.com/ckeditor/ckeditor5/issues/7838). ([commit](https://github.com/ckeditor/ckeditor5/commit/ccfaf5e54854cc8a62ebbc005e35676f77be37c4))
 
 ### Other changes
 
 * **[markdown-gfm](https://www.npmjs.com/package/@ckeditor/ckeditor5-markdown-gfm)**: Upgraded to Marked v1.1.1. Closes [#7850](https://github.com/ckeditor/ckeditor5/issues/7850). ([commit](https://github.com/ckeditor/ckeditor5/commit/d6c8731a33f3402b8bd71b987b762116efd3898a))
-* **[mention](https://www.npmjs.com/package/@ckeditor/ckeditor5-mention)**: The <kbd>space</kbd> key will not confirm a mention selection from the list. Closes [#6394](https://github.com/ckeditor/ckeditor5/issues/6394). ([commit](https://github.com/ckeditor/ckeditor5/commit/a8d41ecbbeb5d36694ba74d0391805cfaa5214e7))
+* **[mention](https://www.npmjs.com/package/@ckeditor/ckeditor5-mention)**: The <kbd>Space</kbd> key will not confirm a mention selection from the list. Closes [#6394](https://github.com/ckeditor/ckeditor5/issues/6394). ([commit](https://github.com/ckeditor/ckeditor5/commit/a8d41ecbbeb5d36694ba74d0391805cfaa5214e7))
 * **[remove-format](https://www.npmjs.com/package/@ckeditor/ckeditor5-remove-format)**: Block formatting should be removed if the selection is inside that block. ([commit](https://github.com/ckeditor/ckeditor5/commit/6b2cc25dd717eb22caf7189d8cf33511397179c0))
 * **[table](https://www.npmjs.com/package/@ckeditor/ckeditor5-table)**: The `tableCell` model element brought by the `TableEditing` plugin is no longer an object (`SchemaItemDefinition#isObject`) in the `Schema` but a selectable (`SchemaItemDefinition#isSelectable`) (see [#6432](https://github.com/ckeditor/ckeditor5/issues/6432)). ([commit](https://github.com/ckeditor/ckeditor5/commit/579c1c851ca33c78de60c98777684f8ee5ceb26e))
-* **[table](https://www.npmjs.com/package/@ckeditor/ckeditor5-table)**: Pressing <kbd>Shift</kbd>+<kbd>Tab</kbd> in the first table cell now selects entire table. Closes [#7535](https://github.com/ckeditor/ckeditor5/issues/7535). ([commit](https://github.com/ckeditor/ckeditor5/commit/3064c64733145b40290480f3299e168b74380d04))
+* **[table](https://www.npmjs.com/package/@ckeditor/ckeditor5-table)**: Pressing <kbd>Shift</kbd>+<kbd>Tab</kbd> in the first table cell now selects the entire table. Closes [#7535](https://github.com/ckeditor/ckeditor5/issues/7535). ([commit](https://github.com/ckeditor/ckeditor5/commit/3064c64733145b40290480f3299e168b74380d04))
 * **[ui](https://www.npmjs.com/package/@ckeditor/ckeditor5-ui)**: The `clickOutsideHandler()` function will take into consideration that the editor can be placed in a shadow root while detecting a click. Closes [#7743](https://github.com/ckeditor/ckeditor5/issues/7743). ([commit](https://github.com/ckeditor/ckeditor5/commit/2dc026409051828618c274ae62ce331fe05681fe))
 
   Thanks to [@ywsang](https://github.com/ywsang).

+ 2 - 2
packages/ckeditor5-autoformat/tests/autoformat.js

@@ -486,7 +486,7 @@ describe( 'Autoformat', () => {
 		} );
 
 		describe( 'with code element', () => {
-			describe( 'should not format', () => {
+			describe( 'should not format (inside)', () => {
 				it( '* inside', () => {
 					setData( model, '<paragraph><$text code="true">fo*obar[]</$text></paragraph>' );
 
@@ -532,7 +532,7 @@ describe( 'Autoformat', () => {
 				} );
 			} );
 
-			describe( 'should not format', () => {
+			describe( 'should not format (across)', () => {
 				it( '* across', () => {
 					setData( model, '<paragraph><$text code="true">fo*o</$text>bar[]</paragraph>' );
 

+ 3 - 3
packages/ckeditor5-code-block/src/codeblockediting.js

@@ -214,9 +214,9 @@ export default class CodeBlockEditing extends Plugin {
 				return;
 			}
 
-			leaveBlockStartOnEnter( editor, data.isSoft ) ||
-			leaveBlockEndOnEnter( editor, data.isSoft ) ||
-			breakLineOnEnter( editor );
+			if ( !leaveBlockStartOnEnter( editor, data.isSoft ) && !leaveBlockEndOnEnter( editor, data.isSoft ) ) {
+				breakLineOnEnter( editor );
+			}
 
 			data.preventDefault();
 			evt.stop();

+ 2 - 2
packages/ckeditor5-core/tests/commandcollection.js

@@ -135,8 +135,8 @@ describe( 'CommandCollection', () => {
 		} );
 	} );
 
-	describe( 'commands()', () => {
-		it( 'returns iterator of commands', () => {
+	describe( 'destroy()', () => {
+		it( 'should destroy commands', () => {
 			const c1 = new SomeCommand( editor );
 			const c2 = new SomeCommand( editor );
 

+ 8 - 8
packages/ckeditor5-engine/docs/framework/guides/deep-dive/schema.md

@@ -260,8 +260,8 @@ Here is a table listing various model elements and their properties registered i
 </table>
 
 <info-box>
-	* <span id="inherited1">[1]</span> The value of `isLimit` is `true` for this element because all [objects](#object-elements) are automatically [limit elements](#limit-elements),
-	* <span id="inherited2">[2]</span> The value of `isSelectable` is `true` for this element because all [objects](#object-elements) are automatically [selectable elements](#selectable-elements),
+	* <span id="inherited1">[1]</span> The value of `isLimit` is `true` for this element because all [objects](#object-elements) are automatically [limit elements](#limit-elements).
+	* <span id="inherited2">[2]</span> The value of `isSelectable` is `true` for this element because all [objects](#object-elements) are automatically [selectable elements](#selectable-elements).
 	* <span id="inherited3">[3]</span> The value of `isContent` is `true` for this element because all [objects](#object-elements) are automatically [content elements](#content-elements).
 </info-box>
 
@@ -303,11 +303,11 @@ schema.register( 'myImage', {
 The {@link module:engine/model/schema~Schema#isObject `Schema#isObject()`} can later be used to check this property.
 
 <info-box>
-	Every "object" is automatically also:
+	Every object is automatically also:
 
-	* a [limit element](#limit-elements) – for every element with `isObject` set `true`, {@link module:engine/model/schema~Schema#isLimit `Schema#isLimit( element )`} will always return `true`.
-	* a [selectable element](#selectable-elements) – for every element with `isObject` set `true`, {@link module:engine/model/schema~Schema#isSelectable `Schema#isSelectable( element )`} will always return `true`.
-	* a [content element](#content-elements) – for every element with `isObject` set `true`, {@link module:engine/model/schema~Schema#isContent `Schema#isContent( element )`} will always return `true`.
+	* A [limit element](#limit-elements) &ndash; For every element with `isObject` set to `true`, {@link module:engine/model/schema~Schema#isLimit `Schema#isLimit( element )`} will always return `true`.
+	* A [selectable element](#selectable-elements) &ndash; For every element with `isObject` set to `true`, {@link module:engine/model/schema~Schema#isSelectable `Schema#isSelectable( element )`} will always return `true`.
+	* A [content element](#content-elements) &ndash; For every element with `isObject` set to `true`, {@link module:engine/model/schema~Schema#isContent `Schema#isContent( element )`} will always return `true`.
 </info-box>
 
 ### Block elements
@@ -341,14 +341,14 @@ schema.register( 'mySelectable', {
 The {@link module:engine/model/schema~Schema#isSelectable `Schema#isSelectable()`} method can later be used to check this property.
 
 <info-box>
-	All [object elements](#object-elements) are selectable by default. There are other selectable elements registered in the editor, though. For instance, there is also the `tableCell` model element (rendered as a `<td>` in the editing view) that is selectable while **not** registered as an object. The {@link features/table#table-selection table selection} plugin takes advantage of this fact and allows users create rectangular selections made of multiple table cells.
+	All [object elements](#object-elements) are selectable by default. There are other selectable elements registered in the editor, though. For instance, there is also the `tableCell` model element (rendered as a `<td>` in the editing view) that is selectable while **not** registered as an object. The {@link features/table#table-selection table selection} plugin takes advantage of this fact and allows users to create rectangular selections made of multiple table cells.
 </info-box>
 
 ### Content elements
 
 You can tell content model elements from other elements by looking at their representation in the editor data (you can use {@link module:editor-classic/classiceditor~ClassicEditor#getData `editor.getData()`} or {@link module:engine/model/model~Model#hasContent Model#hasContent()} to check this out).
 
-Elements such as images or media will **always** find their way into editor data and this is what makes them content elements. They are marked with the {@link module:engine/model/schema~SchemaItemDefinition#isContent `isContent`} property in the schema:
+Elements such as images or media will **always** find their way into the editor data and this is what makes them content elements. They are marked with the {@link module:engine/model/schema~SchemaItemDefinition#isContent `isContent`} property in the schema:
 
 ```js
 schema.register( 'myImage', {

+ 1 - 1
packages/ckeditor5-engine/src/controller/datacontroller.js

@@ -72,7 +72,7 @@ export default class DataController {
 		 *
 		 * @member {module:engine/dataprocessor/dataprocessor~DataProcessor} #processor
 		 */
-		this.processor;
+		this.processor = undefined;
 
 		/**
 		 * Mapper used for the conversion. It has no permanent bindings, because they are created when getting data and

+ 1 - 1
packages/ckeditor5-engine/src/model/schema.js

@@ -1256,7 +1256,7 @@ mix( Schema, ObservableMixin );
  * {@glink framework/guides/deep-dive/schema#selectable-elements Selectable elements} section of the Schema deep dive} guide.
  *
  * @property {Boolean} isContent
- * An item is a content when it always finds its way to editor data output regardless of the number and type of its descendants.
+ * An item is a content when it always finds its way to the editor data output regardless of the number and type of its descendants.
  * Examples of content elements: `$text`, `image`, `table`, etc. (but not `paragraph`, `heading1` or `tableCell`).
  *
  * **Note:** An object is also a content element, so

+ 1 - 1
packages/ckeditor5-engine/tests/model/operation/operation.js

@@ -39,7 +39,7 @@ describe( 'Operation', () => {
 			} );
 		} );
 
-		it( 'should create proper json object #1', () => {
+		it( 'should create proper json object #2', () => {
 			const op = new Operation( 4 );
 			const batch = new Batch();
 			batch.addOperation( op );

+ 0 - 39
packages/ckeditor5-engine/tests/model/operation/transform.js

@@ -1771,45 +1771,6 @@ describe( 'transform', () => {
 				expectOperation( transOp[ 2 ], expected );
 			} );
 
-			it( 'range intersects on right side of transforming range and is important: shrink range', () => {
-				const transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					0
-				);
-
-				const transOp = transform( op, transformBy );
-
-				expected.howMany = 1;
-
-				expect( transOp.length ).to.equal( 1 );
-				expectOperation( transOp[ 0 ], expected );
-			} );
-
-			it( 'range intersects on right side of transforming range and is less important: split into two operations', () => {
-				const transformBy = new MoveOperation(
-					new Position( root, [ 2, 2, 5 ] ),
-					2,
-					new Position( root, [ 4, 1, 0 ] ),
-					0
-				);
-
-				const transOp = transform( op, transformBy, strongContext );
-
-				expect( transOp.length ).to.equal( 2 );
-
-				expected.sourcePosition = sourcePosition;
-				expected.howMany = 1;
-
-				expectOperation( transOp[ 0 ], expected );
-
-				expected.sourcePosition = new Position( root, [ 4, 1, 0 ] );
-				expected.targetPosition = targetPosition.getShiftedBy( 1 );
-
-				expectOperation( transOp[ 1 ], expected );
-			} );
-
 			it( 'range intersects, target inside transforming range and is important: split into two operations', () => {
 				op.targetPosition.path = [ 2, 2, 7 ];
 

+ 1 - 1
packages/ckeditor5-engine/tests/model/position.js

@@ -615,7 +615,7 @@ describe( 'Position', () => {
 			expect( positionB.isTouching( positionA ) ).to.be.false;
 		} );
 
-		it( 'should return false if there are whole nodes between positions', () => {
+		it( 'should return false if there are whole nodes between positions (same depth, but deeper)', () => {
 			const positionA = new Position( root, [ 1, 0, 3 ] );
 			const positionB = new Position( root, [ 1, 1, 1 ] );
 

+ 26 - 28
packages/ckeditor5-engine/tests/model/schema.js

@@ -2509,7 +2509,7 @@ describe( 'Schema', () => {
 				expect( schema.checkChild( root1, r1p1 ) ).to.be.true;
 			} );
 
-			it( 'passes $root>paragraph>$text – paragraph inherits allowIn from $block through $block\'s allowWhere', () => {
+			it( 'passes $root>paragraph>$text – paragraph inherits allowed content from $block through $block\'s allowContentOf', () => {
 				schema.register( '$root' );
 				schema.register( '$blockProto' );
 				schema.register( '$block', {
@@ -2525,6 +2525,31 @@ describe( 'Schema', () => {
 
 				expect( schema.checkChild( r1p1, r1p1.getChild( 0 ) ) ).to.be.true;
 			} );
+
+			it( 'passes paragraph[align] – paragraph inherits attributes of $block', () => {
+				schema.register( '$block', {
+					allowAttributes: 'align'
+				} );
+				schema.register( 'paragraph', {
+					inheritAllFrom: '$block'
+				} );
+
+				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.true;
+			} );
+
+			it( 'passes paragraph[align] – paragraph inherits attributes of $block through allowAttributesOf', () => {
+				schema.register( '$blockProto', {
+					allowAttributes: 'align'
+				} );
+				schema.register( '$block', {
+					allowAttributesOf: '$blockProto'
+				} );
+				schema.register( 'paragraph', {
+					inheritAllFrom: '$block'
+				} );
+
+				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.true;
+			} );
 		} );
 
 		// We need to handle cases where some independent features registered definitions which might use
@@ -2669,33 +2694,6 @@ describe( 'Schema', () => {
 			// However, those situations are rather theoretical, so we're not going to waste time on them now.
 		} );
 
-		describe( 'inheritAllFrom', () => {
-			it( 'passes paragraph[align] – paragraph inherits attributes of $block', () => {
-				schema.register( '$block', {
-					allowAttributes: 'align'
-				} );
-				schema.register( 'paragraph', {
-					inheritAllFrom: '$block'
-				} );
-
-				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.true;
-			} );
-
-			it( 'passes paragraph[align] – paragraph inherits attributes of $block through allowAttributesOf', () => {
-				schema.register( '$blockProto', {
-					allowAttributes: 'align'
-				} );
-				schema.register( '$block', {
-					allowAttributesOf: '$blockProto'
-				} );
-				schema.register( 'paragraph', {
-					inheritAllFrom: '$block'
-				} );
-
-				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.true;
-			} );
-		} );
-
 		describe( 'missing attribute definitions', () => {
 			it( 'does not crash when checking an attribute of a non-registered element', () => {
 				expect( schema.checkAttribute( r1p1, 'align' ) ).to.be.false;

+ 5 - 15
packages/ckeditor5-engine/tests/model/selection.js

@@ -143,7 +143,12 @@ describe( 'Selection', () => {
 			expect( selection.is( 'model' ) ).to.be.false;
 			expect( selection.is( 'model:node' ) ).to.be.false;
 			expect( selection.is( '$text' ) ).to.be.false;
+			expect( selection.is( '$textProxy' ) ).to.be.false;
+			expect( selection.is( 'element' ) ).to.be.false;
 			expect( selection.is( 'element', 'paragraph' ) ).to.be.false;
+			expect( selection.is( 'documentSelection' ) ).to.be.false;
+			expect( selection.is( 'node' ) ).to.be.false;
+			expect( selection.is( 'rootElement' ) ).to.be.false;
 		} );
 	} );
 
@@ -826,21 +831,6 @@ describe( 'Selection', () => {
 		} );
 	} );
 
-	describe( 'is()', () => {
-		it( 'should return true for selection', () => {
-			expect( selection.is( 'selection' ) ).to.be.true;
-		} );
-
-		it( 'should return false for other values', () => {
-			expect( selection.is( 'documentSelection' ) ).to.be.false;
-			expect( selection.is( 'node' ) ).to.be.false;
-			expect( selection.is( '$text' ) ).to.be.false;
-			expect( selection.is( '$textProxy' ) ).to.be.false;
-			expect( selection.is( 'element' ) ).to.be.false;
-			expect( selection.is( 'rootElement' ) ).to.be.false;
-		} );
-	} );
-
 	describe( 'setTo - used to collapse at start', () => {
 		it( 'should collapse to start position and fire change event', () => {
 			selection.setTo( [ range2, range1, range3 ] );

+ 2 - 2
packages/ckeditor5-engine/tests/tickets/ckeditor5-692.js

@@ -41,7 +41,7 @@ describe( 'Bug ckeditor5#692', () => {
 
 	describe( 'DomConverter', () => {
 		// https://github.com/ckeditor/ckeditor5/issues/692 Scenario 1.
-		it( 'should handle space after inline filler at the end of container', () => {
+		it( 'should handle space after inline filler at the end of container (scenario 1)', () => {
 			setModelData( editor.model, '<paragraph>foo[]</paragraph>' );
 
 			// Create Bold attribute at the end of paragraph.
@@ -63,7 +63,7 @@ describe( 'Bug ckeditor5#692', () => {
 		} );
 
 		// https://github.com/ckeditor/ckeditor5/issues/692 Scenario 2.
-		it( 'should handle space after inline filler at the end of container', () => {
+		it( 'should handle space after inline filler at the end of container (scenario 2)', () => {
 			setModelData( editor.model, '<paragraph>[]foo</paragraph>' );
 
 			// Create Bold attribute at the end of paragraph.

+ 0 - 16
packages/ckeditor5-engine/tests/view/documentselection.js

@@ -80,16 +80,6 @@ describe( 'DocumentSelection', () => {
 			expect( selection.isBackward ).to.be.false;
 		} );
 
-		it( 'should be able to create a collapsed selection at the given position', () => {
-			const position = range1.start;
-			const selection = new DocumentSelection( position );
-
-			expect( Array.from( selection.getRanges() ).length ).to.equal( 1 );
-			expect( selection.getFirstRange().start ).to.deep.equal( position );
-			expect( selection.getFirstRange().end ).to.deep.equal( position );
-			expect( selection.isBackward ).to.be.false;
-		} );
-
 		it( 'should be able to create a selection from the other document selection', () => {
 			const otherSelection = new DocumentSelection( [ range2, range3 ], { backward: true } );
 			const selection = new DocumentSelection( otherSelection );
@@ -553,12 +543,6 @@ describe( 'DocumentSelection', () => {
 			expect( documentSelection.isEqual( otherSelection ) ).to.be.false;
 		} );
 
-		it( 'should return false if one selection is fake', () => {
-			const otherSelection = new DocumentSelection( null, { fake: true } );
-
-			expect( documentSelection.isEqual( otherSelection ) ).to.be.false;
-		} );
-
 		it( 'should return true if both selection are fake - DocumentSelection and Selection', () => {
 			const otherSelection = new Selection( range1, { fake: true } );
 			documentSelection._setTo( range1, { fake: true } );

+ 58 - 58
packages/ckeditor5-engine/tests/view/domconverter/dom-to-view.js

@@ -421,7 +421,7 @@ describe( 'DomConverter', () => {
 				expect( viewDiv.getChild( 0 ).getChild( 0 ).data ).to.equal( 'f o o' );
 			} );
 
-			function test( inputTexts, output ) {
+			function testTexts( inputTexts, output ) {
 				if ( typeof inputTexts == 'string' ) {
 					inputTexts = [ inputTexts ];
 				}
@@ -446,75 +446,75 @@ describe( 'DomConverter', () => {
 			}
 
 			// At the beginning.
-			test( '_x', ' x' );
-			test( '_ x', '  x' );
-			test( '_ _x', '   x' );
-			test( '_ _ x', '    x' );
+			testTexts( '_x', ' x' );
+			testTexts( '_ x', '  x' );
+			testTexts( '_ _x', '   x' );
+			testTexts( '_ _ x', '    x' );
 
 			// At the end.
-			test( 'x_', 'x ' );
-			test( 'x _', 'x  ' );
-			test( 'x __', 'x   ' );
-			test( 'x _ _', 'x    ' );
+			testTexts( 'x_', 'x ' );
+			testTexts( 'x _', 'x  ' );
+			testTexts( 'x __', 'x   ' );
+			testTexts( 'x _ _', 'x    ' );
 
 			// In the middle.
-			test( 'x x', 'x x' );
-			test( 'x _x', 'x  x' );
-			test( 'x _ x', 'x   x' );
-			test( 'x _ _x', 'x    x' );
+			testTexts( 'x x', 'x x' );
+			testTexts( 'x _x', 'x  x' );
+			testTexts( 'x _ x', 'x   x' );
+			testTexts( 'x _ _x', 'x    x' );
 
 			// Complex.
-			test( '_x_', ' x ' );
-			test( '_ x _x _', '  x  x  ' );
-			test( '_ _x x _', '   x x  ' );
-			test( '_ _x x __', '   x x   ' );
-			test( '_ _x _ _x_', '   x    x ' );
-			test( '_', ' ' );
+			testTexts( '_x_', ' x ' );
+			testTexts( '_ x _x _', '  x  x  ' );
+			testTexts( '_ _x x _', '   x x  ' );
+			testTexts( '_ _x x __', '   x x   ' );
+			testTexts( '_ _x _ _x_', '   x    x ' );
+			testTexts( '_', ' ' );
 
 			// With hard &nbsp;
-			test( '_x', ' x' );
-			test( '__x', ' _x' );
-			test( '___x', ' __x' );
-			test( '__ x', ' _ x' );
-
-			test( 'x_', 'x ' );
-			test( 'x__', 'x_ ' );
-			test( 'x___', 'x__ ' );
-
-			test( 'x_x', 'x_x' );
-			test( 'x___x', 'x___x' );
-			test( 'x____x', 'x____x' );
-			test( 'x__ x', 'x__ x' );
-			test( 'x___ x', 'x___ x' );
-			test( 'x_ _x', 'x_  x' );
-			test( 'x __x', 'x  _x' );
-			test( 'x _ x', 'x   x' );
-			test( 'x __ _x', 'x  _  x' );
+			testTexts( '_x', ' x' );
+			testTexts( '__x', ' _x' );
+			testTexts( '___x', ' __x' );
+			testTexts( '__ x', ' _ x' );
+
+			testTexts( 'x_', 'x ' );
+			testTexts( 'x__', 'x_ ' );
+			testTexts( 'x___', 'x__ ' );
+
+			testTexts( 'x_x', 'x_x' );
+			testTexts( 'x___x', 'x___x' );
+			testTexts( 'x____x', 'x____x' );
+			testTexts( 'x__ x', 'x__ x' );
+			testTexts( 'x___ x', 'x___ x' );
+			testTexts( 'x_ _x', 'x_  x' );
+			testTexts( 'x __x', 'x  _x' );
+			testTexts( 'x _ x', 'x   x' );
+			testTexts( 'x __ _x', 'x  _  x' );
 
 			// Two text nodes.
-			test( [ 'x', 'y' ], 'xy' );
-			test( [ 'x ', 'y' ], 'x y' );
-			test( [ 'x _', 'y' ], 'x  y' );
-			test( [ 'x __', 'y' ], 'x   y' );
-			test( [ 'x _  _', 'y' ], 'x    y' );
-
-			test( [ 'x', ' y' ], 'x y' );
-			test( [ 'x_', ' y' ], 'x  y' );
-			test( [ 'x _', ' y' ], 'x   y' );
-			test( [ 'x __', ' y' ], 'x    y' );
-			test( [ 'x _ _', ' y' ], 'x     y' );
-
-			test( [ 'x', ' _y' ], 'x  y' );
-			test( [ 'x_', ' _y' ], 'x   y' );
-			test( [ 'x _', ' _y' ], 'x    y' );
-			test( [ 'x __', ' _y' ], 'x     y' );
-			test( [ 'x _ _', ' _y' ], 'x      y' );
+			testTexts( [ 'x', 'y' ], 'xy' );
+			testTexts( [ 'x ', 'y' ], 'x y' );
+			testTexts( [ 'x _', 'y' ], 'x  y' );
+			testTexts( [ 'x __', 'y' ], 'x   y' );
+			testTexts( [ 'x _  _', 'y' ], 'x    y' );
+
+			testTexts( [ 'x', ' y' ], 'x y' );
+			testTexts( [ 'x_', ' y' ], 'x  y' );
+			testTexts( [ 'x _', ' y' ], 'x   y' );
+			testTexts( [ 'x __', ' y' ], 'x    y' );
+			testTexts( [ 'x _ _', ' y' ], 'x     y' );
+
+			testTexts( [ 'x', ' _y' ], 'x  y' );
+			testTexts( [ 'x_', ' _y' ], 'x   y' );
+			testTexts( [ 'x _', ' _y' ], 'x    y' );
+			testTexts( [ 'x __', ' _y' ], 'x     y' );
+			testTexts( [ 'x _ _', ' _y' ], 'x      y' );
 
 			// Some tests with hard &nbsp;
-			test( [ 'x', '_y' ], 'x_y' );
-			test( [ 'x_', 'y' ], 'x_y' );
-			test( [ 'x__', ' y' ], 'x_  y' );
-			test( [ 'x_ _', ' y' ], 'x_   y' );
+			testTexts( [ 'x', '_y' ], 'x_y' );
+			testTexts( [ 'x_', 'y' ], 'x_y' );
+			testTexts( [ 'x__', ' y' ], 'x_  y' );
+			testTexts( [ 'x_ _', ' y' ], 'x_   y' );
 
 			it( 'not in preformatted blocks', () => {
 				const domDiv = createElement( document, 'div', {}, [

+ 1 - 1
packages/ckeditor5-engine/tests/view/node.js

@@ -214,7 +214,7 @@ describe( 'Node', () => {
 		} );
 	} );
 
-	describe( 'getIndex()', () => {
+	describe( '#index getter', () => {
 		it( 'should return null if the parent is null', () => {
 			expect( root.index ).to.be.null;
 		} );

+ 0 - 10
packages/ckeditor5-engine/tests/view/selection.js

@@ -82,16 +82,6 @@ describe( 'Selection', () => {
 			expect( selection.isBackward ).to.be.false;
 		} );
 
-		it( 'should be able to create a collapsed selection at the given position', () => {
-			const position = range1.start;
-			const selection = new Selection( position );
-
-			expect( Array.from( selection.getRanges() ).length ).to.equal( 1 );
-			expect( selection.getFirstRange().start ).to.deep.equal( position );
-			expect( selection.getFirstRange().end ).to.deep.equal( position );
-			expect( selection.isBackward ).to.be.false;
-		} );
-
 		it( 'should be able to create a selection from the other selection', () => {
 			const otherSelection = new Selection( [ range2, range3 ], { backward: true } );
 			const selection = new Selection( otherSelection );

+ 0 - 9
packages/ckeditor5-engine/tests/view/styles/utils.js

@@ -232,15 +232,6 @@ describe( 'Styles utils', () => {
 			} );
 		} );
 
-		it( 'should parse one value', () => {
-			expect( getBoxSidesValues( 'foo' ) ).to.deep.equal( {
-				top: 'foo',
-				right: 'foo',
-				bottom: 'foo',
-				left: 'foo'
-			} );
-		} );
-
 		it( 'should parse two value', () => {
 			expect( getBoxSidesValues( 'foo bar' ) ).to.deep.equal( {
 				top: 'foo',

+ 1 - 1
packages/ckeditor5-font/src/ui/colorui.js

@@ -75,7 +75,7 @@ export default class ColorUI extends Plugin {
 		 *
 		 * @member {module:font/ui/colortableview~ColorTableView}
 		 */
-		this.colorTableView;
+		this.colorTableView = undefined;
 	}
 
 	/**

+ 1 - 1
packages/ckeditor5-image/src/imageupload/ui/imageuploadpanelview.js

@@ -218,7 +218,7 @@ export default class ImageUploadPanelView extends View {
 	/**
 	 * Returns a view of the integration.
 	 *
-	 * @param {string} name The name of the integration.
+	 * @param {String} name The name of the integration.
 	 * @returns {module:ui/view~View}
 	 */
 	getIntegration( name ) {

+ 20 - 11
packages/ckeditor5-link/src/linkui.js

@@ -589,18 +589,27 @@ export default class LinkUI extends Plugin {
 		const view = this.editor.editing.view;
 		const model = this.editor.model;
 		const viewDocument = view.document;
-		const targetLink = this._getSelectedLinkElement();
-		const range = model.markers.has( VISUAL_SELECTION_MARKER_NAME ) ?
+		let target = null;
+
+		if ( model.markers.has( VISUAL_SELECTION_MARKER_NAME ) ) {
 			// There are cases when we highlight selection using a marker (#7705, #4721).
-			this.editor.editing.mapper.toViewRange( model.markers.get( VISUAL_SELECTION_MARKER_NAME ).getRange() ) :
-			// If no markers are available refer to a regular selection.
-			viewDocument.selection.getFirstRange();
-
-		const target = targetLink ?
-			// When selection is inside link element, then attach panel to this element.
-			view.domConverter.mapViewToDom( targetLink ) :
-			// Otherwise attach panel to the selection.
-			view.domConverter.viewRangeToDom( range );
+			const markerViewElements = Array.from( this.editor.editing.mapper.markerNameToElements( VISUAL_SELECTION_MARKER_NAME ) );
+			const newRange = view.createRange(
+				view.createPositionBefore( markerViewElements[ 0 ] ),
+				view.createPositionAfter( markerViewElements[ markerViewElements.length - 1 ] )
+			);
+
+			target = view.domConverter.viewRangeToDom( newRange );
+		} else {
+			const targetLink = this._getSelectedLinkElement();
+			const range = viewDocument.selection.getFirstRange();
+
+			target = targetLink ?
+				// When selection is inside link element, then attach panel to this element.
+				view.domConverter.mapViewToDom( targetLink ) :
+				// Otherwise attach panel to the selection.
+				view.domConverter.viewRangeToDom( range );
+		}
 
 		return { target };
 	}

+ 36 - 24
packages/ckeditor5-link/tests/linkui.js

@@ -7,6 +7,8 @@
 
 import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
+import indexOf from '@ckeditor/ckeditor5-utils/src/dom/indexof';
+import isRange from '@ckeditor/ckeditor5-utils/src/dom/isrange';
 import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
 import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
@@ -134,49 +136,37 @@ describe( 'LinkUI', () => {
 
 		it( 'should add #formView to the balloon and attach the balloon to the selection when text fragment is selected', () => {
 			setModelData( editor.model, '<paragraph>f[o]o</paragraph>' );
-			const selectedRange = editorElement.ownerDocument.getSelection().getRangeAt( 0 );
 
 			linkUIFeature._showUI();
 
+			const expectedRange = getMarkersRange( editor );
+
 			expect( balloon.visibleView ).to.equal( formView );
 			sinon.assert.calledWithExactly( balloonAddSpy, {
 				view: formView,
 				position: {
-					target: selectedRange
+					target: sinon.match( isRange )
 				}
 			} );
+
+			assertDomRange( expectedRange, balloonAddSpy.args[ 0 ][ 0 ].position.target );
 		} );
 
-		it( 'should add #formView to the balloon and attach the balloon to the selection when selection is collapsed', () => {
+		it( 'should add #formView to the balloon and attach the balloon to the marker element when selection is collapsed', () => {
+			// (#7926)
 			setModelData( editor.model, '<paragraph>f[]oo</paragraph>' );
-			const selectedRange = editorElement.ownerDocument.getSelection().getRangeAt( 0 );
-
 			linkUIFeature._showUI();
 
+			const expectedRange = getMarkersRange( editor );
+
 			expect( balloon.visibleView ).to.equal( formView );
 			sinon.assert.calledWithExactly( balloonAddSpy, {
 				view: formView,
 				position: {
-					target: selectedRange
+					target: sinon.match( isRange )
 				}
 			} );
-		} );
-
-		it( 'should pass a proper position target to the balloon toolbar', () => {
-			setModelData( editor.model, '<paragraph>f[o]o</paragraph>' );
-
-			linkUIFeature._showUI();
-
-			const markerModelRange = editor.model.markers.get( 'link-ui' ).getRange();
-			const markerViewRange = editor.editing.mapper.toViewRange( markerModelRange );
-			const domRange = editor.editing.view.domConverter.viewRangeToDom( markerViewRange );
-
-			expect( balloonAddSpy.calledWithExactly( {
-				view: formView,
-				position: {
-					target: domRange
-				}
-			} ), 'spy arguments' ).to.be.true;
+			assertDomRange( expectedRange, balloonAddSpy.args[ 0 ][ 0 ].position.target );
 		} );
 
 		it( 'should add #actionsView to the balloon and attach the balloon to the link element when collapsed selection is inside ' +
@@ -380,10 +370,14 @@ describe( 'LinkUI', () => {
 					writer.setSelection( text, 1, true );
 				} );
 
+				const expectedRange = getMarkersRange( editor );
+
 				sinon.assert.calledOnce( spy );
 				sinon.assert.calledWithExactly( spy, {
-					target: editorElement.ownerDocument.getSelection().getRangeAt( 0 )
+					target: sinon.match( isRange )
 				} );
+
+				assertDomRange( expectedRange, spy.args[ 0 ][ 0 ].target );
 			} );
 
 			it( 'not update the position when is in not visible stack', () => {
@@ -524,6 +518,24 @@ describe( 'LinkUI', () => {
 			);
 			expect( editor.getData() ).to.equal( '<p>fo</p>' );
 		} );
+
+		function getMarkersRange( editor ) {
+			const markerElements = editor.ui.view.element.querySelectorAll( '.ck-fake-link-selection' );
+			const lastMarkerElement = markerElements[ markerElements.length - 1 ];
+
+			const range = document.createRange();
+			range.setStart( markerElements[ 0 ].parentElement, indexOf( markerElements[ 0 ] ) );
+			range.setEnd( lastMarkerElement.parentElement, indexOf( lastMarkerElement ) + 1 );
+
+			return range;
+		}
+
+		function assertDomRange( expected, actual ) {
+			expect( actual, 'startContainer' ).to.have.property( 'startContainer', expected.startContainer );
+			expect( actual, 'startOffset' ).to.have.property( 'startOffset', expected.startOffset );
+			expect( actual, 'endContainer' ).to.have.property( 'endContainer', expected.endContainer );
+			expect( actual, 'endOffset' ).to.have.property( 'endOffset', expected.endOffset );
+		}
 	} );
 
 	describe( '_hideUI()', () => {

+ 10 - 12
packages/ckeditor5-list/docs/_snippets/features/lists-basic.html

@@ -1,20 +1,18 @@
 <div id="snippet-lists-basic">
-    <h2>Unordered list</h2>
-    <p>Such a list can represent items where the order is not important, e.g. a list of ingredients required for preparing a dish or a drink.</p>
+    <h2>Ingredients</h2>
     <p>Ingredients required for making a coffee:</p>
     <ul>
-        <li>15g coffee ground</li>
-        <li>a cup</li>
+        <li>15g ground coffee</li>
         <li>water</li>
+        <li>milk <i>(optional)</i></li>
     </ul>
-    <h2>Ordered list</h2>
-    <p>The ordered list can be used if the order of the items matters, e.g. when describing an instruction. The order of steps that must be done is important.</p>
-    <p>How to prepare the coffee?</p>
+    <h2>Instructions</h2>
+    <p>How to prepare a cup of coffee:</p>
     <ol>
-        <li>Gather the ingredients</li>
-        <li>Put 15g of the coffee ground into the cup</li>
-        <li>Boil 200ml of water</li>
-        <li>Pour water into a cup</li>
-        <li>Optional: add milk as you wish</li>
+        <li>Gather the ingredients.</li>
+        <li>Put 15g of ground coffee in the cup.</li>
+        <li>Boil 200ml of water.</li>
+        <li>Pour the water into the cup.</li>
+        <li>Optional: Add milk.</li>
     </ol>
 </div>

+ 10 - 9
packages/ckeditor5-list/docs/_snippets/features/lists-style.html

@@ -1,17 +1,18 @@
 <div id="snippet-lists-styles">
-    <p>Let's use the coffee recipe from the demo in section <a href="#demo">Ordered and unordered lists</a> and use the list styles feature.</p>
+    <h2>Ingredients</h2>
     <p>Ingredients required for making a coffee:</p>
     <ul style="list-style-type:circle;">
-        <li>15g coffee ground</li>
-        <li>a cup</li>
+        <li>15g ground coffee</li>
         <li>water</li>
+        <li>milk <i>(optional)</i></li>
     </ul>
-    <p>How to prepare the coffee?</p>
+    <h2>Instructions</h2>
+    <p>How to prepare a cup of coffee:</p>
     <ol style="list-style-type:decimal-leading-zero;">
-        <li>Gather the ingredients</li>
-        <li>Put 15g of the coffee ground into the cup</li>
-        <li>Boil 200ml of water</li>
-        <li>Pour water into a cup</li>
-        <li>Optional: add milk as you wish</li>
+        <li>Gather the ingredients.</li>
+        <li>Put 15g of ground coffee in the cup.</li>
+        <li>Boil 200ml of water.</li>
+        <li>Pour the water into the cup.</li>
+        <li>Optional: Add milk.</li>
     </ol>
 </div>

+ 3 - 3
packages/ckeditor5-list/docs/api/list.md

@@ -6,15 +6,15 @@ category: api-reference
 
 [![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-list.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-list)
 
-This package implements bulleted, numbered and to-do list feature for CKEditor 5.
+This package implements bulleted, numbered and to-do list features for CKEditor 5.
 
 ## Documentation
 
-See the {@link module:list/list~List} plugin documentation and {@link features/todo-lists to-do list feature} guide.
+See the {@link module:list/list~List} plugin documentation as well as the {@link features/lists lists} and {@link features/todo-lists to-do list} feature guides.
 
 ## Installation
 
-```bash
+```
 npm install --save @ckeditor/ckeditor5-list
 ```
 

+ 17 - 9
packages/ckeditor5-list/docs/features/lists.md

@@ -4,7 +4,7 @@ category: features
 
 # Lists
 
-The {@link module:list/list~List list} feature allows creating ordered and unordered lists in the editor.
+The {@link module:list/list~List list} feature allows creating ordered (numbered) and unordered (bulleted) lists in the editor.
 
 <info-box info>
 	The feature is enabled by default in all CKEditor 5 WYSIWYG editor builds.
@@ -14,6 +14,10 @@ The {@link module:list/list~List list} feature allows creating ordered and unord
 
 ## Ordered and unordered lists
 
+An unordered (bulleted) list can represent items where the order is not important, for example, a list of ingredients required for preparing a dish or a drink.
+
+An ordered (numbered) list can be used if the order of the items matters, for example, when creating an instruction. Here, the sequence of steps that must be done is important.
+
 Use the editor below to see the list feature plugin in action.
 
 ### Demo
@@ -22,11 +26,11 @@ Use the editor below to see the list feature plugin in action.
 
 ## List styles
 
-The {@link module:list/liststyle~ListStyle list styles} feature allows customizing the list's marker.
+The {@link module:list/liststyle~ListStyle list style} feature allows customizing the list item markers. When enabled, it adds 3 styles for unordered lists and 6 styles for ordered lists to choose from. The styles can be changed via the dropdown that opens when you click the arrow next to the appropriate list button in the toolbar.
 
 ### Demo
 
-Use the editor below to see the list styles feature plugin in action.
+Use the editor below to see the list style plugin in action.
 
 {@snippet features/lists-style}
 
@@ -34,7 +38,7 @@ Use the editor below to see the list styles feature plugin in action.
 
 To add this feature to your editor, install the [`@ckeditor/ckeditor5-list`](https://www.npmjs.com/package/@ckeditor/ckeditor5-list) package:
 
-```bash
+```
 npm install --save @ckeditor/ckeditor5-list
 ```
 
@@ -60,6 +64,10 @@ ClassicEditor
 	The {@link module:list/liststyle~ListStyle} feature overrides UI button implementations from the {@link module:list/listui~ListUI}.
 </info-box>
 
+## List indentation
+
+Refer to the {@link features/indent Indenting lists} section of the Block indentation feature guide.
+
 ## To-do list
 
 You can read more about the feature in the {@link features/todo-lists To-do lists} feature guide.
@@ -72,12 +80,12 @@ The {@link module:list/list~List} plugin registers:
 * The {@link module:list/listcommand~ListCommand `'bulletedList'`} command.
 * The {@link module:list/indentcommand~IndentCommand `'indentList'`} command.
 * The {@link module:list/indentcommand~IndentCommand `'outdentList'`} command.
-* The `'numberedList'` ui button.
-* The `'bulletedList'` ui button.
+* The `'numberedList'` UI button.
+* The `'bulletedList'` UI button.
 
 The {@link module:list/liststyle~ListStyle} plugin registers:
 
-* The {@link module:list/liststylecommand~ListStyleCommand `'listStyle'`} command that accepts a `type` of a list style to set.
+* The {@link module:list/liststylecommand~ListStyleCommand `'listStyle'`} command that accepts a `type` of the list style to set.
     ```js
     editor.execute( 'listStyle', { type: 'decimal' } );
     ```
@@ -85,8 +93,8 @@ The {@link module:list/liststyle~ListStyle} plugin registers:
 
     * For bulleted lists: `'disc'`, `'circle'`, and `'square'`.
     * For numbered lists: `'decimal'`, `'decimal-leading-zero'`, `'lower-roman'`, `'upper-roman'`, `'lower-latin'`, and `'upper-latin'`.
-* The `'numberedList'` ui split button (it overrides UI button registered by the `List` plguin.
-* The `'bulletedList'` ui split button (it overrides UI button registered by the `List` plguin.
+* The `'numberedList'` UI split button (it overrides the UI button registered by the `List` plguin.
+* The `'bulletedList'` UI split button (it overrides the UI button registered by the `List` plguin.
 
 ## Contribute
 

+ 2 - 2
packages/ckeditor5-list/docs/features/todo-lists.md

@@ -4,7 +4,7 @@ category: features
 
 # To-do lists
 
-The {@link module:list/todolist~TodoList to-do list} feature lets you create a list of interactive checkboxes with labels. It supports all features of regular lists so you can nest a to-do list together with bulleted and numbered lists in any combination.
+The {@link module:list/todolist~TodoList to-do list} feature lets you create a list of interactive checkboxes with labels. It supports all features of regular lists so you can nest a to-do list together with {@link features/lists bulleted and numbered lists} in any combination.
 
 ## Demo
 
@@ -90,7 +90,7 @@ From the technical point of view, to-do lists are built on top of the {@link mod
 
 ## Ordered and unordered lists
 
-You can read more about those features in the {@link features/lists Lists} feature guide.
+You can read more about these features in the {@link features/lists Lists} feature guide.
 
 ## Contribute
 

+ 48 - 41
packages/ckeditor5-list/src/liststyleediting.js

@@ -189,7 +189,6 @@ export default class ListStyleEditing extends Plugin {
 // Returns a converter that consumes the `style` attribute and search for `list-style-type` definition.
 // If not found, the `"default"` value will be used.
 //
-// @private
 // @returns {Function}
 function upcastListItemStyle() {
 	return dispatcher => {
@@ -206,7 +205,6 @@ function upcastListItemStyle() {
 // Returns a converter that adds the `list-style-type` definition as a value for the `style` attribute.
 // The `"default"` value is removed and not present in the view/data.
 //
-// @private
 // @returns {Function}
 function downcastListStyleAttribute() {
 	return dispatcher => {
@@ -271,7 +269,6 @@ function downcastListStyleAttribute() {
 //     ○ List item 2.[]
 // ■ List item 3.
 //
-// @private
 // @param {module:core/editor/editor~Editor} editor
 // @returns {Function}
 function fixListAfterIndentListCommand( editor ) {
@@ -323,7 +320,6 @@ function fixListAfterIndentListCommand( editor ) {
 // ■ List item 2.[]
 // ■ List item 3.
 //
-// @private
 // @param {module:core/editor/editor~Editor} editor
 // @returns {Function}
 function fixListAfterOutdentListCommand( editor ) {
@@ -423,22 +419,17 @@ function fixListAfterOutdentListCommand( editor ) {
 // ■ List item 2.  // ...
 // ■ List item 3.  // ...
 //
-// @private
 // @param {module:core/editor/editor~Editor} editor
 // @returns {Function}
 function fixListStyleAttributeOnListItemElements( editor ) {
 	return writer => {
 		let wasFixed = false;
-		let insertedListItems = [];
 
-		for ( const change of editor.model.document.differ.getChanges() ) {
-			if ( change.type == 'insert' && change.name == 'listItem' ) {
-				insertedListItems.push( change.position.nodeAfter );
-			}
-		}
-
-		// Don't touch todo lists.
-		insertedListItems = insertedListItems.filter( item => item.getAttribute( 'listType' ) !== 'todo' );
+		const insertedListItems = getChangedListItems( editor.model.document.differ.getChanges() )
+			.filter( item => {
+				// Don't touch todo lists. They are handled in another post-fixer.
+				return item.getAttribute( 'listType' ) !== 'todo';
+			} );
 
 		if ( !insertedListItems.length ) {
 			return wasFixed;
@@ -474,7 +465,7 @@ function fixListStyleAttributeOnListItemElements( editor ) {
 
 		for ( const item of insertedListItems ) {
 			if ( !item.hasAttribute( 'listStyle' ) ) {
-				if ( shouldInheritListType( existingListItem ) ) {
+				if ( shouldInheritListType( existingListItem, item ) ) {
 					writer.setAttribute( 'listStyle', existingListItem.getAttribute( 'listStyle' ), item );
 				} else {
 					writer.setAttribute( 'listStyle', DEFAULT_LIST_TYPE, item );
@@ -493,8 +484,9 @@ function fixListStyleAttributeOnListItemElements( editor ) {
 	// the value for the element is other than default in the base element.
 	//
 	// @param {module:engine/model/element~Element|null} baseItem
+	// @param {module:engine/model/element~Element} itemToChange
 	// @returns {Boolean}
-	function shouldInheritListType( baseItem ) {
+	function shouldInheritListType( baseItem, itemToChange ) {
 		if ( !baseItem ) {
 			return false;
 		}
@@ -509,28 +501,25 @@ function fixListStyleAttributeOnListItemElements( editor ) {
 			return false;
 		}
 
+		if ( baseItem.getAttribute( 'listType' ) !== itemToChange.getAttribute( 'listType' ) ) {
+			return false;
+		}
+
 		return true;
 	}
 }
 
 // Removes the `listStyle` attribute from "todo" list items.
 //
-// @private
 // @param {module:core/editor/editor~Editor} editor
 // @returns {Function}
 function removeListStyleAttributeFromTodoList( editor ) {
 	return writer => {
-		let todoListItems = [];
-
-		for ( const change of editor.model.document.differ.getChanges() ) {
-			const item = getItemFromChange( change );
-
-			if ( item && item.is( 'element', 'listItem' ) && item.getAttribute( 'listType' ) === 'todo' ) {
-				todoListItems.push( item );
-			}
-		}
-
-		todoListItems = todoListItems.filter( item => item.hasAttribute( 'listStyle' ) );
+		const todoListItems = getChangedListItems( editor.model.document.differ.getChanges() )
+			.filter( item => {
+				// Handle the todo lists only. The rest is handled in another post-fixer.
+				return item.getAttribute( 'listType' ) === 'todo' && item.hasAttribute( 'listStyle' );
+			} );
 
 		if ( !todoListItems.length ) {
 			return false;
@@ -542,23 +531,10 @@ function removeListStyleAttributeFromTodoList( editor ) {
 
 		return true;
 	};
-
-	function getItemFromChange( change ) {
-		if ( change.type === 'attribute' ) {
-			return change.range.start.nodeAfter;
-		}
-
-		if ( change.type === 'insert' ) {
-			return change.position.nodeAfter;
-		}
-
-		return null;
-	}
 }
 
 // Restores the `listStyle` attribute after changing the list type.
 //
-// @private
 // @param {module:core/editor/editor~Editor} editor
 // @returns {Function}
 function restoreDefaultListStyle( editor ) {
@@ -573,3 +549,34 @@ function restoreDefaultListStyle( editor ) {
 		} );
 	};
 }
+
+// Returns `listItem` that were inserted or changed.
+//
+// @param {Array.<Object>} changes The changes list returned by the differ.
+// @returns {Array.<module:engine/model/element~Element>}
+function getChangedListItems( changes ) {
+	const items = [];
+
+	for ( const change of changes ) {
+		const item = getItemFromChange( change );
+
+		if ( item && item.is( 'element', 'listItem' ) ) {
+			items.push( item );
+		}
+	}
+
+	return items;
+}
+
+function getItemFromChange( change ) {
+	if ( change.type === 'attribute' ) {
+		return change.range.start.nodeAfter;
+	}
+
+	if ( change.type === 'insert' ) {
+		return change.position.nodeAfter;
+	}
+
+	return null;
+}
+

+ 3 - 15
packages/ckeditor5-list/tests/listediting.js

@@ -175,7 +175,7 @@ describe( 'ListEditing', () => {
 	} );
 
 	describe( 'delete key handling callback', () => {
-		it( 'should execute outdentList command on backspace key in first item of list', () => {
+		it( 'should execute outdentList command on backspace key in first item of list (first node in root)', () => {
 			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };
 
 			sinon.spy( editor, 'execute' );
@@ -187,7 +187,7 @@ describe( 'ListEditing', () => {
 			sinon.assert.calledWithExactly( editor.execute, 'outdentList' );
 		} );
 
-		it( 'should execute outdentList command on backspace key in first item of list', () => {
+		it( 'should execute outdentList command on backspace key in first item of list (after a paragraph)', () => {
 			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };
 
 			sinon.spy( editor, 'execute' );
@@ -262,18 +262,6 @@ describe( 'ListEditing', () => {
 			sinon.assert.notCalled( editor.execute );
 		} );
 
-		it( 'should not execute outdentList command when selection is not on first position', () => {
-			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };
-
-			sinon.spy( editor, 'execute' );
-
-			setModelData( model, '<listItem listType="bulleted" listIndent="0">fo[]o</listItem>' );
-
-			editor.editing.view.document.fire( 'delete', domEvtDataStub );
-
-			sinon.assert.notCalled( editor.execute );
-		} );
-
 		it( 'should outdent list when previous element is nested in block quote', () => {
 			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };
 
@@ -3985,7 +3973,7 @@ describe( 'ListEditing', () => {
 		} );
 
 		// Just checking that it doesn't crash. #69
-		it( 'should work if an element is passed to DataController#insertContent()', () => {
+		it( 'should work if an element is passed to DataController#insertContent() - case #69', () => {
 			setModelData( model,
 				'<listItem listType="bulleted" listIndent="0">A</listItem>' +
 				'<listItem listType="bulleted" listIndent="1">B[]</listItem>' +

+ 92 - 4
packages/ckeditor5-list/tests/liststyleediting.js

@@ -452,19 +452,38 @@ describe( 'ListStyleEditing', () => {
 			it( 'should not inherit the list style attribute when merging different kind of lists (from top, merge a single item)', () => {
 				setModelData( model,
 					'<paragraph>Foo Bar.[]</paragraph>' +
-					'<listItem listIndent="0" listStyle="default"  listType="numbered">Foo</listItem>' +
-					'<listItem listIndent="0" listStyle="default"  listType="numbered">Bar</listItem>'
+					'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +
+					'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>'
 				);
 
 				editor.execute( 'bulletedList' );
 
 				expect( getModelData( model ) ).to.equal(
 					'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>' +
-					'<listItem listIndent="0" listStyle="default" listType="numbered">Foo</listItem>' +
-					'<listItem listIndent="0" listStyle="default" listType="numbered">Bar</listItem>'
+					'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +
+					'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>'
 				);
 			} );
 
+			it(
+				'should not inherit the list style attribute when merging different kind of lists (from bottom, merge a single item)',
+				() => {
+					setModelData( model,
+						'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +
+						'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>' +
+						'<paragraph>Foo Bar.[]</paragraph>'
+					);
+
+					editor.execute( 'bulletedList' );
+
+					expect( getModelData( model ) ).to.equal(
+						'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +
+						'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>' +
+						'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>'
+					);
+				}
+			);
+
 			it( 'should inherit the list style attribute when merging the same kind of lists (from bottom, merge a single item)', () => {
 				setModelData( model,
 					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
@@ -503,6 +522,75 @@ describe( 'ListStyleEditing', () => {
 			);
 		} );
 
+		describe( 'modifying "listType" attribute', () => {
+			it( 'should inherit the list style attribute when the modified list is the same kind of the list as next sibling', () => {
+				setModelData( model,
+					'<listItem listIndent="0" listStyle="default" listType="numbered">Foo Bar.[]</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
+				);
+
+				editor.execute( 'bulletedList' );
+
+				expect( getModelData( model ) ).to.equal(
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
+				);
+			} );
+
+			it( 'should inherit the list style attribute when the modified list is the same kind of the list as previous sibling', () => {
+				setModelData( model,
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +
+					'<listItem listIndent="0" listStyle="default" listType="numbered">Foo Bar.[]</listItem>'
+				);
+
+				editor.execute( 'bulletedList' );
+
+				expect( getModelData( model ) ).to.equal(
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>'
+				);
+			} );
+
+			it( 'should not inherit the list style attribute when the modified list already has defined it (next sibling check)', () => {
+				setModelData( model,
+					'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
+				);
+
+				editor.execute( 'listStyle', { type: 'disc' } );
+
+				expect( getModelData( model ) ).to.equal(
+					'<listItem listIndent="0" listStyle="disc" listType="bulleted">Foo Bar.[]</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
+					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
+				);
+			} );
+
+			it(
+				'should not inherit the list style attribute when the modified list already has defined it (previous sibling check)',
+				() => {
+					setModelData( model,
+						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
+						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +
+						'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>'
+					);
+
+					editor.execute( 'listStyle', { type: 'disc' } );
+
+					expect( getModelData( model ) ).to.equal(
+						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
+						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +
+						'<listItem listIndent="0" listStyle="disc" listType="bulleted">Foo Bar.[]</listItem>'
+					);
+				}
+			);
+		} );
+
 		describe( 'indenting lists', () => {
 			it( 'should restore the default value for the list style attribute when indenting a single item', () => {
 				setModelData( model,

+ 1 - 1
packages/ckeditor5-list/tests/todolistediting.js

@@ -1180,7 +1180,7 @@ describe( 'TodoListEditing', () => {
 	} );
 } );
 
-describe( 'TodoListEditing', () => {
+describe( 'TodoListEditing - checkbox rendering', () => {
 	let editorElement, editor, model, modelDoc, view, viewDoc, viewRoot;
 
 	beforeEach( () => {

+ 0 - 11
packages/ckeditor5-page-break/tests/pagebreakediting.js

@@ -171,17 +171,6 @@ describe( 'PageBreakEditing', () => {
 					.to.equal( '' );
 			} );
 
-			it( 'should not convert if inner span has wrong styles', () => {
-				editor.setData(
-					'<div class="page-break" style="page-break-after:always;">' +
-					'<span style="display:inline-block;">&nbsp;</span>' +
-					'</div>'
-				);
-
-				expect( getModelData( model, { withoutSelection: true } ) )
-					.to.equal( '' );
-			} );
-
 			it( 'should not convert if inner span has any children', () => {
 				editor.setData(
 					'<div class="page-break" style="page-break-after:always;">' +

+ 1 - 1
packages/ckeditor5-restricted-editing/tests/restrictededitingmodeediting.js

@@ -656,7 +656,7 @@ describe( 'RestrictedEditingModeEditing', () => {
 			assertEqualMarkup( getModelData( model ), '<paragraph>foo b[]ar baz</paragraph>' );
 		} );
 
-		it( 'should prevent changing text before exception marker', () => {
+		it( 'should prevent changing text before exception marker (native spell-check simulation)', () => {
 			addExceptionMarker( 4, 7, firstParagraph );
 
 			model.change( writer => {

+ 2 - 2
packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js

@@ -323,7 +323,7 @@ describe( 'table cell properties', () => {
 					model.change( writer => writer.setAttribute( 'borderStyle', 'ridge', tableCell ) );
 				} );
 
-				it( 'should be overridable', () => {
+				it( 'should be overridable for borderStyle', () => {
 					editor.conversion.for( 'downcast' )
 						.add( dispatcher => dispatcher.on( 'attribute:borderStyle:tableCell', ( evt, data, conversionApi ) => {
 							conversionApi.consumable.consume( data.item, evt.name );
@@ -365,7 +365,7 @@ describe( 'table cell properties', () => {
 					model.change( writer => writer.setAttribute( 'borderWidth', '2px', tableCell ) );
 				} );
 
-				it( 'should be overridable', () => {
+				it( 'should be overridable for borderWidth', () => {
 					editor.conversion.for( 'downcast' )
 						.add( dispatcher => dispatcher.on( 'attribute:borderWidth:tableCell', ( evt, data, conversionApi ) => {
 							conversionApi.consumable.consume( data.item, evt.name );

+ 2 - 2
packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js

@@ -293,7 +293,7 @@ describe( 'table properties', () => {
 					model.change( writer => writer.setAttribute( 'borderStyle', 'solid', table ) );
 				} );
 
-				it( 'should be overridable', () => {
+				it( 'should be overridable for borderStyle', () => {
 					editor.conversion.for( 'downcast' )
 						.add( dispatcher => dispatcher.on( 'attribute:borderStyle:table', ( evt, data, conversionApi ) => {
 							conversionApi.consumable.consume( data.item, evt.name );
@@ -335,7 +335,7 @@ describe( 'table properties', () => {
 					model.change( writer => writer.setAttribute( 'borderWidth', '2px', table ) );
 				} );
 
-				it( 'should be overridable', () => {
+				it( 'should be overridable for borderWidth', () => {
 					editor.conversion.for( 'downcast' )
 						.add( dispatcher => dispatcher.on( 'attribute:borderWidth:table', ( evt, data, conversionApi ) => {
 							conversionApi.consumable.consume( data.item, evt.name );

+ 1 - 1
packages/ckeditor5-ui/tests/toolbar/toolbarview.js

@@ -64,7 +64,7 @@ describe( 'ToolbarView', () => {
 				expect( view.options ).to.deep.equal( {} );
 			} );
 
-			it( 'should be an empty object if none were passed', () => {
+			it( 'should be an empty object if other options were passed', () => {
 				const options = {
 					foo: 'bar'
 				};

+ 0 - 3
packages/ckeditor5-ui/tests/viewcollection.js

@@ -100,9 +100,6 @@ describe( 'ViewCollection', () => {
 					children: collection
 				} );
 
-				// Render view#template along with collection of children.
-				view.element;
-
 				const viewC = getView( 'C' );
 
 				// Modify the collection, while the view#element has already

+ 4 - 4
packages/ckeditor5-utils/tests/config.js

@@ -396,9 +396,8 @@ describe( 'Config', () => {
 
 		it( 'should not be possible to retrieve value directly from config object', () => {
 			expect( config.creator ).to.be.undefined;
-			expect( () => {
-				config.resize.maxHeight;
-			} ).to.throw();
+			// Check if 'resize.maxHeight' would be accessible;
+			expect( config.resize ).to.be.undefined;
 		} );
 
 		it( 'should not be possible to alter config object by altering returned value', () => {
@@ -430,7 +429,8 @@ describe( 'Config', () => {
 		} );
 
 		it( 'should return class & functions references from config array', () => {
-			class Foo {}
+			class Foo {
+			}
 
 			function bar() {
 				return 'bar';

+ 1 - 1
packages/ckeditor5-utils/tests/diff.js

@@ -63,7 +63,7 @@ describe( 'diff', () => {
 		testUtils.sinon.assert.called( fastDiffSpy );
 	} );
 
-	it( 'should use fastDiff() internally for strings with length sum of 2000+', () => {
+	it( 'should use fastDiff() internally for strings with length sum of exaclty 2000', () => {
 		diff( getLongText( 10 ), getLongText( 1990 ) );
 		testUtils.sinon.assert.called( fastDiffSpy );
 	} );

+ 4 - 4
packages/ckeditor5-utils/tests/fastdiff.js

@@ -317,14 +317,14 @@ describe( 'fastDiff', () => {
 				], false );
 			} );
 
-			it( 'should diff insertion of duplicated content', () => {
+			it( 'should diff insertion of duplicated content (case 1)', () => {
 				expectDiff( '1234', '123123', [
 					{ index: 3, type: 'insert', values: [ '1', '2', '3' ] },
 					{ index: 6, type: 'delete', howMany: 1 }
 				], false );
 			} );
 
-			it( 'should diff insertion of duplicated content', () => {
+			it( 'should diff insertion of duplicated content (case 2)', () => {
 				expectDiff( '1234', '13424', [
 					{ index: 1, type: 'insert', values: [ '3', '4', '2' ] },
 					{ index: 4, type: 'delete', howMany: 2 }
@@ -584,11 +584,11 @@ describe( 'fastDiff', () => {
 				expectDiffLinear( '12345', '1231234', 'eeeiiiidd', false );
 			} );
 
-			it( 'should diff insertion of duplicated content', () => {
+			it( 'should diff insertion of duplicated content - case 1', () => {
 				expectDiffLinear( '1234', '123123', 'eeeiiid' );
 			} );
 
-			it( 'should diff insertion of duplicated content', () => {
+			it( 'should diff insertion of duplicated content - case 2', () => {
 				expectDiffLinear( '1234', '13424', 'eiiidde', false );
 			} );
 

+ 0 - 11
packages/ckeditor5-watchdog/tests/utils/areconnectedthroughproperties.js

@@ -285,16 +285,5 @@ describe( 'areConnectedThroughProperties()', () => {
 
 			expect( areConnectedThroughProperties( editor1, editor2 ) ).to.be.false;
 		} );
-
-		it( 'should return false for two different editors sharing builtin plugins', () => {
-			Editor.builtinPlugins = [
-				class Foo {}
-			];
-
-			const editor1 = new Editor();
-			const editor2 = new Editor();
-
-			expect( areConnectedThroughProperties( editor1, editor2 ) ).to.be.false;
-		} );
 	} );
 } );

+ 1 - 1
packages/ckeditor5-word-count/src/wordcount.js

@@ -120,7 +120,7 @@ export default class WordCount extends Plugin {
 		 * @readonly
 		 * @type {module:ui/view~View}
 		 */
-		this._outputView;
+		this._outputView = undefined;
 
 		/**
 		 * A regular expression used to recognize words in the editor's content.

+ 6 - 6
scripts/docs/build-docs.js

@@ -27,12 +27,7 @@ function buildDocs() {
 	if ( skipApi ) {
 		promise = Promise.resolve();
 	} else {
-		promise = buildApiDocs()
-			.catch( err => {
-				console.error( err );
-
-				process.exitCode = 1;
-			} );
+		promise = buildApiDocs();
 	}
 
 	promise
@@ -45,6 +40,11 @@ function buildDocs() {
 				watch,
 				verbose
 			} );
+		} )
+		.catch( err => {
+			console.error( err );
+
+			process.exitCode = 1;
 		} );
 }
 

+ 2 - 1
scripts/docs/buildapi.js

@@ -23,6 +23,7 @@ module.exports = function buildApiDocs() {
 				'!' + process.cwd() + '/external/*/packages/@(ckeditor|ckeditor5)-*/src/lib/**/*.js',
 				'!' + process.cwd() + '/external/*/packages/ckeditor5-build-*/src/**/*.js'
 			],
-			validateOnly: process.argv.includes( '--validate-only' )
+			validateOnly: process.argv.includes( '--validate-only' ),
+			strict: process.argv.includes( '--strict' )
 		} );
 };

+ 16 - 16
scripts/switch-to-dev-dev.sh

@@ -13,42 +13,42 @@ if [ ! -d node_modules/@ckeditor ]; then
   mkdir node_modules/@ckeditor
 fi
 
-echo "Linking ckeditor5-dev-docs..."
+echo "Linking packages from ckeditor5-dev..."
 
+echo "Linking ckeditor5-dev-docs..."
 rm -rf node_modules/@ckeditor/ckeditor5-dev-docs
 ln -s ../../../ckeditor5-dev/packages/ckeditor5-dev-docs node_modules/@ckeditor
 
 echo "Linking ckeditor5-dev-env..."
-
 rm -rf node_modules/@ckeditor/ckeditor5-dev-env
 ln -s ../../../ckeditor5-dev/packages/ckeditor5-dev-env node_modules/@ckeditor
 
 echo "Linking ckeditor5-dev-tests..."
-
 rm -rf node_modules/@ckeditor/ckeditor5-dev-tests
 ln -s ../../../ckeditor5-dev/packages/ckeditor5-dev-tests node_modules/@ckeditor
 
 echo "Linking ckeditor5-dev-utils..."
-
 rm -rf node_modules/@ckeditor/ckeditor5-dev-utils
 ln -s ../../../ckeditor5-dev/packages/ckeditor5-dev-utils node_modules/@ckeditor
 
-echo "Linking eslint-config-ckeditor5..."
-
-rm -rf node_modules/eslint-config-ckeditor5
-ln -s ../../ckeditor5-dev/packages/eslint-config-ckeditor5 node_modules/
-
-echo "Linking stylelint-config-ckeditor5..."
-
-rm -rf node_modules/stylelint-config-ckeditor5
-ln -s ../../ckeditor5-dev/packages/stylelint-config-ckeditor5 node_modules/
-
 echo "Linking jsdoc-plugins..."
-
 rm -rf node_modules/@ckeditor/jsdoc-plugins
 ln -s ../../../ckeditor5-dev/packages/jsdoc-plugins node_modules/@ckeditor
 
 echo "Linking ckeditor5-dev-webpack-plugin..."
-
 rm -rf node_modules/@ckeditor/ckeditor5-dev-webpack-plugin
 ln -s ../../../ckeditor5-dev/packages/ckeditor5-dev-webpack-plugin node_modules/@ckeditor
+
+echo "Linking linters packages..."
+
+echo "Linking eslint-config-ckeditor5..."
+rm -rf node_modules/eslint-config-ckeditor5
+ln -s ../../eslint-config-ckeditor5 node_modules/
+
+echo "Linking eslint-plugin-ckeditor5-rules..."
+rm -rf node_modules/eslint-plugin-ckeditor5-rules
+ln -s ../../eslint-plugin-ckeditor5-rules node_modules/
+
+echo "Linking stylelint-config-ckeditor5..."
+rm -rf node_modules/stylelint-config-ckeditor5
+ln -s ../../stylelint-config-ckeditor5 node_modules/