Browse Source

Merge branch 'release' into stable

Marek Lewandowski 5 years ago
parent
commit
76f979bf94
100 changed files with 763 additions and 420 deletions
  1. 33 0
      .github/workflows/ckeditor5-integrations.yml
  2. 1 1
      .github/workflows/merge-stable.yml
  3. 156 21
      CHANGELOG.md
  4. 6 1
      docs/_snippets/examples/document-editor.js
  5. 1 1
      docs/_snippets/examples/multi-root-editor.html
  6. 3 3
      docs/_snippets/examples/multi-root-editor.js
  7. 24 24
      docs/builds/guides/integration/content-styles.md
  8. 1 1
      docs/builds/guides/migrate.md
  9. 3 2
      docs/framework/guides/contributing/testing-environment.md
  10. 8 6
      docs/framework/guides/support/versioning-policy.md
  11. 63 61
      package.json
  12. 2 2
      packages/ckeditor-cloud-services-core/package.json
  13. 77 18
      packages/ckeditor-cloud-services-core/src/token/token.js
  14. 5 5
      packages/ckeditor-cloud-services-core/src/uploadgateway/fileuploader.js
  15. 2 2
      packages/ckeditor-cloud-services-core/src/uploadgateway/uploadgateway.js
  16. 202 103
      packages/ckeditor-cloud-services-core/tests/token/token.js
  17. 6 2
      packages/ckeditor-cloud-services-core/tests/uploadgateway/fileuploader.js
  18. 4 1
      packages/ckeditor-cloud-services-core/tests/uploadgateway/uploadgateway.js
  19. 13 13
      packages/ckeditor5-adapter-ckfinder/package.json
  20. 13 13
      packages/ckeditor5-alignment/package.json
  21. 14 14
      packages/ckeditor5-autoformat/package.json
  22. 2 2
      packages/ckeditor5-autoformat/tests/autoformat.js
  23. 5 5
      packages/ckeditor5-autosave/package.json
  24. 10 10
      packages/ckeditor5-basic-styles/package.json
  25. 14 14
      packages/ckeditor5-block-quote/package.json
  26. 1 1
      packages/ckeditor5-build-balloon-block/build/ckeditor.js
  27. 1 1
      packages/ckeditor5-build-balloon-block/build/ckeditor.js.map
  28. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/ar.js
  29. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/ast.js
  30. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/az.js
  31. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/bg.js
  32. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/cs.js
  33. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/da.js
  34. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/de.js
  35. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/el.js
  36. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/en-au.js
  37. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/en-gb.js
  38. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/eo.js
  39. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/es.js
  40. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/et.js
  41. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/eu.js
  42. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/fa.js
  43. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/fi.js
  44. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/fr.js
  45. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/gl.js
  46. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/he.js
  47. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/hr.js
  48. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/hu.js
  49. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/id.js
  50. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/it.js
  51. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/ja.js
  52. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/km.js
  53. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/kn.js
  54. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/ko.js
  55. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/ku.js
  56. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/lt.js
  57. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/lv.js
  58. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/nb.js
  59. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/ne.js
  60. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/nl.js
  61. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/no.js
  62. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/pl.js
  63. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/pt-br.js
  64. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/pt.js
  65. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/ro.js
  66. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/ru.js
  67. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/si.js
  68. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/sk.js
  69. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/sq.js
  70. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/sr-latn.js
  71. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/sr.js
  72. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/sv.js
  73. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/th.js
  74. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/tr.js
  75. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/ug.js
  76. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/uk.js
  77. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/vi.js
  78. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/zh-cn.js
  79. 1 1
      packages/ckeditor5-build-balloon-block/build/translations/zh.js
  80. 22 22
      packages/ckeditor5-build-balloon-block/package.json
  81. 1 1
      packages/ckeditor5-build-balloon/build/ckeditor.js
  82. 1 1
      packages/ckeditor5-build-balloon/build/ckeditor.js.map
  83. 1 1
      packages/ckeditor5-build-balloon/build/translations/ar.js
  84. 1 1
      packages/ckeditor5-build-balloon/build/translations/ast.js
  85. 1 1
      packages/ckeditor5-build-balloon/build/translations/az.js
  86. 1 1
      packages/ckeditor5-build-balloon/build/translations/bg.js
  87. 1 1
      packages/ckeditor5-build-balloon/build/translations/cs.js
  88. 1 1
      packages/ckeditor5-build-balloon/build/translations/da.js
  89. 1 1
      packages/ckeditor5-build-balloon/build/translations/de.js
  90. 1 1
      packages/ckeditor5-build-balloon/build/translations/el.js
  91. 1 1
      packages/ckeditor5-build-balloon/build/translations/en-au.js
  92. 1 1
      packages/ckeditor5-build-balloon/build/translations/en-gb.js
  93. 1 1
      packages/ckeditor5-build-balloon/build/translations/eo.js
  94. 1 1
      packages/ckeditor5-build-balloon/build/translations/es.js
  95. 1 1
      packages/ckeditor5-build-balloon/build/translations/et.js
  96. 1 1
      packages/ckeditor5-build-balloon/build/translations/eu.js
  97. 1 1
      packages/ckeditor5-build-balloon/build/translations/fa.js
  98. 1 1
      packages/ckeditor5-build-balloon/build/translations/fi.js
  99. 1 1
      packages/ckeditor5-build-balloon/build/translations/fr.js
  100. 0 0
      packages/ckeditor5-build-balloon/build/translations/gl.js

+ 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"

+ 1 - 1
.github/workflows/merge-stable.yml

@@ -22,7 +22,7 @@ jobs:
       - uses: rtCamp/action-slack-notify@v2.0.2
         id: error_message_slack
         name: Slack notification
-        if: (steps.merge_action.outputs.status != 201) && (steps.merge_action.outputs.status != 204)
+        if: ((steps.merge_action.outputs.status != 201) && (steps.merge_action.outputs.status != 204)) || failure()
         env:
           SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
           SLACK_CHANNEL: "cke5-ci"

+ 156 - 21
CHANGELOG.md

@@ -1,6 +1,141 @@
 Changelog
 =========
 
+## [23.0.0](https://github.com/ckeditor/ckeditor5/compare/v22.0.0...v23.0.0) (2020-09-29)
+
+### Release highlights
+
+We are happy to announce the release of CKEditor 5 v23.0.0.
+
+This release was focused on bug fixes and stability improvements. Some highlights are listed below:
+
+* [Five bug fixes for list and list style plugins](https://github.com/ckeditor/ckeditor5/issues?q=is%3Aissue+milestone%3A%22iteration+36%22+label%3Atype%3Abug+label%3Apackage%3Alist).
+* [Extracted the "Image upload via URL" feature to a separate image insert plugin](https://github.com/ckeditor/ckeditor5/issues/7890).
+* [Improvements for pasting as plain text using <kbd>ctrl/cmd</kbd> + <kbd>shift</kbd> + <kbd>v</kbd>](https://github.com/ckeditor/ckeditor5/issues/7799).
+* Fixed [a case where the link balloon toolbar would be mispositioned](https://github.com/ckeditor/ckeditor5/issues/7926) in some rare cases.
+
+Please note that there are some **major breaking changes**. Be sure to review them before upgrading.
+
+<!-- TODO: Add a link to the blog post. -->
+
+### Collaboration features
+
+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)
+
+* **[image](https://www.npmjs.com/package/@ckeditor/ckeditor5-image)**: In order to use the "insert image via URL" feature you now need to load the `ImageInsert` plugin and use the `imageInsert` button instead of the `imageUpload` button that implemented that functionality previously.
+
+### MINOR BREAKING CHANGES [ℹ️](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/versioning-policy.html#major-and-minor-breaking-changes)
+
+* **[clipboard](https://www.npmjs.com/package/@ckeditor/ckeditor5-clipboard)**: When pasting plain text each double line break is now treated as a paragraph separator, while a single line break is converted into a soft break. Formerly every single line break was treated as paragraph separation.
+
+### Features
+
+* **[clipboard](https://www.npmjs.com/package/@ckeditor/ckeditor5-clipboard)**: Improved line to paragraph/soft break retention when pasting as plain text. Closes [#7884](https://github.com/ckeditor/ckeditor5/issues/7884). ([commit](https://github.com/ckeditor/ckeditor5/commit/a4b89965e8b156ee4ed67df9d4a634c0e6deac01))
+* **[utils](https://www.npmjs.com/package/@ckeditor/ckeditor5-utils)**: Added a user-agent check for the Blink engine to the [`env`](https://ckeditor.com/docs/ckeditor5/latest/api/module_utils_env-env.html) module. ([commit](https://github.com/ckeditor/ckeditor5/commit/a5a4b933e8ecef2b25ddbf03d371b89f26490025))
+* Introduced the `PastePlainText` feature that detects pasting with <kbd>ctrl/cmd</kbd> + <kbd>shift</kbd> + <kbd>v</kbd> keystroke. Closes [#7799](https://github.com/ckeditor/ckeditor5/issues/7799). ([commit](https://github.com/ckeditor/ckeditor5/commit/ab7bce94ebb7b6d59c5f3ea2d9433f71ddd864d2))
+
+### Bug fixes
+
+* **[clipboard](https://www.npmjs.com/package/@ckeditor/ckeditor5-clipboard)**: Soft breaks are now properly placed in the plain text clipboard data representation by the editor. Closes [#8045](https://github.com/ckeditor/ckeditor5/issues/8045). ([commit](https://github.com/ckeditor/ckeditor5/commit/92ace8d7f3abe4c8247ca18697984eb538f3f5ec))
+* **[engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine)**: `model.History#getOperations` was returning incorrect values if history had operations with negative version numbers or version numbers differing by more than one. Closes [#8143](https://github.com/ckeditor/ckeditor5/issues/8143). ([commit](https://github.com/ckeditor/ckeditor5/commit/3433e9a8ad64cc971cdfa4658a84585b4e23f19e))
+* **[image](https://www.npmjs.com/package/@ckeditor/ckeditor5-image)**: Aligned and fixed the styling for the split button in the `ImageInsert` dropdown. Closes [#7986](https://github.com/ckeditor/ckeditor5/issues/7986), [#7927](https://github.com/ckeditor/ckeditor5/issues/7927). ([commit](https://github.com/ckeditor/ckeditor5/commit/4671ed10a4af4c507abd594414771b714ff31cf7))
+* **[link](https://www.npmjs.com/package/@ckeditor/ckeditor5-link)**: Manual decorators will no longer be corrupted by the link image plugin. Closes [#7975](https://github.com/ckeditor/ckeditor5/issues/7975). ([commit](https://github.com/ckeditor/ckeditor5/commit/73eacd641f38ee261cd43ddfdf98df5e22eb2fdd))
+* **[link](https://www.npmjs.com/package/@ckeditor/ckeditor5-link)**: Prevented throwing an error when creating a link from a multi-block selection. Closes [#7907](https://github.com/ckeditor/ckeditor5/issues/7907). ([commit](https://github.com/ckeditor/ckeditor5/commit/eb92cfb7377fa066a4cb08163ade33a73639aab1))
+* **[link](https://www.npmjs.com/package/@ckeditor/ckeditor5-link)**: Pressing the <kbd>Enter</kbd> key should not throw an error when a non-collapsed selection ends with a valid URL. Closes [#7983](https://github.com/ckeditor/ckeditor5/issues/7983). ([commit](https://github.com/ckeditor/ckeditor5/commit/bcf3af6bee1edbd3a6d0c6874e0ad0518f73f518))
+* **[link](https://www.npmjs.com/package/@ckeditor/ckeditor5-link)**: The link balloon positioning should be correct when the selection is collapsed in some rare cases. Closes [#7926](https://github.com/ckeditor/ckeditor5/issues/7926). ([commit](https://github.com/ckeditor/ckeditor5/commit/b532a8ec55e1e1506b6f8030f944559b1cf0761d))
+* **[list](https://www.npmjs.com/package/@ckeditor/ckeditor5-list)**: List styles plugin will no longer cause the editor to crash when indenting a list item that is the last element in the editor. Closes [#8072](https://github.com/ckeditor/ckeditor5/issues/8072). ([commit](https://github.com/ckeditor/ckeditor5/commit/3e6ea99fe28225c52092b621c3593748bb1c168e))
+* **[list](https://www.npmjs.com/package/@ckeditor/ckeditor5-list)**: Undo will restore a proper value of the `list-style-type` attribute in the view element after undoing list merge. Closes [#7930](https://github.com/ckeditor/ckeditor5/issues/7930). ([commit](https://github.com/ckeditor/ckeditor5/commit/3e6ea99fe28225c52092b621c3593748bb1c168e))
+* **[list](https://www.npmjs.com/package/@ckeditor/ckeditor5-list)**: Fixed a bug that prevented using the same list style for nested lists. Closes [#8081](https://github.com/ckeditor/ckeditor5/issues/8081). ([commit](https://github.com/ckeditor/ckeditor5/commit/3e6ea99fe28225c52092b621c3593748bb1c168e))
+* **[list](https://www.npmjs.com/package/@ckeditor/ckeditor5-list)**: The `listStyle` attribute should be inherited when inserting or replacing a `listItem` with the same kind of the list (the `listType` attribute for the inserted/modified item is equal to next/previous sibling list). Closes [#7932](https://github.com/ckeditor/ckeditor5/issues/7932). ([commit](https://github.com/ckeditor/ckeditor5/commit/03bf7211b1efc94ba087750f77006d534fdbaa5d))
+* **[list](https://www.npmjs.com/package/@ckeditor/ckeditor5-list)**: When removing the content between two lists items, the lists will be merged into a single list. The second list should adjust its `listStyle` attribute to the first list. Closes [#7879](https://github.com/ckeditor/ckeditor5/issues/7879). ([commit](https://github.com/ckeditor/ckeditor5/commit/7aa952823a8b182dc41075fa8cf4cc3a452eb78b))
+* **[paste-from-office](https://www.npmjs.com/package/@ckeditor/ckeditor5-paste-from-office)**: Fixed pasting a list with an empty item from Google Docs. Closes [#7958](https://github.com/ckeditor/ckeditor5/issues/7958). ([commit](https://github.com/ckeditor/ckeditor5/commit/ebf6bb798cb274c840df86de073cf511c66d876c))
+
+### Other changes
+
+* **[cloud-services-core](https://www.npmjs.com/package/@ckeditor/ckeditor-cloud-services-core)**: Change tokens refreshing mechanism to depend on the token expiration time. ([commit](https://github.com/ckeditor/ckeditor5/commit/501490a5729c413ee00311fe3c9a965fab2bb2ad))
+* **[image](https://www.npmjs.com/package/@ckeditor/ckeditor5-image)**: The `config.image.upload.panel.items` does not need to be set anymore in order to show the "insert image via URL form". It is enough to load the new `ImageInsert` plugin and use the new `imageInsert` button. See [#8034](https://github.com/ckeditor/ckeditor5/issues/8034). ([commit](https://github.com/ckeditor/ckeditor5/commit/48a9e943122e4cdd0e2647f03ebc7b17c402710e))
+* **[image](https://www.npmjs.com/package/@ckeditor/ckeditor5-image)**: Introduced `ImageInsert` as a standalone plugin that contains `ImageUpload` functionality. Closes [#7890](https://github.com/ckeditor/ckeditor5/issues/7890). ([commit](https://github.com/ckeditor/ckeditor5/commit/4671ed10a4af4c507abd594414771b714ff31cf7))
+* **[image](https://www.npmjs.com/package/@ckeditor/ckeditor5-image)**: The `ImageUploadPanelView` form label should change depending on whether the image is selected or not. Closes [#7878](https://github.com/ckeditor/ckeditor5/issues/7878). ([commit](https://github.com/ckeditor/ckeditor5/commit/288fb97e00181a130dd2833d6e3aa74bdab5b7cc))
+* **[link](https://www.npmjs.com/package/@ckeditor/ckeditor5-link)**: The link plugin now comes with the autolink feature enabled by default. Closes [#7682](https://github.com/ckeditor/ckeditor5/issues/7682). ([commit](https://github.com/ckeditor/ckeditor5/commit/c9533f1752057fd833998a356282f8a625f4e39c))
+* **[theme-lark](https://www.npmjs.com/package/@ckeditor/ckeditor5-theme-lark)**: Balloon panel arrows pointing south should have realistic shadows. Closes [#7928](https://github.com/ckeditor/ckeditor5/issues/7928). ([commit](https://github.com/ckeditor/ckeditor5/commit/1c0b5c978fc23f3ca5cccba7b89711469838c315))
+* Updated translations. ([commit](https://github.com/ckeditor/ckeditor5/commit/9256cbee9dc2173e1f1756fa566ba92a2d4bd6bc), [commit](https://github.com/ckeditor/ckeditor5/commit/08fc2a54b8953fe6000c900d8f1270b86edc1590))
+
+### Released packages
+
+Check out the [Versioning policy](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/versioning-policy.html) guide for more information.
+
+<details>
+<summary>Released packages (summary)</summary>
+
+Major releases (contain major breaking changes):
+
+* [@ckeditor/ckeditor5-easy-image](https://www.npmjs.com/package/@ckeditor/ckeditor5-easy-image): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-image](https://www.npmjs.com/package/@ckeditor/ckeditor5-image): v22.0.0 => v23.0.0
+
+Minor releases (contain minor breaking changes):
+
+* [@ckeditor/ckeditor5-clipboard](https://www.npmjs.com/package/@ckeditor/ckeditor5-clipboard): v22.0.0 => v23.0.0
+
+Releases containing new features:
+
+* [@ckeditor/ckeditor5-utils](https://www.npmjs.com/package/@ckeditor/ckeditor5-utils): v22.0.0 => v23.0.0
+
+Other releases:
+
+* [@ckeditor/ckeditor-cloud-services-core](https://www.npmjs.com/package/@ckeditor/ckeditor-cloud-services-core): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-adapter-ckfinder](https://www.npmjs.com/package/@ckeditor/ckeditor5-adapter-ckfinder): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-alignment](https://www.npmjs.com/package/@ckeditor/ckeditor5-alignment): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-autoformat](https://www.npmjs.com/package/@ckeditor/ckeditor5-autoformat): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-autosave](https://www.npmjs.com/package/@ckeditor/ckeditor5-autosave): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-basic-styles](https://www.npmjs.com/package/@ckeditor/ckeditor5-basic-styles): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-block-quote](https://www.npmjs.com/package/@ckeditor/ckeditor5-block-quote): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-build-balloon](https://www.npmjs.com/package/@ckeditor/ckeditor5-build-balloon): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-build-balloon-block](https://www.npmjs.com/package/@ckeditor/ckeditor5-build-balloon-block): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-build-classic](https://www.npmjs.com/package/@ckeditor/ckeditor5-build-classic): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-build-decoupled-document](https://www.npmjs.com/package/@ckeditor/ckeditor5-build-decoupled-document): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-build-inline](https://www.npmjs.com/package/@ckeditor/ckeditor5-build-inline): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-ckfinder](https://www.npmjs.com/package/@ckeditor/ckeditor5-ckfinder): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-cloud-services](https://www.npmjs.com/package/@ckeditor/ckeditor5-cloud-services): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-code-block](https://www.npmjs.com/package/@ckeditor/ckeditor5-code-block): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-core](https://www.npmjs.com/package/@ckeditor/ckeditor5-core): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-editor-balloon](https://www.npmjs.com/package/@ckeditor/ckeditor5-editor-balloon): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-editor-classic](https://www.npmjs.com/package/@ckeditor/ckeditor5-editor-classic): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-editor-decoupled](https://www.npmjs.com/package/@ckeditor/ckeditor5-editor-decoupled): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-editor-inline](https://www.npmjs.com/package/@ckeditor/ckeditor5-editor-inline): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-engine](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-enter](https://www.npmjs.com/package/@ckeditor/ckeditor5-enter): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-essentials](https://www.npmjs.com/package/@ckeditor/ckeditor5-essentials): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-font](https://www.npmjs.com/package/@ckeditor/ckeditor5-font): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-heading](https://www.npmjs.com/package/@ckeditor/ckeditor5-heading): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-highlight](https://www.npmjs.com/package/@ckeditor/ckeditor5-highlight): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-horizontal-line](https://www.npmjs.com/package/@ckeditor/ckeditor5-horizontal-line): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-indent](https://www.npmjs.com/package/@ckeditor/ckeditor5-indent): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-link](https://www.npmjs.com/package/@ckeditor/ckeditor5-link): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-list](https://www.npmjs.com/package/@ckeditor/ckeditor5-list): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-markdown-gfm](https://www.npmjs.com/package/@ckeditor/ckeditor5-markdown-gfm): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-media-embed](https://www.npmjs.com/package/@ckeditor/ckeditor5-media-embed): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-mention](https://www.npmjs.com/package/@ckeditor/ckeditor5-mention): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-page-break](https://www.npmjs.com/package/@ckeditor/ckeditor5-page-break): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-paragraph](https://www.npmjs.com/package/@ckeditor/ckeditor5-paragraph): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-paste-from-office](https://www.npmjs.com/package/@ckeditor/ckeditor5-paste-from-office): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-remove-format](https://www.npmjs.com/package/@ckeditor/ckeditor5-remove-format): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-restricted-editing](https://www.npmjs.com/package/@ckeditor/ckeditor5-restricted-editing): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-select-all](https://www.npmjs.com/package/@ckeditor/ckeditor5-select-all): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-special-characters](https://www.npmjs.com/package/@ckeditor/ckeditor5-special-characters): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-table](https://www.npmjs.com/package/@ckeditor/ckeditor5-table): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-theme-lark](https://www.npmjs.com/package/@ckeditor/ckeditor5-theme-lark): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-typing](https://www.npmjs.com/package/@ckeditor/ckeditor5-typing): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-ui](https://www.npmjs.com/package/@ckeditor/ckeditor5-ui): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-undo](https://www.npmjs.com/package/@ckeditor/ckeditor5-undo): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-upload](https://www.npmjs.com/package/@ckeditor/ckeditor5-upload): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-watchdog](https://www.npmjs.com/package/@ckeditor/ckeditor5-watchdog): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-widget](https://www.npmjs.com/package/@ckeditor/ckeditor5-widget): v22.0.0 => v23.0.0
+* [@ckeditor/ckeditor5-word-count](https://www.npmjs.com/package/@ckeditor/ckeditor5-word-count): v22.0.0 => v23.0.0
+</details>
+
+
 ## [22.0.0](https://github.com/ckeditor/ckeditor5/compare/v21.0.0...v22.0.0) (2020-08-26)
 
 ### Release highlights
@@ -9,24 +144,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 +171,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).

+ 6 - 1
docs/_snippets/examples/document-editor.js

@@ -6,11 +6,16 @@
 /* globals console, window, document */
 
 import DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document/src/ckeditor';
+import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize';
 import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config';
 
 DecoupledEditor
 	.create( document.querySelector( '.document-editor__editable' ), {
-		cloudServices: CS_CONFIG
+		extraPlugins: [ ImageResize ],
+		cloudServices: CS_CONFIG,
+		image: {
+			toolbar: [ 'imageTextAlternative', '|', 'imageStyle:alignLeft', 'imageStyle:full', 'imageStyle:alignRight' ]
+		}
 	} )
 	.then( editor => {
 		const toolbarContainer = document.querySelector( '.document-editor__toolbar' );

+ 1 - 1
docs/_snippets/examples/multi-root-editor.html

@@ -11,7 +11,7 @@
 
 		<h4>Valletta</h4>
 
-		<figure class="image image-style-align-right">
+		<figure class="image image-style-side">
 			<img alt="Picture of a sunlit facade of a Maltan building." src="%BASE_PATH%/assets/img/malta.jpg">
 			<figcaption>It's siesta time in Valletta.</figcaption>
 		</figure>

+ 3 - 3
docs/_snippets/examples/multi-root-editor.js

@@ -404,8 +404,9 @@ MultirootEditor
 		toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'imageUpload', 'blockQuote',
 			'insertTable', 'mediaEmbed', 'undo', 'redo' ],
 		image: {
-			toolbar: [ 'imageTextAlternative', '|', 'imageStyle:alignLeft', 'imageStyle:full', 'imageStyle:alignRight' ],
-			styles: [ 'full', 'alignLeft', 'alignRight' ]
+			toolbar: [ 'imageTextAlternative', '|', 'imageStyle:full',
+				'imageStyle:side' ],
+			styles: [ 'full', 'side' ]
 		},
 		table: {
 			contentToolbar: [
@@ -430,4 +431,3 @@ MultirootEditor
 	.catch( err => {
 		console.error( err.stack );
 	} );
-

+ 24 - 24
docs/builds/guides/integration/content-styles.md

@@ -48,8 +48,8 @@ Below there is a full list of content styles used by the editor features. You ca
 
 ```css
 /*
- * CKEditor 5 (v22.0.0) content styles.
- * Generated on Thu, 27 Aug 2020 12:13:06 GMT.
+ * CKEditor 5 (v23.0.0) content styles.
+ * Generated on Wed, 30 Sep 2020 10:17:57 GMT.
  * For more information, check out https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/content-styles.html
  */
 
@@ -113,6 +113,28 @@ Below there is a full list of content styles used by the editor features. You ca
 	float: right;
 	margin-left: var(--ck-image-style-spacing);
 }
+/* ckeditor5-block-quote/theme/blockquote.css */
+.ck-content blockquote {
+	overflow: hidden;
+	padding-right: 1.5em;
+	padding-left: 1.5em;
+	margin-left: 0;
+	margin-right: 0;
+	font-style: italic;
+	border-left: solid 5px hsl(0, 0%, 80%);
+}
+/* ckeditor5-block-quote/theme/blockquote.css */
+.ck-content[dir="rtl"] blockquote {
+	border-left: 0;
+	border-right: solid 5px hsl(0, 0%, 80%);
+}
+/* ckeditor5-horizontal-line/theme/horizontalline.css */
+.ck-content hr {
+	margin: 15px 0;
+	height: 4px;
+	background: hsl(0, 0%, 87%);
+	border: 0;
+}
 /* ckeditor5-image/theme/image.css */
 .ck-content .image {
 	display: table;
@@ -174,21 +196,6 @@ Below there is a full list of content styles used by the editor features. You ca
 .ck-content .text-huge {
 	font-size: 1.8em;
 }
-/* ckeditor5-block-quote/theme/blockquote.css */
-.ck-content blockquote {
-	overflow: hidden;
-	padding-right: 1.5em;
-	padding-left: 1.5em;
-	margin-left: 0;
-	margin-right: 0;
-	font-style: italic;
-	border-left: solid 5px hsl(0, 0%, 80%);
-}
-/* ckeditor5-block-quote/theme/blockquote.css */
-.ck-content[dir="rtl"] blockquote {
-	border-left: 0;
-	border-right: solid 5px hsl(0, 0%, 80%);
-}
 /* ckeditor5-table/theme/table.css */
 .ck-content .table {
 	margin: 1em auto;
@@ -332,13 +339,6 @@ Below there is a full list of content styles used by the editor features. You ca
 .ck-content .todo-list .todo-list__label .todo-list__label__description {
 	vertical-align: middle;
 }
-/* ckeditor5-horizontal-line/theme/horizontalline.css */
-.ck-content hr {
-	margin: 15px 0;
-	height: 4px;
-	background: hsl(0, 0%, 87%);
-	border: 0;
-}
 /* ckeditor5-code-block/theme/codeblock.css */
 .ck-content pre {
 	padding: 1em;

File diff suppressed because it is too large
+ 1 - 1
docs/builds/guides/migrate.md


+ 3 - 2
docs/framework/guides/contributing/testing-environment.md

@@ -54,11 +54,12 @@ In order to start the manual tests server, use the `yarn run manual` task.
 
 The task accepts the following options:
 
-* `--source-map` (alias `-s`) &ndash; Whether to generate useful source maps for the code.
 * `--files` &ndash; Specifies test files to run. Accepts a package name or a glob. For example `--files=ckeditor5` will only run tests from the CKEditor 5 main package. Read more about the [rules for converting the `--files` option to a glob pattern](https://github.com/ckeditor/ckeditor5-dev/tree/master/packages/ckeditor5-dev-tests#rules-for-converting---files-option-to-glob-pattern).
-* `--additionalLanguages="ar,pl,..."` &ndash; Specifies extra languages to the [CKEditor 5 webpack plugin](https://www.npmjs.com/package/@ckeditor/ckeditor5-dev-webpack-plugin). Check out the {@link features/ui-language UI language guide} to learn more.
+* `--language="pl"` &ndash; The main language build in into all test editors, passed to the [CKEditor 5 webpack plugin](https://www.npmjs.com/package/@ckeditor/ckeditor5-dev-webpack-plugin).  Check out the {@link features/ui-language UI language guide} to learn more. When unspecified, `'en'` is passed to the test runner.
+* `--additionalLanguages="ar,pl,..."` &ndash; Specifies extra languages passed to the [CKEditor 5 webpack plugin](https://www.npmjs.com/package/@ckeditor/ckeditor5-dev-webpack-plugin). Check out the {@link features/ui-language UI language guide} to learn more.
 * `--debug` (alias `-d`) &ndash; Allows specifying custom debug flags. For example, the `--debug engine` option uncomments the `// @if CK_DEBUG_ENGINE //` lines in the code. Note that by default `--debug` is set to `true` even if you did not specify it. This enables the base set of debug logs (`// @if CK_DEBUG //`) which should always be enabled in the testing environment. You can completely turn off the debug mode by setting the `--debug false` option.
 * `--port` &ndash; Specifies the port for the server to use. Defaults to `8125`.
+* `--identityFile="/path/to/file.js"` &ndash; Path to the file containing the license key(s) for closed–source features.
 
 It starts the server available at http://localhost:8125.
 

File diff suppressed because it is too large
+ 8 - 6
docs/framework/guides/support/versioning-policy.md


+ 63 - 61
package.json

@@ -1,6 +1,6 @@
 {
   "name": "ckeditor5",
-  "version": "22.0.0",
+  "version": "23.0.0",
   "description": "The development environment of CKEditor 5 – the best browser-based rich text editor.",
   "private": true,
   "keywords": [
@@ -21,71 +21,71 @@
     "framework"
   ],
   "dependencies": {
-    "@ckeditor/ckeditor-cloud-services-core": "^22.0.0",
-    "@ckeditor/ckeditor5-adapter-ckfinder": "^22.0.0",
-    "@ckeditor/ckeditor5-alignment": "^22.0.0",
-    "@ckeditor/ckeditor5-autoformat": "^22.0.0",
-    "@ckeditor/ckeditor5-autosave": "^22.0.0",
-    "@ckeditor/ckeditor5-basic-styles": "^22.0.0",
-    "@ckeditor/ckeditor5-block-quote": "^22.0.0",
-    "@ckeditor/ckeditor5-build-balloon": "^22.0.0",
-    "@ckeditor/ckeditor5-build-balloon-block": "^22.0.0",
-    "@ckeditor/ckeditor5-build-classic": "^22.0.0",
-    "@ckeditor/ckeditor5-build-decoupled-document": "^22.0.0",
-    "@ckeditor/ckeditor5-build-inline": "^22.0.0",
-    "@ckeditor/ckeditor5-ckfinder": "^22.0.0",
-    "@ckeditor/ckeditor5-clipboard": "^22.0.0",
-    "@ckeditor/ckeditor5-cloud-services": "^22.0.0",
-    "@ckeditor/ckeditor5-code-block": "^22.0.0",
-    "@ckeditor/ckeditor5-core": "^22.0.0",
-    "@ckeditor/ckeditor5-easy-image": "^22.0.0",
-    "@ckeditor/ckeditor5-editor-balloon": "^22.0.0",
-    "@ckeditor/ckeditor5-editor-classic": "^22.0.0",
-    "@ckeditor/ckeditor5-editor-decoupled": "^22.0.0",
-    "@ckeditor/ckeditor5-editor-inline": "^22.0.0",
-    "@ckeditor/ckeditor5-engine": "^22.0.0",
-    "@ckeditor/ckeditor5-enter": "^22.0.0",
-    "@ckeditor/ckeditor5-essentials": "^22.0.0",
-    "@ckeditor/ckeditor5-font": "^22.0.0",
-    "@ckeditor/ckeditor5-heading": "^22.0.0",
-    "@ckeditor/ckeditor5-highlight": "^22.0.0",
-    "@ckeditor/ckeditor5-horizontal-line": "^22.0.0",
-    "@ckeditor/ckeditor5-image": "^22.0.0",
-    "@ckeditor/ckeditor5-indent": "^22.0.0",
-    "@ckeditor/ckeditor5-link": "^22.0.0",
-    "@ckeditor/ckeditor5-list": "^22.0.0",
-    "@ckeditor/ckeditor5-markdown-gfm": "^22.0.0",
-    "@ckeditor/ckeditor5-media-embed": "^22.0.0",
-    "@ckeditor/ckeditor5-mention": "^22.0.0",
-    "@ckeditor/ckeditor5-page-break": "^22.0.0",
-    "@ckeditor/ckeditor5-paragraph": "^22.0.0",
-    "@ckeditor/ckeditor5-paste-from-office": "^22.0.0",
-    "@ckeditor/ckeditor5-remove-format": "^22.0.0",
-    "@ckeditor/ckeditor5-restricted-editing": "^22.0.0",
-    "@ckeditor/ckeditor5-select-all": "^22.0.0",
-    "@ckeditor/ckeditor5-special-characters": "^22.0.0",
-    "@ckeditor/ckeditor5-table": "^22.0.0",
-    "@ckeditor/ckeditor5-theme-lark": "^22.0.0",
-    "@ckeditor/ckeditor5-typing": "^22.0.0",
-    "@ckeditor/ckeditor5-ui": "^22.0.0",
-    "@ckeditor/ckeditor5-undo": "^22.0.0",
-    "@ckeditor/ckeditor5-upload": "^22.0.0",
-    "@ckeditor/ckeditor5-utils": "^22.0.0",
-    "@ckeditor/ckeditor5-watchdog": "^22.0.0",
-    "@ckeditor/ckeditor5-widget": "^22.0.0",
-    "@ckeditor/ckeditor5-word-count": "^22.0.0"
+    "@ckeditor/ckeditor-cloud-services-core": "^23.0.0",
+    "@ckeditor/ckeditor5-adapter-ckfinder": "^23.0.0",
+    "@ckeditor/ckeditor5-alignment": "^23.0.0",
+    "@ckeditor/ckeditor5-autoformat": "^23.0.0",
+    "@ckeditor/ckeditor5-autosave": "^23.0.0",
+    "@ckeditor/ckeditor5-basic-styles": "^23.0.0",
+    "@ckeditor/ckeditor5-block-quote": "^23.0.0",
+    "@ckeditor/ckeditor5-build-balloon": "^23.0.0",
+    "@ckeditor/ckeditor5-build-balloon-block": "^23.0.0",
+    "@ckeditor/ckeditor5-build-classic": "^23.0.0",
+    "@ckeditor/ckeditor5-build-decoupled-document": "^23.0.0",
+    "@ckeditor/ckeditor5-build-inline": "^23.0.0",
+    "@ckeditor/ckeditor5-ckfinder": "^23.0.0",
+    "@ckeditor/ckeditor5-clipboard": "^23.0.0",
+    "@ckeditor/ckeditor5-cloud-services": "^23.0.0",
+    "@ckeditor/ckeditor5-code-block": "^23.0.0",
+    "@ckeditor/ckeditor5-core": "^23.0.0",
+    "@ckeditor/ckeditor5-easy-image": "^23.0.0",
+    "@ckeditor/ckeditor5-editor-balloon": "^23.0.0",
+    "@ckeditor/ckeditor5-editor-classic": "^23.0.0",
+    "@ckeditor/ckeditor5-editor-decoupled": "^23.0.0",
+    "@ckeditor/ckeditor5-editor-inline": "^23.0.0",
+    "@ckeditor/ckeditor5-engine": "^23.0.0",
+    "@ckeditor/ckeditor5-enter": "^23.0.0",
+    "@ckeditor/ckeditor5-essentials": "^23.0.0",
+    "@ckeditor/ckeditor5-font": "^23.0.0",
+    "@ckeditor/ckeditor5-heading": "^23.0.0",
+    "@ckeditor/ckeditor5-highlight": "^23.0.0",
+    "@ckeditor/ckeditor5-horizontal-line": "^23.0.0",
+    "@ckeditor/ckeditor5-image": "^23.0.0",
+    "@ckeditor/ckeditor5-indent": "^23.0.0",
+    "@ckeditor/ckeditor5-link": "^23.0.0",
+    "@ckeditor/ckeditor5-list": "^23.0.0",
+    "@ckeditor/ckeditor5-markdown-gfm": "^23.0.0",
+    "@ckeditor/ckeditor5-media-embed": "^23.0.0",
+    "@ckeditor/ckeditor5-mention": "^23.0.0",
+    "@ckeditor/ckeditor5-page-break": "^23.0.0",
+    "@ckeditor/ckeditor5-paragraph": "^23.0.0",
+    "@ckeditor/ckeditor5-paste-from-office": "^23.0.0",
+    "@ckeditor/ckeditor5-remove-format": "^23.0.0",
+    "@ckeditor/ckeditor5-restricted-editing": "^23.0.0",
+    "@ckeditor/ckeditor5-select-all": "^23.0.0",
+    "@ckeditor/ckeditor5-special-characters": "^23.0.0",
+    "@ckeditor/ckeditor5-table": "^23.0.0",
+    "@ckeditor/ckeditor5-theme-lark": "^23.0.0",
+    "@ckeditor/ckeditor5-typing": "^23.0.0",
+    "@ckeditor/ckeditor5-ui": "^23.0.0",
+    "@ckeditor/ckeditor5-undo": "^23.0.0",
+    "@ckeditor/ckeditor5-upload": "^23.0.0",
+    "@ckeditor/ckeditor5-utils": "^23.0.0",
+    "@ckeditor/ckeditor5-watchdog": "^23.0.0",
+    "@ckeditor/ckeditor5-widget": "^23.0.0",
+    "@ckeditor/ckeditor5-word-count": "^23.0.0"
   },
   "devDependencies": {
     "@ckeditor/ckeditor5-comments": "^22.0.0",
     "@ckeditor/ckeditor5-dev-docs": "^23.2.0",
     "@ckeditor/ckeditor5-dev-env": "^23.2.0",
-    "@ckeditor/ckeditor5-dev-tests": "^23.2.0",
+    "@ckeditor/ckeditor5-dev-tests": "^23.3.0",
     "@ckeditor/ckeditor5-dev-utils": "^23.2.0",
     "@ckeditor/ckeditor5-dev-webpack-plugin": "^23.2.0",
-    "@ckeditor/ckeditor5-export-pdf": "^1.0.1",
-    "@ckeditor/ckeditor5-export-word": "^1.0.0",
+    "@ckeditor/ckeditor5-export-pdf": ">=1.0.0",
+    "@ckeditor/ckeditor5-export-word": ">=1.0.0",
     "@ckeditor/ckeditor5-inspector": "^2.2.0",
-    "@ckeditor/ckeditor5-pagination": "^0.0.3",
+    "@ckeditor/ckeditor5-pagination": ">=1.0.0",
     "@ckeditor/ckeditor5-react": "^2.1.0",
     "@ckeditor/ckeditor5-real-time-collaboration": "^22.0.0",
     "@ckeditor/ckeditor5-track-changes": "^22.0.0",
@@ -132,7 +132,7 @@
   },
   "scripts": {
     "lint": "eslint --quiet '**/*.js'",
-    "stylelint": "stylelint --quiet --allow-empty-input 'packages/**/*.css' 'external/*/packages/**/*.css' 'docs/**/*.css'",
+    "stylelint": "stylelint --quiet --allow-empty-input 'packages/**/*.css' 'docs/**/*.css'",
     "test": "node --max_old_space_size=8192 node_modules/@ckeditor/ckeditor5-dev-tests/bin/test.js",
     "manual": "node --max_old_space_size=8192 node_modules/@ckeditor/ckeditor5-dev-tests/bin/test-manual.js",
     "bootstrap": "yarn install",
@@ -176,8 +176,10 @@
       "packages/*",
       "external/*",
       "external/*/packages/*",
-      "external/*/packages/**/ckeditor5",
-      "external/*/packages/**/frontend",
+      "external/*/external/*",
+      "external/*/external/*/packages/*",
+      "external/*/external/*/packages/**/ckeditor5",
+      "external/*/external/*/packages/**/frontend",
       "."
     ],
     "nohoist": [

+ 2 - 2
packages/ckeditor-cloud-services-core/package.json

@@ -1,13 +1,13 @@
 {
   "name": "@ckeditor/ckeditor-cloud-services-core",
-  "version": "22.0.0",
+  "version": "23.0.0",
   "description": "CKEditor Cloud Services Core API.",
   "keywords": [
     "ckeditor5",
     "ckeditor5-lib"
   ],
   "dependencies": {
-    "@ckeditor/ckeditor5-utils": "^22.0.0"
+    "@ckeditor/ckeditor5-utils": "^23.0.0"
   },
   "engines": {
     "node": ">=12.0.0",

+ 77 - 18
packages/ckeditor-cloud-services-core/src/token/token.js

@@ -7,13 +7,14 @@
  * @module cloud-services-core/token
  */
 
-/* globals XMLHttpRequest, setInterval, clearInterval */
+/* globals XMLHttpRequest, setTimeout, clearTimeout, atob */
 
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 
-const DEFAULT_OPTIONS = { refreshInterval: 3600000, autoRefresh: true };
+const DEFAULT_OPTIONS = { autoRefresh: true };
+const DEFAULT_TOKEN_REFRESH_TIMEOUT_TIME = 3600000;
 
 /**
  * Class representing the token used for communication with CKEditor Cloud Services.
@@ -30,7 +31,6 @@ class Token {
 	 * value is a function it has to match the {@link module:cloud-services-core/token~refreshToken} interface.
 	 * @param {Object} options
 	 * @param {String} [options.initValue] Initial value of the token.
-	 * @param {Number} [options.refreshInterval=3600000] Delay between refreshes. Default 1 hour.
 	 * @param {Boolean} [options.autoRefresh=true] Specifies whether to start the refresh automatically.
 	 */
 	constructor( tokenUrlOrRefreshToken, options = DEFAULT_OPTIONS ) {
@@ -41,11 +41,15 @@ class Token {
 			 * @error token-missing-token-url
 			 */
 			throw new CKEditorError(
-				'token-missing-token-url: A `tokenUrl` must be provided as the first constructor argument.',
+				'token-missing-token-url',
 				this
 			);
 		}
 
+		if ( options.initValue ) {
+			this._validateTokenValue( options.initValue );
+		}
+
 		/**
 		 * Value of the token.
 		 * The value of the token is null if `initValue` is not provided or `init` method was not called.
@@ -84,10 +88,6 @@ class Token {
 	 */
 	init() {
 		return new Promise( ( resolve, reject ) => {
-			if ( this._options.autoRefresh ) {
-				this._startRefreshing();
-			}
-
 			if ( !this.value ) {
 				this.refreshToken()
 					.then( resolve )
@@ -96,6 +96,10 @@ class Token {
 				return;
 			}
 
+			if ( this._options.autoRefresh ) {
+				this._registerRefreshTokenTimeout();
+			}
+
 			resolve( this );
 		} );
 	}
@@ -106,7 +110,14 @@ class Token {
 	 */
 	refreshToken() {
 		return this._refresh()
-			.then( value => this.set( 'value', value ) )
+			.then( value => {
+				this._validateTokenValue( value );
+				this.set( 'value', value );
+
+				if ( this._options.autoRefresh ) {
+					this._registerRefreshTokenTimeout();
+				}
+			} )
 			.then( () => this );
 	}
 
@@ -114,25 +125,74 @@ class Token {
 	 * Destroys token instance. Stops refreshing.
 	 */
 	destroy() {
-		this._stopRefreshing();
+		clearTimeout( this._tokenRefreshTimeout );
+	}
+
+	/**
+	 * Checks whether the provided token follows the JSON Web Tokens (JWT) format.
+	 *
+	 * @protected
+	 * @param {String} tokenValue The token to validate.
+	 */
+	_validateTokenValue( tokenValue ) {
+		// The token must be a string.
+		const isString = typeof tokenValue === 'string';
+
+		// The token must be a plain string without quotes ("").
+		const isPlainString = !/^".*"$/.test( tokenValue );
+
+		// JWT token contains 3 parts: header, payload, and signature.
+		// Each part is separated by a dot.
+		const isJWTFormat = isString && tokenValue.split( '.' ).length === 3;
+
+		if ( !( isPlainString && isJWTFormat ) ) {
+			/**
+			 * The provided token must follow the [JSON Web Tokens](https://jwt.io/introduction/) format.
+			 *
+			 * @error token-not-in-jwt-format
+			 */
+			throw new CKEditorError( 'token-not-in-jwt-format', this );
+		}
 	}
 
 	/**
-	 * Starts value refreshing every `refreshInterval` time.
+	 * Registers a refresh token timeout for the time taken from token.
 	 *
 	 * @protected
 	 */
-	_startRefreshing() {
-		this._refreshInterval = setInterval( () => this.refreshToken(), this._options.refreshInterval );
+	_registerRefreshTokenTimeout() {
+		const tokenRefreshTimeoutTime = this._getTokenRefreshTimeoutTime();
+
+		clearTimeout( this._tokenRefreshTimeout );
+
+		this._tokenRefreshTimeout = setTimeout( () => {
+			this.refreshToken();
+		}, tokenRefreshTimeoutTime );
 	}
 
 	/**
-	 * Stops value refreshing.
+	 * Returns token refresh timeout time calculated from expire time in the token payload.
+	 *
+	 * If the token parse fails or the token payload doesn't contain, the default DEFAULT_TOKEN_REFRESH_TIMEOUT_TIME is returned.
 	 *
 	 * @protected
+	 * @returns {Number}
 	 */
-	_stopRefreshing() {
-		clearInterval( this._refreshInterval );
+	_getTokenRefreshTimeoutTime() {
+		try {
+			const [ , binaryTokenPayload ] = this.value.split( '.' );
+			const { exp: tokenExpireTime } = JSON.parse( atob( binaryTokenPayload ) );
+
+			if ( !tokenExpireTime ) {
+				return DEFAULT_TOKEN_REFRESH_TIMEOUT_TIME;
+			}
+
+			const tokenRefreshTimeoutTime = Math.floor( ( ( tokenExpireTime * 1000 ) - Date.now() ) / 2 );
+
+			return tokenRefreshTimeoutTime;
+		} catch ( err ) {
+			return DEFAULT_TOKEN_REFRESH_TIMEOUT_TIME;
+		}
 	}
 
 	/**
@@ -142,7 +202,6 @@ class Token {
 	 * value is a function it has to match the {@link module:cloud-services-core/token~refreshToken} interface.
 	 * @param {Object} options
 	 * @param {String} [options.initValue] Initial value of the token.
-	 * @param {Number} [options.refreshInterval=3600000] Delay between refreshes. Default 1 hour.
 	 * @param {Boolean} [options.autoRefresh=true] Specifies whether to start the refresh automatically.
 	 * @returns {Promise.<module:cloud-services-core/token~Token>}
 	 */
@@ -185,7 +244,7 @@ function defaultRefreshToken( tokenUrl ) {
 				 * @error token-cannot-download-new-token
 				 */
 				return reject(
-					new CKEditorError( 'token-cannot-download-new-token: Cannot download new token from the provided url.', null )
+					new CKEditorError( 'token-cannot-download-new-token', null )
 				);
 			}
 

+ 5 - 5
packages/ckeditor-cloud-services-core/src/uploadgateway/fileuploader.js

@@ -33,7 +33,7 @@ export default class FileUploader {
 			 *
 			 * @error fileuploader-missing-file
 			 */
-			throw new CKEditorError( 'fileuploader-missing-file: File must be provided as the first argument', null );
+			throw new CKEditorError( 'fileuploader-missing-file', null );
 		}
 
 		if ( !token ) {
@@ -42,7 +42,7 @@ export default class FileUploader {
 			 *
 			 * @error fileuploader-missing-token
 			 */
-			throw new CKEditorError( 'fileuploader-missing-token: Token must be provided as the second argument.', null );
+			throw new CKEditorError( 'fileuploader-missing-token', null );
 		}
 
 		if ( !apiAddress ) {
@@ -51,7 +51,7 @@ export default class FileUploader {
 			 *
 			 * @error fileuploader-missing-api-address
 			 */
-			throw new CKEditorError( 'fileuploader-missing-api-address: Api address must be provided as the third argument.', null );
+			throw new CKEditorError( 'fileuploader-missing-api-address', null );
 		}
 
 		/**
@@ -201,7 +201,7 @@ export default class FileUploader {
 						 * @error fileuploader-uploading-data-failed
 						 */
 						return reject( new CKEditorError(
-							'fileuploader-uploading-data-failed: Uploading file failed.',
+							'fileuploader-uploading-data-failed',
 							this,
 							{ message: xhrResponse.message }
 						) );
@@ -270,7 +270,7 @@ function _base64ToBlob( base64, sliceSize = 512 ) {
 		 *
 		 * @error fileuploader-decoding-image-data-error
 		 */
-		throw new CKEditorError( 'fileuploader-decoding-image-data-error: Problem with decoding Base64 image data.', null );
+		throw new CKEditorError( 'fileuploader-decoding-image-data-error', null );
 	}
 }
 

+ 2 - 2
packages/ckeditor-cloud-services-core/src/uploadgateway/uploadgateway.js

@@ -27,7 +27,7 @@ export default class UploadGateway {
 			 *
 			 * @error uploadgateway-missing-token
 			 */
-			throw new CKEditorError( 'uploadgateway-missing-token: Token must be provided.', null );
+			throw new CKEditorError( 'uploadgateway-missing-token', null );
 		}
 
 		if ( !apiAddress ) {
@@ -36,7 +36,7 @@ export default class UploadGateway {
 			 *
 			 * @error uploadgateway-missing-api-address
 			 */
-			throw new CKEditorError( 'uploadgateway-missing-api-address: Api address must be provided.', null );
+			throw new CKEditorError( 'uploadgateway-missing-api-address', null );
 		}
 
 		/**

+ 202 - 103
packages/ckeditor-cloud-services-core/tests/token/token.js

@@ -26,31 +26,56 @@ describe( 'Token', () => {
 	} );
 
 	describe( 'constructor()', () => {
-		it( 'should throw error when no tokenUrl provided', () => {
+		it( 'should throw an error when no tokenUrl provided', () => {
 			expect( () => new Token() ).to.throw(
 				CKEditorError,
 				'token-missing-token-url'
 			);
 		} );
 
-		it( 'should set a init token value', () => {
-			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+		it( 'should throw an error if the token passed in options is not a string', () => {
+			expect( () => new Token( 'http://token-endpoint', { initValue: 123456 } ) ).to.throw(
+				CKEditorError,
+				'token-not-in-jwt-format'
+			);
+		} );
+
+		it( 'should throw an error if the token passed in options is wrapped in additional quotes', () => {
+			const tokenInitValue = getTestTokenValue();
+
+			expect( () => new Token( 'http://token-endpoint', { initValue: `"${ tokenInitValue }"` } ) ).to.throw(
+				CKEditorError,
+				'token-not-in-jwt-format'
+			);
+		} );
 
-			expect( token.value ).to.equal( 'initValue' );
+		it( 'should throw an error if the token passed in options is not a valid JWT token', () => {
+			expect( () => new Token( 'http://token-endpoint', { initValue: 'token' } ) ).to.throw(
+				CKEditorError,
+				'token-not-in-jwt-format'
+			);
+		} );
+
+		it( 'should set token value if the token passed in options is valid', () => {
+			const tokenInitValue = getTestTokenValue();
+			const token = new Token( 'http://token-endpoint', { initValue: tokenInitValue } );
+
+			expect( token.value ).to.equal( tokenInitValue );
 		} );
 
 		it( 'should fire `change:value` event if the value of the token has changed', done => {
+			const tokenValue = getTestTokenValue();
 			const token = new Token( 'http://token-endpoint', { autoRefresh: false } );
 
 			token.on( 'change:value', ( event, name, newValue ) => {
-				expect( newValue ).to.equal( 'token-value' );
+				expect( newValue ).to.equal( tokenValue );
 
 				done();
 			} );
 
 			token.init();
 
-			requests[ 0 ].respond( 200, '', 'token-value' );
+			requests[ 0 ].respond( 200, '', tokenValue );
 		} );
 
 		it( 'should accept the callback in the constructor', () => {
@@ -62,98 +87,205 @@ describe( 'Token', () => {
 	} );
 
 	describe( 'init()', () => {
-		it( 'should get a token value from endpoint', done => {
+		it( 'should get a token value from the endpoint', done => {
+			const tokenValue = getTestTokenValue();
 			const token = new Token( 'http://token-endpoint', { autoRefresh: false } );
 
 			token.init()
 				.then( () => {
-					expect( token.value ).to.equal( 'token-value' );
+					expect( token.value ).to.equal( tokenValue );
 
 					done();
 				} );
 
-			requests[ 0 ].respond( 200, '', 'token-value' );
+			requests[ 0 ].respond( 200, '', tokenValue );
 		} );
 
 		it( 'should get a token from the refreshToken function when is provided', () => {
-			const token = new Token( () => Promise.resolve( 'token-value' ), { autoRefresh: false } );
+			const tokenValue = getTestTokenValue();
+			const token = new Token( () => Promise.resolve( tokenValue ), { autoRefresh: false } );
 
 			return token.init()
 				.then( () => {
-					expect( token.value ).to.equal( 'token-value' );
+					expect( token.value ).to.equal( tokenValue );
 				} );
 		} );
 
-		it( 'should start token refresh every 1 hour', done => {
-			const clock = sinon.useFakeTimers( { toFake: [ 'setInterval' ] } );
+		it( 'should not refresh token if autoRefresh is disabled in options', async () => {
+			const clock = sinon.useFakeTimers( { toFake: [ 'setTimeout' ] } );
+			const tokenInitValue = getTestTokenValue();
 
-			const token = new Token( 'http://token-endpoint', { initValue: 'initValue' } );
+			const token = new Token( 'http://token-endpoint', { initValue: tokenInitValue, autoRefresh: false } );
 
-			token.init()
-				.then( () => {
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
+			await token.init();
 
-					expect( requests.length ).to.equal( 5 );
+			await clock.tickAsync( 3600000 );
 
-					clock.restore();
+			expect( requests ).to.be.empty;
 
-					done();
-				} );
+			clock.restore();
+		} );
+
+		it( 'should refresh token with the time specified in token `exp` payload property', async () => {
+			const clock = sinon.useFakeTimers( { toFake: [ 'setTimeout' ] } );
+			const tokenInitValue = getTestTokenValue();
+
+			const token = new Token( 'http://token-endpoint', { initValue: tokenInitValue } );
+
+			await token.init();
+
+			await clock.tickAsync( 1800000 );
+			requests[ 0 ].respond( 200, '', getTestTokenValue( 1500 ) );
+
+			await clock.tickAsync( 750000 );
+			requests[ 1 ].respond( 200, '', getTestTokenValue( 900 ) );
+
+			await clock.tickAsync( 450000 );
+			requests[ 2 ].respond( 200, '', getTestTokenValue( 450 ) );
+
+			await clock.tickAsync( 225000 );
+			requests[ 3 ].respond( 200, '', getTestTokenValue( 20 ) );
+
+			await clock.tickAsync( 10000 );
+			requests[ 4 ].respond( 200, '', getTestTokenValue( 20 ) );
+
+			expect( requests.length ).to.equal( 5 );
+
+			clock.restore();
+		} );
+
+		it( 'should refresh the token with the default time if getting token expiration time failed', async () => {
+			const clock = sinon.useFakeTimers( { toFake: [ 'setTimeout' ] } );
+			const tokenValue = 'header.test.signature';
+
+			const token = new Token( 'http://token-endpoint', { initValue: tokenValue } );
+
+			await token.init();
+
+			await clock.tickAsync( 3600000 );
+			requests[ 0 ].respond( 200, '', tokenValue );
+
+			await clock.tickAsync( 3600000 );
+			requests[ 1 ].respond( 200, '', tokenValue );
+
+			expect( requests.length ).to.equal( 2 );
+
+			clock.restore();
+		} );
+
+		it( 'should refresh the token with the default time if the token payload does not contain `exp` property', async () => {
+			const clock = sinon.useFakeTimers( { toFake: [ 'setTimeout' ] } );
+			const tokenValue = `header.${ btoa( JSON.stringify( {} ) ) }.signature`;
+
+			const token = new Token( 'http://token-endpoint', { initValue: tokenValue } );
+
+			await token.init();
+
+			await clock.tickAsync( 3600000 );
+			requests[ 0 ].respond( 200, '', tokenValue );
+
+			await clock.tickAsync( 3600000 );
+			requests[ 1 ].respond( 200, '', tokenValue );
+
+			await clock.tickAsync( 3600000 );
+			requests[ 2 ].respond( 200, '', tokenValue );
+
+			expect( requests.length ).to.equal( 3 );
+
+			clock.restore();
 		} );
 	} );
 
 	describe( 'destroy', () => {
-		it( 'should stop refreshing the token', () => {
-			const clock = sinon.useFakeTimers( { toFake: [ 'setInterval', 'clearInterval' ] } );
-			const token = new Token( 'http://token-endpoint', { initValue: 'initValue' } );
+		it( 'should stop refreshing the token', async () => {
+			const clock = sinon.useFakeTimers( { toFake: [ 'setTimeout', 'clearTimeout' ] } );
+			const tokenInitValue = getTestTokenValue();
 
-			return token.init()
-				.then( () => {
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
+			const token = new Token( 'http://token-endpoint', { initValue: tokenInitValue } );
 
-					expect( requests.length ).to.equal( 2 );
+			await token.init();
 
-					token.destroy();
+			await clock.tickAsync( 1800000 );
+			requests[ 0 ].respond( 200, '', getTestTokenValue( 1500 ) );
+			await clock.tickAsync( 100 );
 
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
+			await clock.tickAsync( 750000 );
+			requests[ 1 ].respond( 200, '', getTestTokenValue( 900 ) );
+			await clock.tickAsync( 100 );
 
-					expect( requests.length ).to.equal( 2 );
-				} );
+			token.destroy();
+
+			await clock.tickAsync( 3600000 );
+			await clock.tickAsync( 3600000 );
+			await clock.tickAsync( 3600000 );
+
+			expect( requests.length ).to.equal( 2 );
+
+			clock.restore();
 		} );
 	} );
 
 	describe( 'refreshToken()', () => {
 		it( 'should get a token from the specified address', done => {
-			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+			const tokenValue = getTestTokenValue();
+			const token = new Token( 'http://token-endpoint', { autoRefresh: false } );
 
 			token.refreshToken()
 				.then( newToken => {
-					expect( newToken.value ).to.equal( 'token-value' );
+					expect( newToken.value ).to.equal( tokenValue );
 
 					done();
 				} );
 
-			requests[ 0 ].respond( 200, '', 'token-value' );
+			requests[ 0 ].respond( 200, '', tokenValue );
+		} );
+
+		it( 'should throw an error if the returned token is wrapped in additional quotes', done => {
+			const tokenValue = getTestTokenValue();
+			const token = new Token( 'http://token-endpoint', { autoRefresh: false } );
+
+			token.refreshToken()
+				.then( () => {
+					done( new Error( 'Promise should be rejected' ) );
+				} )
+				.catch( error => {
+					expect( error.constructor ).to.equal( CKEditorError );
+					expect( error ).to.match( /token-not-in-jwt-format/ );
+					done();
+				} );
+
+			requests[ 0 ].respond( 200, '', `"${ tokenValue }"` );
+		} );
+
+		it( 'should throw an error if the returned token is not a valid JWT token', done => {
+			const token = new Token( 'http://token-endpoint', { autoRefresh: false } );
+
+			token.refreshToken()
+				.then( () => {
+					done( new Error( 'Promise should be rejected' ) );
+				} )
+				.catch( error => {
+					expect( error.constructor ).to.equal( CKEditorError );
+					expect( error ).to.match( /token-not-in-jwt-format/ );
+					done();
+				} );
+
+			requests[ 0 ].respond( 200, '', 'token' );
 		} );
 
 		it( 'should get a token from the specified callback function', () => {
-			const token = new Token( () => Promise.resolve( 'token-value' ), { initValue: 'initValue', autoRefresh: false } );
+			const tokenValue = getTestTokenValue();
+			const token = new Token( () => Promise.resolve( tokenValue ), { autoRefresh: false } );
 
 			return token.refreshToken()
 				.then( newToken => {
-					expect( newToken.value ).to.equal( 'token-value' );
+					expect( newToken.value ).to.equal( tokenValue );
 				} );
 		} );
 
-		it( 'should throw an error when cannot download new token', () => {
-			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+		it( 'should throw an error when cannot download a new token', () => {
+			const tokenInitValue = getTestTokenValue();
+			const token = new Token( 'http://token-endpoint', { initValue: tokenInitValue, autoRefresh: false } );
 			const promise = token._refresh();
 
 			requests[ 0 ].respond( 401 );
@@ -167,7 +299,8 @@ describe( 'Token', () => {
 		} );
 
 		it( 'should throw an error when the response is aborted', () => {
-			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+			const tokenInitValue = getTestTokenValue();
+			const token = new Token( 'http://token-endpoint', { initValue: tokenInitValue, autoRefresh: false } );
 			const promise = token._refresh();
 
 			requests[ 0 ].abort();
@@ -180,7 +313,8 @@ describe( 'Token', () => {
 		} );
 
 		it( 'should throw an error when network error occurs', () => {
-			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+			const tokenInitValue = getTestTokenValue();
+			const token = new Token( 'http://token-endpoint', { initValue: tokenInitValue, autoRefresh: false } );
 			const promise = token._refresh();
 
 			requests[ 0 ].error();
@@ -192,8 +326,9 @@ describe( 'Token', () => {
 			} );
 		} );
 
-		it( 'should throw an error when the callback throws error', () => {
-			const token = new Token( () => Promise.reject( 'Custom error occurred' ), { initValue: 'initValue', autoRefresh: false } );
+		it( 'should throw an error when the callback throws an error', () => {
+			const tokenInitValue = getTestTokenValue();
+			const token = new Token( () => Promise.reject( 'Custom error occurred' ), { initValue: tokenInitValue, autoRefresh: false } );
 
 			token.refreshToken()
 				.catch( error => {
@@ -202,75 +337,39 @@ describe( 'Token', () => {
 		} );
 	} );
 
-	describe( '_startRefreshing()', () => {
-		it( 'should start refreshing', () => {
-			const clock = sinon.useFakeTimers( { toFake: [ 'setInterval' ] } );
-
-			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
-
-			token._startRefreshing();
-
-			clock.tick( 3600000 );
-			clock.tick( 3600000 );
-			clock.tick( 3600000 );
-			clock.tick( 3600000 );
-			clock.tick( 3600000 );
-
-			expect( requests.length ).to.equal( 5 );
-
-			clock.restore();
-		} );
-	} );
-
-	describe( '_stopRefreshing()', () => {
-		it( 'should stop refreshing', done => {
-			const clock = sinon.useFakeTimers( { toFake: [ 'setInterval', 'clearInterval' ] } );
-
-			const token = new Token( 'http://token-endpoint', { initValue: 'initValue' } );
-
-			token.init()
-				.then( () => {
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
-
-					token._stopRefreshing();
-
-					clock.tick( 3600000 );
-					clock.tick( 3600000 );
-
-					expect( requests.length ).to.equal( 3 );
-
-					clock.restore();
-
-					done();
-				} );
-		} );
-	} );
-
 	describe( 'static create()', () => {
-		it( 'should return a initialized token', done => {
+		it( 'should return an initialized token', done => {
+			const tokenValue = getTestTokenValue();
+
 			Token.create( 'http://token-endpoint', { autoRefresh: false } )
 				.then( token => {
-					expect( token.value ).to.equal( 'token-value' );
+					expect( token.value ).to.equal( tokenValue );
 
 					done();
 				} );
 
-			requests[ 0 ].respond( 200, '', 'token-value' );
+			requests[ 0 ].respond( 200, '', tokenValue );
 		} );
 
 		it( 'should use default options when none passed', done => {
-			const intervalSpy = sinon.spy( window, 'setInterval' );
+			const tokenValue = getTestTokenValue();
 
 			Token.create( 'http://token-endpoint' )
-				.then( () => {
-					expect( intervalSpy.args[ 0 ][ 1 ] ).to.equal( 3600000 );
+				.then( token => {
+					expect( token._options ).to.eql( { autoRefresh: true } );
 
 					done();
 				} );
 
-			requests[ 0 ].respond( 200, '', 'token-value' );
+			requests[ 0 ].respond( 200, '', tokenValue );
 		} );
 	} );
 } );
+
+// Returns valid token for tests with given expiration time offset.
+//
+// @param {Number} [timeOffset=3600000]
+// @returns {String}
+function getTestTokenValue( timeOffset = 3600 ) {
+	return `header.${ btoa( JSON.stringify( { exp: ( Math.floor( Date.now() / 1000 ) ) + timeOffset } ) ) }.signature`;
+}

+ 6 - 2
packages/ckeditor-cloud-services-core/tests/uploadgateway/fileuploader.js

@@ -14,7 +14,8 @@ const BASE_64_FILE = 'data:image/gif;base64,R0lGODlhCQAJAPIAAGFhYZXK/1FRUf///' +
 	'9ra2gD/AAAAAAAAACH5BAEAAAUALAAAAAAJAAkAAAMYWFqwru2xERcYJLSNNWNBVimC5wjfaTkJADs=';
 
 describe( 'FileUploader', () => {
-	const token = new Token( 'url', { initValue: 'token', autoRefresh: false } );
+	const tokenInitValue = `header.${ btoa( JSON.stringify( { exp: Date.now() + 3600000 } ) ) }.signature`;
+	const token = new Token( 'url', { initValue: tokenInitValue, autoRefresh: false } );
 
 	let fileUploader;
 
@@ -116,9 +117,12 @@ describe( 'FileUploader', () => {
 					expect( request.url ).to.equal( API_ADDRESS );
 					expect( request.method ).to.equal( 'POST' );
 					expect( request.responseType ).to.equal( 'json' );
-					expect( request.requestHeaders ).to.be.deep.equal( { Authorization: 'token' } );
+					expect( request.requestHeaders ).to.be.deep.equal( { Authorization: tokenInitValue } );
 
 					done();
+				} )
+				.catch( err => {
+					console.log( err );
 				} );
 
 			request.respond( 200, { 'Content-Type': 'application/json' },

+ 4 - 1
packages/ckeditor-cloud-services-core/tests/uploadgateway/uploadgateway.js

@@ -3,13 +3,16 @@
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  */
 
+/* eslint-env browser */
+
 import FileUploader from '../../src/uploadgateway/fileuploader';
 import UploadGateway from '../../src/uploadgateway/uploadgateway';
 import Token from '../../src/token/token';
 import { expectToThrowCKEditorError } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'UploadGateway', () => {
-	const token = new Token( 'url', { initValue: 'token', autoRefresh: false } );
+	const tokenInitValue = `header.${ btoa( JSON.stringify( { exp: Date.now() + 3600000 } ) ) }.signature`;
+	const token = new Token( 'url', { initValue: tokenInitValue, autoRefresh: false } );
 
 	describe( 'constructor()', () => {
 		it( 'should throw error when no token provided', () => {

+ 13 - 13
packages/ckeditor5-adapter-ckfinder/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@ckeditor/ckeditor5-adapter-ckfinder",
-  "version": "22.0.0",
+  "version": "23.0.0",
   "description": "CKFinder adapter for CKEditor 5.",
   "keywords": [
     "ckeditor",
@@ -10,20 +10,20 @@
     "ckeditor5-plugin"
   ],
   "dependencies": {
-    "@ckeditor/ckeditor5-core": "^22.0.0",
-    "@ckeditor/ckeditor5-upload": "^22.0.0"
+    "@ckeditor/ckeditor5-core": "^23.0.0",
+    "@ckeditor/ckeditor5-upload": "^23.0.0"
   },
   "devDependencies": {
-    "@ckeditor/ckeditor5-basic-styles": "^22.0.0",
-    "@ckeditor/ckeditor5-clipboard": "^22.0.0",
-    "@ckeditor/ckeditor5-editor-classic": "^22.0.0",
-    "@ckeditor/ckeditor5-enter": "^22.0.0",
-    "@ckeditor/ckeditor5-heading": "^22.0.0",
-    "@ckeditor/ckeditor5-image": "^22.0.0",
-    "@ckeditor/ckeditor5-list": "^22.0.0",
-    "@ckeditor/ckeditor5-paragraph": "^22.0.0",
-    "@ckeditor/ckeditor5-typing": "^22.0.0",
-    "@ckeditor/ckeditor5-undo": "^22.0.0"
+    "@ckeditor/ckeditor5-basic-styles": "^23.0.0",
+    "@ckeditor/ckeditor5-clipboard": "^23.0.0",
+    "@ckeditor/ckeditor5-editor-classic": "^23.0.0",
+    "@ckeditor/ckeditor5-enter": "^23.0.0",
+    "@ckeditor/ckeditor5-heading": "^23.0.0",
+    "@ckeditor/ckeditor5-image": "^23.0.0",
+    "@ckeditor/ckeditor5-list": "^23.0.0",
+    "@ckeditor/ckeditor5-paragraph": "^23.0.0",
+    "@ckeditor/ckeditor5-typing": "^23.0.0",
+    "@ckeditor/ckeditor5-undo": "^23.0.0"
   },
   "engines": {
     "node": ">=12.0.0",

+ 13 - 13
packages/ckeditor5-alignment/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@ckeditor/ckeditor5-alignment",
-  "version": "22.0.0",
+  "version": "23.0.0",
   "description": "Text alignment feature for CKEditor 5.",
   "keywords": [
     "ckeditor",
@@ -10,20 +10,20 @@
     "ckeditor5-plugin"
   ],
   "dependencies": {
-    "@ckeditor/ckeditor5-core": "^22.0.0",
-    "@ckeditor/ckeditor5-ui": "^22.0.0"
+    "@ckeditor/ckeditor5-core": "^23.0.0",
+    "@ckeditor/ckeditor5-ui": "^23.0.0"
   },
   "devDependencies": {
-    "@ckeditor/ckeditor5-block-quote": "^22.0.0",
-    "@ckeditor/ckeditor5-editor-classic": "^22.0.0",
-    "@ckeditor/ckeditor5-engine": "^22.0.0",
-    "@ckeditor/ckeditor5-enter": "^22.0.0",
-    "@ckeditor/ckeditor5-heading": "^22.0.0",
-    "@ckeditor/ckeditor5-image": "^22.0.0",
-    "@ckeditor/ckeditor5-list": "^22.0.0",
-    "@ckeditor/ckeditor5-paragraph": "^22.0.0",
-    "@ckeditor/ckeditor5-typing": "^22.0.0",
-    "@ckeditor/ckeditor5-utils": "^22.0.0"
+    "@ckeditor/ckeditor5-block-quote": "^23.0.0",
+    "@ckeditor/ckeditor5-editor-classic": "^23.0.0",
+    "@ckeditor/ckeditor5-engine": "^23.0.0",
+    "@ckeditor/ckeditor5-enter": "^23.0.0",
+    "@ckeditor/ckeditor5-heading": "^23.0.0",
+    "@ckeditor/ckeditor5-image": "^23.0.0",
+    "@ckeditor/ckeditor5-list": "^23.0.0",
+    "@ckeditor/ckeditor5-paragraph": "^23.0.0",
+    "@ckeditor/ckeditor5-typing": "^23.0.0",
+    "@ckeditor/ckeditor5-utils": "^23.0.0"
   },
   "engines": {
     "node": ">=12.0.0",

+ 14 - 14
packages/ckeditor5-autoformat/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@ckeditor/ckeditor5-autoformat",
-  "version": "22.0.0",
+  "version": "23.0.0",
   "description": "Autoformatting feature for CKEditor 5.",
   "keywords": [
     "ckeditor",
@@ -10,21 +10,21 @@
     "ckeditor5-plugin"
   ],
   "dependencies": {
-    "@ckeditor/ckeditor5-core": "^22.0.0",
-    "@ckeditor/ckeditor5-typing": "^22.0.0"
+    "@ckeditor/ckeditor5-core": "^23.0.0",
+    "@ckeditor/ckeditor5-typing": "^23.0.0"
   },
   "devDependencies": {
-    "@ckeditor/ckeditor5-basic-styles": "^22.0.0",
-    "@ckeditor/ckeditor5-block-quote": "^22.0.0",
-    "@ckeditor/ckeditor5-code-block": "^22.0.0",
-    "@ckeditor/ckeditor5-editor-classic": "^22.0.0",
-    "@ckeditor/ckeditor5-engine": "^22.0.0",
-    "@ckeditor/ckeditor5-enter": "^22.0.0",
-    "@ckeditor/ckeditor5-heading": "^22.0.0",
-    "@ckeditor/ckeditor5-list": "^22.0.0",
-    "@ckeditor/ckeditor5-paragraph": "^22.0.0",
-    "@ckeditor/ckeditor5-undo": "^22.0.0",
-    "@ckeditor/ckeditor5-utils": "^22.0.0"
+    "@ckeditor/ckeditor5-basic-styles": "^23.0.0",
+    "@ckeditor/ckeditor5-block-quote": "^23.0.0",
+    "@ckeditor/ckeditor5-code-block": "^23.0.0",
+    "@ckeditor/ckeditor5-editor-classic": "^23.0.0",
+    "@ckeditor/ckeditor5-engine": "^23.0.0",
+    "@ckeditor/ckeditor5-enter": "^23.0.0",
+    "@ckeditor/ckeditor5-heading": "^23.0.0",
+    "@ckeditor/ckeditor5-list": "^23.0.0",
+    "@ckeditor/ckeditor5-paragraph": "^23.0.0",
+    "@ckeditor/ckeditor5-undo": "^23.0.0",
+    "@ckeditor/ckeditor5-utils": "^23.0.0"
   },
   "engines": {
     "node": ">=12.0.0",

+ 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>' );
 

+ 5 - 5
packages/ckeditor5-autosave/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@ckeditor/ckeditor5-autosave",
-  "version": "22.0.0",
+  "version": "23.0.0",
   "description": "Autosave feature for CKEditor 5.",
   "keywords": [
     "ckeditor",
@@ -10,13 +10,13 @@
     "ckeditor5-plugin"
   ],
   "dependencies": {
-    "@ckeditor/ckeditor5-core": "^22.0.0",
-    "@ckeditor/ckeditor5-utils": "^22.0.0",
+    "@ckeditor/ckeditor5-core": "^23.0.0",
+    "@ckeditor/ckeditor5-utils": "^23.0.0",
     "lodash-es": "^4.17.15"
   },
   "devDependencies": {
-    "@ckeditor/ckeditor5-editor-classic": "^22.0.0",
-    "@ckeditor/ckeditor5-paragraph": "^22.0.0"
+    "@ckeditor/ckeditor5-editor-classic": "^23.0.0",
+    "@ckeditor/ckeditor5-paragraph": "^23.0.0"
   },
   "engines": {
     "node": ">=12.0.0",

+ 10 - 10
packages/ckeditor5-basic-styles/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@ckeditor/ckeditor5-basic-styles",
-  "version": "22.0.0",
+  "version": "23.0.0",
   "description": "Basic styles feature for CKEditor 5.",
   "keywords": [
     "ckeditor",
@@ -10,17 +10,17 @@
     "ckeditor5-plugin"
   ],
   "dependencies": {
-    "@ckeditor/ckeditor5-core": "^22.0.0",
-    "@ckeditor/ckeditor5-typing": "^22.0.0",
-    "@ckeditor/ckeditor5-ui": "^22.0.0"
+    "@ckeditor/ckeditor5-core": "^23.0.0",
+    "@ckeditor/ckeditor5-typing": "^23.0.0",
+    "@ckeditor/ckeditor5-ui": "^23.0.0"
   },
   "devDependencies": {
-    "@ckeditor/ckeditor5-editor-classic": "^22.0.0",
-    "@ckeditor/ckeditor5-engine": "^22.0.0",
-    "@ckeditor/ckeditor5-essentials": "^22.0.0",
-    "@ckeditor/ckeditor5-paragraph": "^22.0.0",
-    "@ckeditor/ckeditor5-remove-format": "^22.0.0",
-    "@ckeditor/ckeditor5-utils": "^22.0.0"
+    "@ckeditor/ckeditor5-editor-classic": "^23.0.0",
+    "@ckeditor/ckeditor5-engine": "^23.0.0",
+    "@ckeditor/ckeditor5-essentials": "^23.0.0",
+    "@ckeditor/ckeditor5-paragraph": "^23.0.0",
+    "@ckeditor/ckeditor5-remove-format": "^23.0.0",
+    "@ckeditor/ckeditor5-utils": "^23.0.0"
   },
   "engines": {
     "node": ">=12.0.0",

+ 14 - 14
packages/ckeditor5-block-quote/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@ckeditor/ckeditor5-block-quote",
-  "version": "22.0.0",
+  "version": "23.0.0",
   "description": "Block quote feature for CKEditor 5.",
   "keywords": [
     "ckeditor",
@@ -10,21 +10,21 @@
     "ckeditor5-plugin"
   ],
   "dependencies": {
-    "@ckeditor/ckeditor5-core": "^22.0.0",
-    "@ckeditor/ckeditor5-ui": "^22.0.0",
-    "@ckeditor/ckeditor5-utils": "^22.0.0"
+    "@ckeditor/ckeditor5-core": "^23.0.0",
+    "@ckeditor/ckeditor5-ui": "^23.0.0",
+    "@ckeditor/ckeditor5-utils": "^23.0.0"
   },
   "devDependencies": {
-    "@ckeditor/ckeditor5-basic-styles": "^22.0.0",
-    "@ckeditor/ckeditor5-editor-classic": "^22.0.0",
-    "@ckeditor/ckeditor5-engine": "^22.0.0",
-    "@ckeditor/ckeditor5-enter": "^22.0.0",
-    "@ckeditor/ckeditor5-heading": "^22.0.0",
-    "@ckeditor/ckeditor5-image": "^22.0.0",
-    "@ckeditor/ckeditor5-list": "^22.0.0",
-    "@ckeditor/ckeditor5-paragraph": "^22.0.0",
-    "@ckeditor/ckeditor5-table": "^22.0.0",
-    "@ckeditor/ckeditor5-typing": "^22.0.0"
+    "@ckeditor/ckeditor5-basic-styles": "^23.0.0",
+    "@ckeditor/ckeditor5-editor-classic": "^23.0.0",
+    "@ckeditor/ckeditor5-engine": "^23.0.0",
+    "@ckeditor/ckeditor5-enter": "^23.0.0",
+    "@ckeditor/ckeditor5-heading": "^23.0.0",
+    "@ckeditor/ckeditor5-image": "^23.0.0",
+    "@ckeditor/ckeditor5-list": "^23.0.0",
+    "@ckeditor/ckeditor5-paragraph": "^23.0.0",
+    "@ckeditor/ckeditor5-table": "^23.0.0",
+    "@ckeditor/ckeditor5-typing": "^23.0.0"
   },
   "engines": {
     "node": ">=12.0.0",

File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/ckeditor.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/ckeditor.js.map


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/ar.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/ast.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/az.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/bg.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/cs.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/da.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/de.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/el.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/en-au.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/en-gb.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/eo.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/es.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/et.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/eu.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/fa.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/fi.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/fr.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/gl.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/he.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/hr.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/hu.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/id.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/it.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/ja.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/km.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/kn.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/ko.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/ku.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/lt.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/lv.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/nb.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/ne.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/nl.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/no.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/pl.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/pt-br.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/pt.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/ro.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/ru.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/si.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/sk.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/sq.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/sr-latn.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/sr.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/sv.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/th.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/tr.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/ug.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/uk.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/vi.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/zh-cn.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon-block/build/translations/zh.js


+ 22 - 22
packages/ckeditor5-build-balloon-block/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@ckeditor/ckeditor5-build-balloon-block",
-  "version": "22.0.0",
+  "version": "23.0.0",
   "description": "The balloon editor build of CKEditor 5 with a block toolbar – the best browser-based rich text editor.",
   "keywords": [
     "wysiwyg",
@@ -25,29 +25,29 @@
     "build"
   ],
   "devDependencies": {
-    "@ckeditor/ckeditor5-adapter-ckfinder": "^22.0.0",
-    "@ckeditor/ckeditor5-autoformat": "^22.0.0",
-    "@ckeditor/ckeditor5-basic-styles": "^22.0.0",
-    "@ckeditor/ckeditor5-block-quote": "^22.0.0",
-    "@ckeditor/ckeditor5-ckfinder": "^22.0.0",
-    "@ckeditor/ckeditor5-core": "^22.0.0",
+    "@ckeditor/ckeditor5-adapter-ckfinder": "^23.0.0",
+    "@ckeditor/ckeditor5-autoformat": "^23.0.0",
+    "@ckeditor/ckeditor5-basic-styles": "^23.0.0",
+    "@ckeditor/ckeditor5-block-quote": "^23.0.0",
+    "@ckeditor/ckeditor5-ckfinder": "^23.0.0",
+    "@ckeditor/ckeditor5-core": "^23.0.0",
     "@ckeditor/ckeditor5-dev-utils": "^20.0.0",
     "@ckeditor/ckeditor5-dev-webpack-plugin": "^20.0.0",
-    "@ckeditor/ckeditor5-easy-image": "^22.0.0",
-    "@ckeditor/ckeditor5-editor-balloon": "^22.0.0",
-    "@ckeditor/ckeditor5-essentials": "^22.0.0",
-    "@ckeditor/ckeditor5-heading": "^22.0.0",
-    "@ckeditor/ckeditor5-image": "^22.0.0",
-    "@ckeditor/ckeditor5-indent": "^22.0.0",
-    "@ckeditor/ckeditor5-link": "^22.0.0",
-    "@ckeditor/ckeditor5-list": "^22.0.0",
-    "@ckeditor/ckeditor5-media-embed": "^22.0.0",
-    "@ckeditor/ckeditor5-paragraph": "^22.0.0",
-    "@ckeditor/ckeditor5-paste-from-office": "^22.0.0",
-    "@ckeditor/ckeditor5-table": "^22.0.0",
-    "@ckeditor/ckeditor5-typing": "^22.0.0",
-    "@ckeditor/ckeditor5-theme-lark": "^22.0.0",
-    "@ckeditor/ckeditor5-ui": "^22.0.0",
+    "@ckeditor/ckeditor5-easy-image": "^23.0.0",
+    "@ckeditor/ckeditor5-editor-balloon": "^23.0.0",
+    "@ckeditor/ckeditor5-essentials": "^23.0.0",
+    "@ckeditor/ckeditor5-heading": "^23.0.0",
+    "@ckeditor/ckeditor5-image": "^23.0.0",
+    "@ckeditor/ckeditor5-indent": "^23.0.0",
+    "@ckeditor/ckeditor5-link": "^23.0.0",
+    "@ckeditor/ckeditor5-list": "^23.0.0",
+    "@ckeditor/ckeditor5-media-embed": "^23.0.0",
+    "@ckeditor/ckeditor5-paragraph": "^23.0.0",
+    "@ckeditor/ckeditor5-paste-from-office": "^23.0.0",
+    "@ckeditor/ckeditor5-table": "^23.0.0",
+    "@ckeditor/ckeditor5-typing": "^23.0.0",
+    "@ckeditor/ckeditor5-theme-lark": "^23.0.0",
+    "@ckeditor/ckeditor5-ui": "^23.0.0",
     "postcss-loader": "^3.0.0",
     "raw-loader": "^4.0.1",
     "style-loader": "^1.2.1",

File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/ckeditor.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/ckeditor.js.map


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/ar.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/ast.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/az.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/bg.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/cs.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/da.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/de.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/el.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/en-au.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/en-gb.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/eo.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/es.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/et.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/eu.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/fa.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/fi.js


File diff suppressed because it is too large
+ 1 - 1
packages/ckeditor5-build-balloon/build/translations/fr.js


+ 0 - 0
packages/ckeditor5-build-balloon/build/translations/gl.js


Some files were not shown because too many files changed in this diff