The easy questions to answer: Why?

Why switch from CKEditor 4?
It’s approaching its end-of-life in 2023.
Why CKEditor 5 and not something else?
Successful past collaboration, healthy project, clearly significantly better than its predecessor, and also: time constraint. See the core policy issue where this was decided.
Why now?
The CKEditor 5 module needs to be stable in the last Drupal 9 minor if we want to be able to deprecate CKEditor 4 (ckeditor.module) before Drupal 10, so we can remove CKEditor 4 in Drupal 10.

Biggest challenge: Frictionless upgrade path

For Drupal 9 users, the transition must be a simple, painless process to switch from CKEditor 4 to 5 using nothing more than the UI.

For Drupal 10 users, when ckeditor.module is dropped from Drupal core, the result must be exactly the same as if they used the UI.

In both cases, the automatically generated CKEditor 5 configuration must be:

  • Correct (result in a working CKEditor 5 instance)
  • Accurate (match the CKEditor 4 configuration as closely as possible, and ensure all HTML tags allowed actually work more about that later)
  • Actionable (whenever there is functionality that cannot be migrated automatically, we require precise error messages that allow the user to efficiently investigate potential solutions)

To achieve that, we need a detailed automatic analysis of the “before” (CKEditor 4 + text format configuration) and “after” (CKEditor 5 + text format configuration).

Biggest risk: Data loss

Imagine switching from CKEditor 4 to 5 and noticing that certain content either:

  • bad: does not appear anymore in the text editor
  • worse: did appear in the text editor, but does not appear anymore in the output after having fixed a typo in CKEditor 5

This is a real risk, because CKEditor 4 and 5 have a different architecture.

CKEditor 4 used browsers’ APIs, so it automatically supported every HTML tag, because browsers support those. This caused cross-browser compatibility issues and maintenance difficulties (since different browsers have different features and bugs).

CKEditor 5 reimplements many low-level APIs in JavaScript. This simplifies their code, makes it easier to test, and makes for a more reliable end result. However, this adds challenges for Drupal because CKEditor 5 does not support every HTML tag by default.

Support for Full HTML

A few months ago, CKSource released a plugin called General HTML Support. This allows us to let CKEditor 5 render arbitrary HTML, but not to edit arbitrary HTML.

The Drupal CKEditor 5 module uses this to support the Full HTML use case: #3216021: Automatically use CKE5's General HTML Support feature on text formats without any TYPE_HTML_RESTRICTOR filter + add `sourceEditing` button.

Tags unsupported by CKEditor 5

Drupal allows restricting allowed tags to an arbitrary set of tags, while CKEditor 5 only supports a subset of HTML 5 tags. For example, Drupal allows <dl> <dt> <dd> by default in Basic HTML, but CKEditor 5 does not support them.

To address this, the CKEditor 5 Drupal module allows configuring additional “manually editable tags” when using the “Source Editing” button (“View Source” in CKEditor 4), so we can track explicitly which tags and attributes are editable only by editing the HTML source. These tags will then work similarly to how they do in CKEditor 4 and Drupal 9 (as they already did not have buttons available in CKEditor 4).

Biggest win: Massively improved toolbar configuration UX

Also see the “Plugin developer DX” section below.

We need excellent user experience when content editors create a new text format and use CKEditor 5, but also when they switch to and modify CKEditor 5’s configuration.

An essential usability feature of CKEditor 4 is that the text format configuration was kept in sync with the CKEditor configuration. CKEditor 4 used a hidden CKEditor 4 instance in the toolbar configuration UI to get metadata, which then updated filter_html’s “Allowed HTML tags” form field with JavaScript. 🙃😱 This was brittle and buggy, especially following #2549077: Allow the "Limit allowed HTML tags" filter to also restrict HTML attributes, and only allow a small whitelist of attributes by default. CKEditor 4 also has no protection against enabling filters that conflict with it! Related bug reports:

All of that is solved in CKEditor 5.

As a site builder, you get real-time validation errors:

Filters for non-HTML markup trigger an immediate validation error.

After removing those filters, if there are HTML restrictions being applied that do not need the fundamental requirements of CKEditor 5, an immediate validation error is also triggered.

Biggest change: No Drupal dialogs in CKEditor anymore

There are no longer Drupal-owned dialog forms to add/edit links or images, which is a usability and maintainability improvement, but will require certain contrib modules change their implementation. See: #3231341: Deprecate EditorLinkDialog, EditorImageDialog and EditorMediaDialog in Drupal 10.1 for removal in Drupal 11

Screenshot of CKEditor 5 built-in dialog replacement

Architecture

Plugin developer DX: less PHP (or even no PHP), more YAML/JS

Plugin definitions require little Drupal/PHP knowledge with clearly delineated ckeditor5 and drupal sections. There are helpful messages when the plugin definition does not work.

With CKEditor 4, a JavaScript developer would also need to learn a lot about PHP and Drupal just to get their (custom or publicly available) CKEditor plugin working in Drupal. With CKEditor 5 in Drupal, that same JavaScript developer would have to learn almost nothing about Drupal and only would need to rely on CKEditor's API documentation.

This is the most minimal valid CKEditor 5 plugin definition:

MODULE_NAME_marquee:
  ckeditor5:
    plugins: [PACKAGE.CLASS]
  drupal:
    label: Marquee
    elements:
      - <marquee>

Validation constraints for config

The frictionless upgrade path requires metadata about CKEditor 5 plugins (because those are written in JS, and we cannot automatically infer that metadata from PHP code) and their functionality. This metadata is used for validation (for both the upgrade path and the configuration UI), in addition to generating a CKEditor 5 configuration that supports a given set of HTML tags (as mentioned earlier).

This means that the logical way to implement validation is at the configuration entity level. Drupal 8 and 9 core only include limited use of config validation. So this means that CKEditor 5 also has had to solve reusing config schema validation constraints in a form-based UI. See: #3231342: [PP-2] Introduce ConfigEntityForm to standardize use of validation constraints for config entities.

CKEditor 5’s validation constraints fall in two buckets:

Fundamental compatibility between a configured CKEditor 5 and the associated text format
  1. A text format must not use any FilterInterface::TYPE_MARKUP_LANGUAGE filters as these indicate a custom markup language (like Markdown) rather than HTML.
  2. <p> and <br> must be allowed — without them, CKEditor 5 cannot function correctly (nor can CKEditor 4).
  3. The HTML allowed by the text format’s HTML filter configuration must exactly match the HTML that can be generated by the current CKEditor 5 configuration. We compare the HTML restrictions of a text format with FilterFormatInterface::getHtmlRestrictions() for the drupal.elements values of all enabled plugins in CKEditor 5.
Valid CKEditor 5 configuration
It is validated that:
  1. All toolbar items in the configuration actually exist. (Uses the drupal.toolbar_items entry in the metadata example above.)
  2. All enabled plugins that are configurable actually have configuration.
  3. All “Manually editable tags” added to the “Source Editing” plugin’s configuration are a) valid expressions, b) not present in any of the enabled plugins (illustrated in the screenshot below), c) not present in any of the available plugins.
    Screenshot of what happens when the user adds a manually editable tag that is already supported by an enabled CKEditor 5 plugin.

Strict config schema conformance is required.

Many of these validation constraints are impossible to violate when using the UI, but migrations are risky, and the constraints help ensure that both config exports and the migration path are correct.

Note: The “fundamental compatibility” validation constraint needs to validate fundamental compatibility between an Editor config entity and its associated FilterFormat config entity.
These are currently two distinct pieces of configuration (merging them would simplify things a lot: #3231354: [PP-2] [META] Discuss: merge the Editor config entity into the FilterFormat config entity). Since validation constraints can never span multiple entities, we had to work around that limitation: \Drupal\ckeditor5\Plugin\Editor\CKEditor5::validatePair().

Smart Default Settings

When enabled, CKEditor 5 generates smart default settings based on:

  1. The old CKEditor 4 configuration, if this text format/editor was using it. The toolbar button order and grouping are retained, as is plugin configuration.
  2. A new group of buttons is added to make the exact HTML restrictions of this text format (FilterFormatInterface::getHTMLRestrictions()) match the pre-configured HTML precisely.

So you go from this default “Basic HTML” text format in Drupal 8|9:

Screenshot of the default CKEditor 4 toolbar configuration in Drupal 8 and 9 for the Basic HTML text format.

To this automatically generated equivalent for CKEditor 5 in Drupal 9|10, with messages explaining what happened:

Screenshot of the automatically generated CKEditor 5 toolbar configuration from the previous screenshot. Messages are present explaining what happened.

Toolbar configuration UX

Configuring the CKEditor toolbar must have a simple and fully accessible user experience.

Using the richer available metadata (see the drupal.elements metadata above!), we can:

  • Automatically generate a sensible CKEditor 5 configuration, based on both the old CKEditor 4 configuration (if any) and the set of allowed HTML tags!
  • Guarantee that it is a valid configuration and that it works.

(We challenge you to break it: even the “Restricted HTML” text format will give you helpful warnings that you need to remove the the \Drupal\filter\Plugin\FilterInterface::TYPE_MARKUP_LANGUAGE type filters for it to be possible to use CKEditor 5).

We also reimplemented the drag-and-drop toolbar configuration UX people used to love for CKEditor 4. Ourc CKEditor 5 implementation of this is less brittle than the jQuery code in core/modules/ckeditor/js/ckeditor.admin.es6.js, which came with a hidden CKEditor 4 instance to get the necessary metadata. It’s a tiny decoupled JS app.

Dependency evaluation

CKEditor 5 and the required tooling included as part of the integration require a total of 390 packages as a dependency. These are listed on this ​file.

ckeditor5, ckeditor5-dev-utils

  • Maintainership of the package: CKEditor 5 is maintained professionally by CKSource.
  • Security policies of the package: Security policies are documented in the repository.
  • Expected release and support cycles: Major releases are shipped every couple of months. Minor releases are shipped more frequently. Only one major release is supported at once. Note that CKEditor 5 is not following semver. Their versioning policy mention that minor releases could include "minor" BC breaking changes.
  • Code quality: CKEditor 5 code quality is excellent and the project has very good test coverage.
  • Other dependencies it would add, if any: many additional dependencies
  • webpack, webpack-cli, raw-loader, terser-webpack-plugin

    • Maintainership of the package
      These packages are maintained by the webpack community. Most of the core team members and contributors in the ecosystem do the work in their free time. However, they have pretty solid funding on Open Collective.
    • Security policies of the package: Security policies are documented in the Webpack repository.
    • Expected release and support cycles: Major releases are happening only every few years. Minor and patch releases are coming at a steady pace. I couldn't find whether Webpack 4.0.0 (the previous major release) is still supported. However, they supported it for at least 6 months since the release of Webpack 5.0.0.
    • Code quality: We haven't had the need to evaluate Webpack code base because they have very solid documentation, and it has worked out of the box without any issues for all of our use cases.
    • Other dependencies it would add, if any: many additional dev dependencies.

    JSDOM

    Provides the ability to use Nightwatch for JavaScript unit testing.

    • Maintainership of the package: it is partnered with Tidelift, has multiple maintainers, many of whom are visibly active on the most recent page of commit history. The openbase stats suggest the library is frequently attended. In an informal review of open issues (18% of total issues filed remain open), none of the ones that have been open for more than a few weeks appear pressing. Many of these are feature requests or performance improvements. Issues that require prompt turnaround are attended to properly.
    • Security policies of the package: jsdom has Tidelift as their security contact, and reports are made directly to Tidelift. The specifics of Tidelift’s policy cover most Drupal-relevant concerns. The report process is confidential and security releases are carefully coordinated. Security updates are limited to the current version: A maintainer confirmed "No previous releases are supported. As a volunteer project, we only ever support the latest-released version. No backports will be performed."
    • Expected release and support cycles: No official release cycles, but commits and releases are frequent (but not unexpectedly so - it’s a familiar frequency for popular modern JS libraries) up to 3 major releases can happen in a year. As confirmed by a project maintainer only the current release is supported.
    • Code quality: code is quite readable, eslint ruleset extends a maintainers already extensive config, the test coverage is extensive
    • Other dependencies: Yes, but jsdom is itself a dev dependency of Drupal and not present in runtime so the following are listed for reference but not subjected to individual dependency evaluations:
      "dependencies": {
          "abab": "^2.0.5",
          "acorn": "^8.5.0",
          "acorn-globals": "^6.0.0",
          "cssom": "^0.5.0",
          "cssstyle": "^2.3.0",
          "data-urls": "^3.0.1",
          "decimal.js": "^10.3.1",
          "domexception": "^4.0.0",
          "escodegen": "^2.0.0",
          "form-data": "^4.0.0",
          "html-encoding-sniffer": "^3.0.0",
          "http-proxy-agent": "^5.0.0",
          "https-proxy-agent": "^5.0.0",
          "is-potential-custom-element-name": "^1.0.1",
          "nwsapi": "^2.2.0",
          "parse5": "6.0.1",
          "saxes": "^5.0.1",
          "symbol-tree": "^3.2.4",
          "tough-cookie": "^4.0.0",
          "w3c-hr-time": "^1.0.2",
          "w3c-xmlserializer": "^3.0.0",
          "webidl-conversions": "^7.0.0",
          "whatwg-encoding": "^2.0.0",
          "whatwg-mimetype": "^3.0.0",
          "whatwg-url": "^10.0.0",
          "ws": "^8.2.3",
          "xml-name-validator": "^4.0.0"
        },

    Roadmap to stable

    👉 #3238333: Roadmap to CKEditor 5 stable in Drupal 9

CommentFileSizeAuthor
#87 interdiff.txt1.71 KBbnjmnm
#87 3231364-87.patch2.85 MBbnjmnm
#86 interdiff.txt1.22 KBlauriii
#86 ckeditor5-86.patch2.86 MBlauriii
#85 ckeditor5-82.patch2.85 MBwim leers
#85 interdiff.txt229.65 KBwim leers
#77 ckeditor5-77.patch2.85 MBwim leers
#77 interdiff.txt487 byteswim leers
#76 ckeditor5-76.patch2.85 MBwim leers
#76 interdiff.txt79.17 KBwim leers
#73 ckeditor5-73.patch2.82 MBwim leers
#73 interdiff.txt93.51 KBwim leers
#72 interdiff.txt193.11 KBwim leers
#71 ckeditor5-71.patch2.81 MBwim leers
#69 interdiff.txt2.81 KBwim leers
#69 ckeditor5-69.patch2.78 MBwim leers
#68 ckeditor5-68.patch2.77 MBwim leers
#67 ckeditor5-67.patch2.77 MBwim leers
#67 interdiff.txt2.7 MBwim leers
#58 ckeditor5-58.patch2.7 MBwim leers
#58 interdiff.txt133.76 KBwim leers
#49 ckeditor5-49.patch2.65 MBwim leers
#49 interdiff.txt1019.51 KBwim leers
#37 Screen Shot 2021-09-09 at 1.29.35 PM.png35.31 KBwebchick
#37 Screen Shot 2021-09-09 at 1.27.39 PM.png546.32 KBwebchick
#37 Screen Shot 2021-09-09 at 1.19.00 PM.png16.52 KBwebchick
patch-error.png244.3 KBvikashsoni
#28 ckeditor5-28.patch2.32 MBwim leers
#28 interdiff.txt3 KBwim leers
#27 interdiff.txt13.26 KBwim leers
#27 ckeditor5-26.patch2.32 MBwim leers
#25 interdiff.txt1.08 KBwim leers
#25 ckeditor5-25.patch2.32 MBwim leers
#23 ckeditor5-23.patch2.32 MBwim leers
#23 interdiff.txt4.97 KBwim leers
3227826-25-core.patch223.33 KBwim leers
#20 interdiff.txt119.94 KBwim leers
#20 ckeditor5-19.patch2.32 MBwim leers
#3 ckeditor5-2.patch2.31 MBwim leers
cke5_basic_html_automatic.png448.53 KBwim leers
cke4_basic_html.png212.87 KBwim leers
cke5_detailed_validation_of_source_editable_tags.png271.09 KBwim leers
cke5_dialogless_link_editing.png23.35 KBwim leers
cke5_real_time_validation2.png148.25 KBwim leers
cke5_real_time_validation1.png130.62 KBwim leers

Comments

Wim Leers created an issue. See original summary.

Wim Leers credited Reinmar.

wim leers’s picture

Status: Active » Needs review
StatusFileSize
new2.31 MB

This represents months and months of work by many wonderful people in https://www.drupal.org/project/ckeditor5! 😊😊

It also is in no small part thanks to the wonderful people at https://ckeditor.com/ — without whom this would not be possible. Special thanks to @Reinmar for always making time for us!

wim leers’s picture

(FYI: the generating of this patch is automated — see #3227826: Preparation for moving CKEditor 5 to core.)

xjm credited Luke.Leber.

xjm credited bnjmnm.

xjm credited caldenjacobs.

xjm credited gabesullice.

xjm credited larowlan.

xjm credited lauriii.

xjm credited longwave.

xjm credited tim.plunkett.

xjm credited zrpnr.

xjm’s picture

xjm credited antojose.

xjm’s picture

ghost of drupal past’s picture

While this is lovely, reading

There are no longer Drupal-owned dialog forms to add/edit links or images,

made me wonder how will media library and entity embed fare. The answer is in #3201824: Roadmap to core. The most important parts of media/media library apparently are already ready.

wim leers’s picture

StatusFileSize
new2.32 MB
new119.94 KB

Clearly it'd have been wiser to first open a test-only issue to first get the patch green. But we've been developing with Drupal core's core/scripts/dev/commit-code-check.sh running for us (patched, of course, since it only works for Drupal core). That made us think it'd work on the first try. Clearly not 🙈😅

This fixes the cspell violations, and a bunch of other test failures that we found by temporarily disabling the core commit checks. We still expect this to fail, because this introduces one big change: instead of keeping the CKEditor 5 build in core/modules/ckeditor5/js/…, we move it to core/assets/vendor/… — which exempts it from many checks. Let's see if I got that right 🤞 (That also explains the huge interdiff.)

Built using #3227826-24: Preparation for moving CKEditor 5 to core, using CKEditor 5 module commit 8a8c4580417427d7644f66e218a0e7cc677f4cdd. (The patch in #2 was using commit f4906174b1d0fdd394a1648b35179c19019834a4.)

daffie’s picture

Status: Needs review » Needs work

Testbot is not happy.

wim leers’s picture

StatusFileSize
new4.97 KB
new2.32 MB

Two *.es6.js complaints remained. Fixed.

Built using #3227826-26: Preparation for moving CKEditor 5 to core, still using commit 8a8c4580417427d7644f66e218a0e7cc677f4cdd .

daffie’s picture

FAILURE core/modules/ckeditor5/tests/modules/ckeditor5_test/js/build/layercake.js does not have a corresponding core/modules/ckeditor5/tests/modules/ckeditor5_test/js/build/layercake.es6.js

Testbot is still not happy.

wim leers’s picture

StatusFileSize
new2.32 MB
new1.08 KB

Indeed, not yet happy. Because I confused eslint compliance with ES6ification compliance.

Built using #3227826-28: Preparation for moving CKEditor 5 to core, still using commit 8a8c4580417427d7644f66e218a0e7cc677f4cdd .

wim leers’s picture

StatusFileSize
new2.32 MB
new13.26 KB

This should fix most failures!

Built using #3227826-36: Preparation for moving CKEditor 5 to core, using commit 545040f7d1fe9eff138e2daa2dc1f5edb2aa8cab. Upstream commit history since the previous build:

* 545040f7d1fe9eff138e2daa2dc1f5edb2aa8cab Issue #3231550 by Wim Leers: Follow-up for #3205654: make hook_help() comply with the format expected by Drupal core
* ca63aa841f0714ba5fad2c2de7e24863ff3a9618 Issue #3231402 by Wim Leers: Work around ConfigImportAllTest somehow calling config schema alter hooks before config schema is imported
* 14c4ca67e32221278eb6ebc46d209b6739acf2cc Issue #3231427 by lauriii, johnwebdev: Changing basic HTML format to CKEditor 5 results in CKEditorError: plugincollection-plugin-not-found {"plugin":null} on fresh install

→ adding credit for @johnwebdev :)

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new3 KB
new2.32 MB

This should fix the remaining failures.

Built using #3227826-39: Preparation for moving CKEditor 5 to core (thanks @lauriii!), using commit 411c7358a3404d11ff1e2f0c1a638f43b37f072a. Upstream commit history since the previous build:

* 411c7358a3404d11ff1e2f0c1a638f43b37f072a Issue #3231718 by Wim Leers: Make ckeditor5_dev_hook_help() comply with the format expected by Drupal core
wim leers’s picture

The 2.32 MB patch size might scare people away. ~75% of that is for the core/assets and core/yarn.lock changes. I think moving that part into a separate issue may be helpful — but I'll first await some initial reviews before doing that :)

shaal’s picture

For those interested in taking CKeditor5 on Drupal 9.3.x for a spin,

I created a snapshot, using DrupalPod -

  • Applied patch #28
  • Installed Umami profile
  • Enabled CKEditor 5 + CKEditor 5 Dev Tools modules
  • Updated Basic HTML & Full HTML to use CKeditor5 as editor

Username: admin
Password: admin

Click on the following link to open it -
When you see Gitpod's login screen, choose "Continue with Github".
https://gitpod.io#snapshot/ec39baf4-f241-40be-a7fe-e28163922a0e

larowlan’s picture

It would be good to verify that the new API will support modules like linkit and editor advanced link that have close to 200k installs between them.

Can we articulate a path forward for those modules - perhaps by creating an issue in their queue (if one doesn't exist) with guidance on how the update will look for them

I think without Ckeditor5 compatible versions of those modules, many will be blocked from updating, so this will be a barrier to adoption of D10.

wim leers’s picture

#30: Thanks! :)

#31: On it.

#29: release manager @xjm indicated that it'd be better to hold off on that for now because it otherwise may need to be removed if the CKEditor 5 module is still alpha-level stability at the time when 9.3.0-rc1 gets tagged. So, holding off on creating that separate issue.

We will instead from now post multiple patches: ckeditor5-CID.patch (includes everything) ckeditor5_assets_only-CID-do-not-commit.patch (assets only) and ckeditor5_module_only-CID-do-not-commit.patch.

wim leers’s picture

duaelfr’s picture

Hey! Great job here as usual! ;)
I created issues on both Editor Advanced Link and Editor File upload.
I might have some time during the DrupalCon Europe. We'll see ;)

wim leers’s picture

#34: Wow, thanks for creating that! Added comment with relevant information from the CKEditor 5 team from the meeting earlier today: #3232052-2: Drupal 10 & CKEditor 5 readiness.

#31: See #34 and the above update for it, plus #3232190: CKEditor 5 readiness for LinkIt. In short: they're aware of this need, but so far they've managed to not have to support it. There are significant implications for focus state/accessibility, real-time collaboration conflict handling, et cetera. @lauriii and I discussed various potential approach with @Reinmar. He'll provide us with an update in ~2 weeks (September 23, 2021).
TL;DR: we're blocked on news from upstream to really make progress on this front. They understand how important this is to Drupal, and are prioritizing getting these aspects unblocked.

Related: we opened #3231341: Deprecate EditorLinkDialog, EditorImageDialog and EditorMediaDialog in Drupal 10.1 for removal in Drupal 11 a while ago for this.

webchick’s picture

*cracks knuckles* Greetings! It's time for round 1 of WebChickTestCase! :D (This means I'm going in blind, without reading the rest of the issue, so I can experience things as a new user. Apologies if this repeats anything said already above.)

To test this, I used the GitPod link mentioned in #30. Firefox 91.0.2 (64-bit) on MacOS Catalina 10.15.7 (19H1323).

First thing I noticed is this CKEditor-specific toolbar added itself to my screen on any page with an editor on it. I'm assuming this is because there is a debug mode on or something in this patch? But would presumably need to be removed prior to commit.

CKEditor-specific toolbar

Initially things worked great—Bold, Italic, Blockquote, Link (nice UX for that!), etc.—then I tried to add a media item. (Cue ominous music. :D) It seemed to upload and add a new image fine, but when trying to press the "Insert selected" button, nothing happens. :( I get some JS errors in the console...

Insert selected button doesn't press; JS errors appear.

Uncaught CKEditorError: t.forEach is not a function
Read more: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-t.forEach is not a function
    o https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/drupal/drupalMedia.js?qz2p04:1
    s https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/drupal/drupalMedia.js?qz2p04:1
    viewToDom https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    viewChildrenToDom https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    viewToDom https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    viewChildrenToDom https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    _updateChildren https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
ckeditor5-dll.js:5:457291

Uncaught CKEditorError: cannot-change-view-tree
Read more: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html#error-cannot-change-view-tree
    i https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    change https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    Q https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    fire https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    _handleChangeBlock https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    _runPendingChanges https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
    change https://8080-gold-reindeer-hwtkum5u.ws-us16.gitpod.io/core/assets/vendor/ckeditor5/build/ckeditor5-dll.js?v=29.0.0:5
ckeditor5-dll.js:5:457291

And then after this, nothing seems to work... the toolbar is greyed out apart from the media button. :(

No toolbar for you

So... needs work, or I need to fix something on my end, but leaving at "needs review" so as not to spook off other potential reviewers.

xjm’s picture

Edit: Disregard for now, missed a step...

xjm’s picture

I was able to reproduce #37 using the contrib module's latest code. Steps I took:

  1. Installed Umami from 9.3.x HEAD and the CKEditor 5 contrib module from its current branch tip.
  2. Went to en/admin/config/content/formats/add.
  3. Created a text format called "CKE5test:
    • Accessible to anonymous and authenticated users
    • Using CKEditor 5 as the WYSIWYG
    • Checked "Limit allowed HTML tags and correct faulty HTML"
    • Checked "Embed media"
    • Dragged the "Drupal Media" button into the CKEditor toolbar.
    • Under the "Embed media" vertical tab, checked "image" as a media type and "Default" as a view mode. (Aside: Why on earth does this not have sensible defaults, instead of everything unchecked by default? Not CKE's problem, but definitely a UX issue.)
  4. Saved the configuration.
  5. Navigated to en/node/add/article.
  6. Changed the text format to CKE5test.
  7. Clicked the media button.
  8. Selected some delicious-looking brownies.
  9. Clicked "Insert selected". Nothing happened. JS console showed the same error:
    Uncaught TypeError: t.forEach is not a function
        at o (drupalMedia.js?qz8fa3:1)
        at g.render (drupalMedia.js?qz8fa3:1)
        at w.viewToDom (ckeditor5-dll.js?v=29.0.0:5)
        at w.viewChildrenToDom (ckeditor5-dll.js?v=29.0.0:5)
        at viewChildrenToDom.next (<anonymous>)
        at w.viewToDom (ckeditor5-dll.js?v=29.0.0:5)
        at w.viewChildrenToDom (ckeditor5-dll.js?v=29.0.0:5)
        at viewChildrenToDom.next (<anonymous>)
        at Function.from (<anonymous>)
        at m._updateChildren (ckeditor5-dll.js?v=29.0.0:5)
    
  10. Closed the dialog using the [x]. No media appeared to be inserted.
  11. Changed the text format back to Basic HTML (which uses CKE4 in Umami).
  12. When I did this, my brownies appeared, proving that they were added to the source despite the insert button doing nothing.

This means that this is only a major bug (not a critical one) since there is a workaround of exiting out of the dialog and toggling away from the editor. Still stable-blocking for sure IMO since this the media integration is a key feature.

xjm’s picture

luke.leber’s picture

I ran into something that was a bit confusing -- it may even be considered data loss? It seems that at least 'class' attributes are stripped from h4, h5, and h6 elements, but are seemingly persisted with h2 and h3 elements?

Steps to reproduce:

  1. Install Drupal 9.3.x
  2. Install ckeditor5
  3. Create a text format and ensure the following plugins are added to the toolbar:

    1. Headings
    2. Source
  4. Leave the "Enabled Headings" plugin settings default (h2, h3, h4, h5, h6).
  5. Leave the "Manually editable HTML tags" plugin settings blank.
  6. Save the text format.

Next...

  1. Edit a piece of content with the text format.
  2. Add a h2 element via the headings plugin.
  3. Enter source mode and give it a class of "test".
  4. Exit source mode.
  5. Via the headings plugin, change the h2 to an h3.
  6. Enter source mode and observe that the class "test" is still there.
  7. Exit source mode.
  8. Via the headings plugin, change the h3 to an h4.
  9. Enter source mode and observe that the class "test" is gone!.
  10. Exit source mode.
  11. Via the headings plugin, change the h4 to an h3.
  12. Enter source mode.
  13. Observe that the class "test" is now back!

See https://www.awesomescreenshot.com/video/5086163?key=09c1158229f0884b9d36... for a visual demo.

Overall, I'm liking the CKEditor5 UX. Keep up the good work :)

luke.leber’s picture

I suppose that on the flip-side, there's also a discrepancy between the "Limit allowed HTML tags and correct faulty HTML" filter and what actually happens when content is saved.

The (read-only textarea) allowed HTML tags in the setup in #41 are: <br> <p> <h2> <h3> <h4><h5><h6>, yet h2 and h3 seem to still allow the class attribute?

Saving

 <h2 class="test" id="whoa">Test</h2>

seems to render the attributes to the front-end just fine when the content renders.

lauriii’s picture

I was able to reproduce the problem from #41 on a text format without HTML filter and I opened new issue for that #3233425: [upstream] h4, h5, and h6 fail to downcast GHS added attributes. However, I'm reading #42 so that the HTML filter was enabled when #41 was tested.

@Luke.Leber would you be able to export your text format and text editor configuration? That could be helpful for investigating this.

luke.leber’s picture

re: #43 - I'll have availability tomorrow afternoon to export and provide the configuration. It seems like this might be a good candidate for a separate issue, so I'll open a new one in the ckeditor5 project's issue queue. The comments in #42 apply to both before and after enabling the filter. The attributes were happily rendered to the frontend in both scenarios, only raising my eyebrow when the filter was enabled.

It could very well be that the read-only text area that outlines the allowed elements/attributes isn't accurate. I honestly find it hard to believe that ckeditor would be rendering stuff to the frontend that wasn't explicitly downcasted (or is it upcasted? I mix the two up!).

luke.leber’s picture

re: #44 - Here's where my source of confusion came from! The real problem here is that the "Limit allowed HTML tags and correct faulty HTML" read-only text area can appear in the filter settings UI without actually checking the box to enable the filter.

I think this issue might be a lot more trivial than originally thought, not being a filter problem at all, but just a confusing UX when setting up a new editor instance.

To reproduce:

  1. Navigate to /admin/config/content/formats/add
  2. Select 'ckeditor5' as the text editor
  3. Observe that the Allowed HTML tags read-only text-area is part of the "Filter settings" fieldset.
  4. Save the configuration
  5. Configure the new text editor
  6. Observe that when the page loads, the Allowed HTML tags is no longer part of the "Filter settings" fieldset.
  7. Enable Heading 1
  8. Observe that the Allowed HTML tags read-only text-area is now part of the "Filter settings" fieldset.

In the steps above, the "Limit allowed HTML tags and correct faulty HTML" option under "Enabled filters" was never checked.

I would have expected to not see the filter settings appear until the filter was actually enabled.

droplet’s picture

I'm coming from #3233491: Create process for reviewing changes in 3rd party JavaScript dependencies

1. What reasons make it must build from DrupalCore? (eg. Assumed it helps a bit of the contrib development, is it must? and involved how many developers? less than 1%?)
2. Why not use this method: #3211214: Using a monorepo with workspaces for Standalone Core JS packages
3. If the above doesn't work, can we do this way: https://github.com/vuejs/vue/tree/dev/packages

yash.rode’s picture

lauriii’s picture

#46.1 The current patch is simply built based on following pre-existing core policies. I guess as part of #3233491: Create process for reviewing changes in 3rd party JavaScript dependencies we could introduce changes to our policies that would make something like what you're proposing possible.

#46.2 We actually started with a structure where the JavaScript was decoupled from the Drupal module. It was very hard to maintain the JavaScript in a separate project because the JavaScript code in the libraries was heavily coupled with the Drupal module. Because the library was so heavily coupled with the Drupal module, it wasn't possible to test the libraries without the Drupal module. See #3216255: Move admin UI build process into module for #3215005: Move custom CKEditor 5 drupal plugins into module for context.

wim leers’s picture

Issue summary: View changes
StatusFileSize
new1019.51 KB
new2.65 MB

#37: the CKEditor-specific toolbar you mentioned: I think you installed the CKEditor 5 developer tools 🤓

#37#40: Fixed in #3232409: Media Embed button is broken. (I agree with the aside in #40 ;))

#41#43: @lauriii reproduced this and confirmed this is an upstream CKEditor 5 bug, for which he filed an issue too: https://github.com/ckeditor/ckeditor5/issues/10539 👍 The CKEditor 5 team is really grateful for our bug reports 😊

#44 + #45 + #47: Fixed in #3236648: The "Limit allowed HTML tags and correct faulty HTML" option under "Enabled filters" was never checked still shows the filter settings for it.

#46: to add to what @lauriii already wrote in #48: we can absolutely change this in the future. But there already are some huge hurdles that we have to overcome here. 😅 Innovating on Drupal's JS package handling isn't one that we should put in the critical path. 🙏


Built using #3227826-42: Preparation for moving CKEditor 5 to core using commit 686cce684c3edc7874db11ece8149a8bcf702b3a. Upstream commit history since the previous build:

* 686cce684c3edc7874db11ece8149a8bcf702b3a Issue #3236648 by Wim Leers, yash.rode, Luke.Leber: The "Limit allowed HTML tags and correct faulty HTML" option under "Enabled filters" was never checked still shows the filter settings for it
* def76f5ad12fcab6ac1acf63cd0848fba3c0cd34 Issue #3227875 by yash.rode, lauriii, Wim Leers: update mapping of CKEditor 4 to 5 toolbar items to support ckeditor5-remove-format
* 54a659b752892f2358dbb6c3c246698e34787120 Issue #3227890 by yash.rode, Wim Leers, lauriii: Add ckeditor5-special-characters to allow inserting special characters for users that do not know the native picker
* 9709e8c213e2f2908b48b257f440d8d0fa1cb03b Issue #3232409 by yash.rode, Wim Leers, webchick: Media Embed button is broken
* 670d8bb7032be81eb32bdf35affb7be217df8daa Issue #3227875 by yash.rode, Wim Leers, lauriii: Add ckeditor5-remove-format to allow removing formatting from pasted content

New since last time: #3227890: Add ckeditor5-special-characters to allow inserting special characters for users that do not know the native picker + #3227875: Add ckeditor5-remove-format to allow removing formatting from pasted content. These bring us closer to complete feature parity. Only a few issues remain. Which reminds me: we have not yet moved the roadmap issue into Drupal core. Did that just now: #3238333: Roadmap to CKEditor 5 stable in Drupal 9.

catch’s picture

This is tagged with release manager review, I'm happy to review anything that has specific release management questions, but overall I think the pressing thing is to get this committable and into 9.3.x, so that we can deprecate ckeditor 4 and remove it from Drupal 10. The biggest concern I have is how robust the upgrade path will be on real sites - but again a core experimental module is the way to flush out problems there.

#3233491: Create process for reviewing changes in 3rd party JavaScript dependencies we need to figure out a plan for, but it's not a new issue introduced by this patch, and any theoretical issues resulting from it are less likely than an unpatched ckeditor4 vulnerability once it's out of support, so it shouldn't be a blocker here.

wim leers’s picture

The biggest concern I have is how robust the upgrade path will be on real sites - but again a core experimental module is the way to flush out problems there.

💯

This is why I focused my time on that very question since I started working on this in earnest ~3 months ago! 😊

It's why we use config validation constraints to help guarantee correct configuration, and why we have the concept of "smart default settings" (see \Drupal\ckeditor5\SmartDefaultSettings).

It's why we (in particular @bnjmnm!) spent a lot of time on making the UX of using the UI to switch from CKEditor 4 to CKEditor 5 over at /admin/config/content/formats/manage/* solid and informative, so that people testing it now (before the upgrade to Drupal 10) are informed in detail of the what and why. We can choose how (or even if) to expose those messages to the end user when it happens automatically when upgrading from 9 to 10.

It's why we have \Drupal\Tests\ckeditor5\Kernel\SmartDefaultSettingsTest in particular: it provides 6 different testing scenarios (3 that cover Drupal 8's default text formats without changes: basic_html + restricted_html + full_html, plus two with high-impact changes to basic_html and finally one that tests a text format that uses only filter_html with its default settings). If I were you, I'd focus my attention (or at least start with) scrutinizing that test. If you have a suspicion that edge cases X or Y are not handled, it's going to be trivial for us to expand test coverage there.

For upgrade path robustness, what remains to be done there is:

  1. #3226335: Follow-up for #3216015: allow contrib & custom Drupal modules providing CKEditor 4 plugins to specify their CKEditor 5 equivalents + settings to be migrated, because currently only core's CKEditor 4 buttons + settings can be migrated (see \Drupal\ckeditor5\SmartDefaultSettings::mapCKEditor4ToolbarButtonToCKEditor5ToolbarItem() + \Drupal\ckeditor5\SmartDefaultSettings::createSettingsFromCKEditor4()). We of course want contrib modules (which provide additional CKEditor 4 plugins, buttons and settings) to be able to specify an upgrade path as well.
  2. #3226694: Follow-up for #3216015: refactor SmartDefaultSettings to return messages rather than sending them
wim leers’s picture

@catch: Clearly #50 is from the release manager POV, what would you write from the framework manager POV? 🤓

catch’s picture

@Wim Leers: nothing from a framework manager point of view yet, because I haven't reviewed yet.

Once #3226335: Follow-up for #3216015: allow contrib & custom Drupal modules providing CKEditor 4 plugins to specify their CKEditor 5 equivalents + settings to be migrated is fixed, what happens when a site tries to update, but a plugin it uses hasn't implemented an upgrade path?

wim leers’s picture

what happens when a site tries to update, but a plugin it uses hasn't implemented an upgrade path?

Any buttons for which no upgrade path is defined will be dropped.

Any plugin settings for which no upgrade path is defined will be dropped.

Most importantly: 100% of the stored HTML will still be editable after the migration, thanks to the Source Editing plugin getting enabled when needed.

catch’s picture

What happens if the plugin later adds an upgrade path and you enable it, will the old markup get upgraded on the fly, or is it stuck in edit source?

wim leers’s picture

What happens if the plugin later adds an upgrade path and you enable it, will the old markup get upgraded on the fly, or is it stuck in edit source?

Not sure I follow. So I'll just explain the different aspects:

  1. At absolutely no time ever do we need to "upgrade the old markup". We do not change the markup, ever. The old markup remains the same before and after the CKEditor 5 plugin gets used. It's just edited through a nicer UX instead of by manually editing the source.
  2. If the plugin adds an upgrade path later, meaning after you've already upgraded to CKEditor 5, we will not re-run the upgrade path — the user might've already customized it since then.
  3. The user can manually add this plugin/toolbar item though, when it becomes available.

    In fact, when it becomes available, they'll be notified explicitly: they'll get the SourceEditingRedundantTagsConstraint::$availablePluginsMessage validation error which says: The following tag(s) are already supported by available plugins and should not be added to the Source Editing "Manually editable HTML tags" field. Instead, enable the following plugins to support these tags: %overlapping_tags..

    If they then actually add this newly available toolbar item, they'll get the SourceEditingRedundantTagsConstraint::$enabledPluginsMessage validation error which says: The following tag(s) are already supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: %overlapping_tags..

    (Both scenarios have test coverage in ValidatorsTest — see the INVALID Source Editable tag already provided by plugin and another available in a not enabled plugin test case.)


Let's apply this to a concrete example: imagine there's a marquee button to add <marquee> markup in Drupal 9, and you've got filter_html configured to only allow <p> <br> <strong> <marquee>. No upgrade path is defined for it at the time the site upgrades from Drupal 9 to 10. This means that a Editor config entity with these settings will be generated during the upgrade:

      'settings' => [
        'toolbar' => [
          'items' => [
            'bold',
            'sourceEditing',
          ],
        ],
        'plugins' => [
          'ckeditor5_sourceEditing' => [
            'allowed_tags' => [
              '<marquee>',
            ],
          ],
        ],
      ],

(<p> <br> are supported by CKEditor 5 core — you cannot disable them. <strong> is supported by bold. <marquee> is supported by nothing, which is why we're explicitly adding it to the list of Manually editable tags that the sourceEditing plugin allows you to configure. If you put all of that together, you can see that CKEditor 5 can generate and edit exactly the set of HTML tags that the text format's HTML restrictions allow 👍)

Then, once a marquee button becomes available that supports that tag, you'd first get that first message when interacting with your text format/editor in the UI. To fix it, you'd add the marquee button:

      'settings' => [
        'toolbar' => [
          'items' => [
            'bold',
            'sourceEditing',
            'marquee',
          ],
        ],
        'plugins' => [
          'ckeditor5_sourceEditing' => [
            'allowed_tags' => [
              '<marquee>',
            ],
          ],
        ],
      ],

(This is the state immediately after dragging that toolbar item into the "active toolbar" in the UI.) You still won't be able to save it though. You'll get that second message now! You'll have to manually remove that tag, which means you're now in this state:

      'settings' => [
        'toolbar' => [
          'items' => [
            'bold',
            'sourceEditing',
            'marquee',
          ],
        ],
        'plugins' => [
          'ckeditor5_sourceEditing' => [
            'allowed_tags' => [],
          ],
        ],
      ],

Now you will be able to save the text editor. You can choose to remove the sourceEditing button, or you can keep it to edit your other markup — there are just no additional allowed tags specified.

In other words: the module does nudge you towards doing the right thing: it nudges you towards using plugins instead of Manually editable HTML tags — because the user experience is way worse there.

wim leers’s picture

@lauriii and I met with @Reinmar from the CKEditor 5 team yesterday. Meeting notes available.

Outcomes:

  1. editor_advanced_link and linkit portability were our top concerns. The challenge here is that we'd love for those two modules to not need a clunky Drupal form/dialog anymore. It's clunky (form-based UI instead of the elegant and less in-your-face balloon UI of CKE5 and slow (requires a round trip to the server). But … that's the ideal. If need be, there's no reason we can't fall back to that for those scenarios.

    So here are the next steps:

    1. @laurii will pair with CKE5's Oleq early next week to investigate how to override the link actions view: autocomplete (for LinkIt)+ button to trigger dialog (for Editor Advanced Link). If that fails:
    2. Allow Drupal modules to signal they want to use EditorLinkDialog instead of CKE5’s link.
    3. Drupal to override the CKE5 Link plugin to not trigger the CKE5-native balloon link UI and instead trigger Drupal’s EditorLinkDialog when that signal is present. Pointers:
      https://github.com/ckeditor/ckeditor5/blob/ab03609f2c599ed4aa9ee758d1e14...
      + https://github.com/ckeditor/ckeditor5/blob/ab03609f2c599ed4aa9ee758d1e14...
    4. IN THE FUTURE use a better CKE5-integrated UX, potentially using new APIs in CKE5. (It's very complicated to make their existing, super compact linking UI extensible while retaining good accessibility and usability, not to mention API supportability.)

    (BTW, I provided a patch for what is implementable today: #3232052-5: Drupal 10 & CKEditor 5 readiness. But the above is necessary to port 100% of their functionality.)

  2. Work has begun on <ol start> support! 🥳
  3. The CKE5 port of the CKE4 StylesCombo plugin will start after this! 🥳
  4. They're prioritizing the major bugs we found: https://github.com/ckeditor/ckeditor5/issues/10505 + https://github.com/ckeditor/ckeditor5/issues/10539.
wim leers’s picture

StatusFileSize
new133.76 KB
new2.7 MB

Aaand … everything I wrote in #51 wrt upgrade path has been completed in https://www.drupal.org/project/ckeditor5! :)

Built using #3227826-44: Preparation for moving CKEditor 5 to core using commit bf5df30c36153131e56b2ca11c1148007645aa92 against 9da1866da41f0bfcdb90e1f8901ce8919549f189 in 9.3.x. Upstream commit history since the previous build:

* bf5df30c36153131e56b2ca11c1148007645aa92 Issue #3228920 by yash.rode, Wim Leers: Improve internal consistency: consistent variable names and return type syntax
* a645cc086e0c3dd95ab670ef78418ab19fda5527 Issue #3226335 by Wim Leers, lauriii: Follow-up for #3216015: allow contrib & custom Drupal modules providing CKEditor 4 plugins to specify their CKEditor 5 equivalents + settings to be migrated
* 40dd5a9f57c59292a672cb856983c229058a1bda Issue #3231327 by Wim Leers, lauriii: Plugin definition DX: validate ckeditor5.drupal.elements items
* 68f2d9ebb126899f84f6011d92d024055e38d938 Issue #3226694 by Wim Leers, bnjmnm: Follow-up for #3216015: refactor SmartDefaultSettings to return messages rather than sending them
* 58bc66be9ec24462f4bc1c7d27026e2ac5f5846a Issue #3229433 by bnjmnm, Wim Leers, lauriii, nod_, tim.plunkett: Post-devue js directory refactoring
* c8bcd03b1c0b21d1ed8d6ebd53caeb99fa95d24e Issue #3231325 by Wim Leers, lauriii, yash.rode: Use pre-existing filter format config from YAML instead of duplicating it in PHP
* 459961596f38b49c9ed314c56a1709d6291e56f7 Issue #3239376 by Wim Leers: [unbreak tests] SA-CORE-2021-009 broke tests
* f91e0e68264b80948ca48645cb62e53a4d906154 Issue #3227871 by yash.rode, Wim Leers: Add ckeditor5-paste-from-office to allow pasting from Microsoft Office & Google Docs
* c66c65ceea0d9b37ef7d69a6893951f5a15cbdaf Issue #3201186 by Wim Leers: Create ckeditor5.api.php (the core equivalent of README.md) + CKEditor5PluginDefinition::toArray()

New and notable since last time: upgrade path (as mentioned before), #3227871: Add ckeditor5-paste-from-office to allow pasting from Microsoft Office & Google Docs (again closer to complete feature parity!), ckeditor5.api.php, improved DX.

tim.plunkett’s picture

Add missing tag

wim leers’s picture

It's been very quiet here. But we've not been idle.

We've been pushing forward the CKEditor 5 module itself, fixing more edge cases, adding more tests, and so on. Mid next-week, there will be a new CKEditor 5 release. Once that's out, we'll be able to address a few things we've been unable to address.

But at least equally crucially, we've been pushing forward the two most popular CKEditor 4-integrating contrib modules: https://www.drupal.org/project/linkit and https://www.drupal.org/project/editor_advanced_link.

Editor Advanced Link

We've been working with the CKEditor 5 team to figure out a way to bring the Editor Advanced Link experience to CKEditor 5 without having to sacrifice the superior CKEditor 5 linking experience (which does not rely on a Drupal-rendered dialog, which is very prone to network latency).

@lauriii collaborated with https://github.com/oleq to get that to work:

And then I worked on the automatic upgrade path, which was just completed:

Linkit

Here too we've been working with the CKEditor 5 team! Again @lauriii has been collaborating with https://github.com/oleq, and again with great results:

This is using https://www.drupal.org/project/a11y_autocomplete (which will soon replace jQuery UI Autocomplete in Drupal core — see #3076171: Provide a new library to replace jQuery UI autocomplete). That's right; we're reusing Drupal JS components in our CKEditor 5 integration, and it required zero hacks. 🤩 However, the Linkit module's use of jQuery UI autocomplete was actually pretty advanced … so advanced that it was doing things https://www.drupal.org/project/a11y_autocomplete could not yet do. That's why @lauriii, @bnjmnm and @nod_ have been collaborating for the past few weeks on this, and it's actually been a great way to validate the work in a11y_autocomplete: this is a prominent, high-profile use case, and they've been expanding API support in several ways to enable the LinkIt use case!

In particular, Linkit needs grouping and richer results, which you can see in this screenshot from its project page:
Current LinkIt autocomplete UI

Cheer them on in #3245114: Allow grouping search results, #3243749: normalizeSuggestionItems() handles additional properties inconsistently and other issues in that project. This is an unexpectedly nice coincidence where we're validating one thing by working on another! 🥳

larowlan’s picture

Awesome news and work folks!

ambient.impact’s picture

I'll also add awesome work! 🎉

tim.plunkett’s picture

@webchick and I spent time going through this together, and identified 4 concerns (2 of which already had issues open!)

First there was a question about "what are CKE plugins?" and "do I need to know?" prompted by the messages upon switching an existing editor:
#3245967: Messages upon switching to CKEditor 5 are overwhelming

There was some wonkiness with the Image Upload checkbox that is being fixed here (already RTBC):
#3245320: Automatic upgrade path always disables image uploads — in the UI

Hit some issues with editing the markup in Source mode that is covered here:
#3229174: Making changes directly in the source view drops the made changes on save
This was fixed in upstream, and the new release came out today so that will be fixed in this MR shortly.

In our testing of pasting in a tweet (with accompanying <script> tag), we hit this bug:
https://github.com/ckeditor/ckeditor5/issues/9659
Which could be addressed by usage of the "HTML Embed" plugin:
#3245950: [upstream] <script> tag support in GHS

webchick’s picture

Yep, as Tim mentioned we kicked the tires on this pretty hard yesterday, for over an hour. I'm especially impressed with how nice the new version looks/feels, and the a11y of the toolbar config UI. :)

Most of my review centered on:

  1. What is the experience going to be like of a user who was not privy to this background issue and use of the CKE5 contrib module ahead of time? This module only actually does something if you first enable it, THEN navigate all the way over to Admin > Config > Formats or whatever. Fortunately, this is covered by the Help page attached to the module section, so that's great. If we clean up the PILE O' MESSAGES on the config form and help explain new terminology, even better.
  2. Are there any outstanding functional bugs? The only two we discovered are both covered by existing issues, one of which is RTBC, the other of which is dealt with by "update to the latest version." 👍
  3. How does it deal with "edge cases" like manually inserting disallowed tags, switching input formats, etc. Everything seemed to be in proper order here, and we jumped back and forth between CKE4 v 5 quite a bit to compare/contrast behaviour.
  4. How will sites with existing content be affected? Heeeeere we did run into some rubs...

It is quite common for people to use "Full HTML" to do things like copy/pasting an ad code into a sidebar block, or putting Twitter embeds in the middle of an article, or what have you. Under the current behaviour:

  • All "pre-existing" content is untouched and continues to work fine. 👍
  • However, upon editing any existing content, any disallowed HTML tags/attributes, including <script> are completely stripped from the content, and after saving, the original markup is irretrievable. This leads to data loss. :(
  • The same will happen for new content as well (this condition is exacerbated by #3229174: Making changes directly in the source view drops the made changes on save); once you flip out of Source mode to WYSIWYG mode and back, the disallowed tags are gone.

Tim and I went back and forth about what to do about this... warn people before they save something with disallowed tags, and direct them to add (or more likely get an admin to add) the tags to the HTML filter? (Definitely not ideal; we don't have an existing interaction pattern for this, and in 99% of cases the content author getting the error can do nothing about it.) Make "Full HTML" truly "Full HTML" and add literally ALL of the possible tags/attributes to any format with the "Skip HTML processing" (or whatever that option's called) bit on so it strips nothing? Or if not doing that, at least allowing <script> tags in those cases? (Definitely not ideal from a security/design standpoint; if anything, we want fewer tags people can shoot themselves in the foot with.) Etc.

I said that my Product Manager sign-off for Beta was conditional on figuring out a path forward for that problem. #3245950: [upstream] <script> tag support in GHS sounds like a very solid approach to me, that also potentially addresses a usability problem in addition to solving the data loss problem, while retaining security. I would make that a Stable blocker, but would rather get this out in front of people with that documented as a known issue than block this feature for an entire release on figuring it out.

Product Management sign-off: complete. :)

larowlan’s picture

Fwiw most of our clients would be ok with the stripping of invalid html, it's not that different to what CKEditor 4 is doing when we've configured allowed tags. In most enterprise settings there is no full HTML and stripping non allowed html attributes and tags is a required feature. So I think it's a good idea to get this in front of people with that known issue listed.

catch’s picture

Another option if you have a limited set of content with full HTML and complex markup you don't want stripped is to disable ckeditor on that text format entirely (if it's not already). Agreed this shouldn't be a blocker to inclusion as an experimental module at all.

wim leers’s picture

StatusFileSize
new2.7 MB
new2.77 MB

Since #60, we now also have a fully operational linkit module with CKEditor 5: both UX and upgrade path. See #3232190-12: CKEditor 5 readiness and later. It looks like this:

Built using #3227826-50: Preparation for moving CKEditor 5 to core using commit 8031f5b7198cfc6b7ca30b4451934b48bb890e32 against 9da1866da41f0bfcdb90e1f8901ce8919549f189 in 9.3.x. Upstream commit history since the previous build:

* 8031f5b7198cfc6b7ca30b4451934b48bb890e32 Issue #3206522 by Wim Leers, yash.rode, effulgentsia: Add FunctionalJavascript test coverage for media library
* 2073a9468d7220f5d2d0b7b4368cc3fcdb9f43c9 Issue #3245942 by lauriii, Wim Leers: Update CKEditor 5 to 31.0.0
* a0a865ebfa813350231bc7898b432794c174bfd7 Issue #3228505 by Wim Leers, lauriii: Plugin definition DX: automatically check for plugin definitions whether their ::getDefaultSettings() matches the config schema
* bc5ca00c8b5698fae2ac81bb417224b81e6e39b2 Issue #3245320 by Wim Leers, lauriii: Automatic upgrade path always disables image uploads — in the UI
* bcbe107fbd8e8c45f1eb24dc846f8d885095bcf7 Issue #3231362 by Wim Leers, lauriii: Refactor ImageUpload's ::validateImageUploadSettings() into the proper validate and submit methods
* ade0c4dff5c5f60c18aad51da3b32818e4514006 Issue #3231289 by Wim Leers, lauriii: Follow-up for #3230447: since optimizing admin UI, messages can accumulate
* 21a2680ce4a7ae5593f9e68c99e9b8a950770adc Issue #3245723 by Wim Leers, lauriii: Follow-up for #3201637: omitting PrimitiveTypeConstraint violations for filter settings is implemented too broadly
* 2443628abebf3e671afca90890f07f9d5a1d46bc Issue #3245807 by Wim Leers, lauriii: DX: allow contrib modules to subclass \Drupal\Tests\ckeditor5\Kernel\ValidatorsTest
* 231adf93d22dfc82b196990498b2b24943056f5f Issue #3245735 by Wim Leers, lauriii: Follow-up for #3222852: validation errors are not associated with the correct form element
* 25c1719eb147fff4fbd3eb78285ec7f6d46ef8d3 Issue #3245772 by Wim Leers: Update CKEditor5AllowedTagsTest following the commit of #2763075 into Drupal 9.3
* 4b9b4955674cda948d4a43c96eacec629dcf5a5c Issue #3245390 by Wim Leers, effulgentsia: CKEditor5::validatePair() and CKEditor5PluginManager::getPluginConfiguration() throw inconsistent exception types
* cacfb842bad00cf688c92e160233e27945f39aa1 Issue #3245387 by Wim Leers, effulgentsia: CKEditor5 has an empty settingsForm() method that neither inherits from nor is called by anything
* c4e005cea07ac3998f343f872f26261b27544be8 Issue #3245079 by Wim Leers, lauriii: Automatic upgrade path always enables all <h*> tags when only >=1 was enabled before
* 5c4433a14fd3b003cbf5e2fb726145f96fb192ec Issue #3244911 by Wim Leers, lauriii: Automatic upgrade path failing when CKEditor 4 has the StylesCombo plugin configured
* 835b8fba6451ebfea9ef429e421967483718911f Issue #3231327 by Wim Leers, lauriii: Plugin definition DX: validate ckeditor5.drupal.elements items
* c4dd59351cc9b5d4b94452b5f3f25d6334540aff Issue #3243850 by Wim Leers, effulgentsia: hook_ckeditor5_plugin_info_alter()'s example sets ['drupal']['config'], but that's not one of the documented definition properties

New and notable since last time: hardened upgrade path (and also now proven further thanks to working upgrade paths for linkit and editor_advanced_link), functional JS test coverage for media/media library (#3206522: Add FunctionalJavascript test coverage for media library), improved DX, and we're on CKEditor 5 https://github.com/ckeditor/ckeditor5/releases/tag/v31.0.0 now 😊

Thanks, @effulgentsia for filing a whole bunch of issues in https://www.drupal.org/project/ckeditor5, we've addressed some but not yet all.

wim leers’s picture

StatusFileSize
new2.77 MB

#3226052: Update to cspell 5 was committed while I was creating #67 🥸

Built using #3227826-51: Preparation for moving CKEditor 5 to core using commit 8031f5b7198cfc6b7ca30b4451934b48bb890e32 against 3eba4b3c583e94b3e2306ca0c141251e0939d7b1 in 9.3.x. No upstream commits.

wim leers’s picture

StatusFileSize
new2.78 MB
new2.81 KB

#68 applied cleanly, but failed on cspell (not surprising since it just was changed), but also on a bunch of phpcs violations, which is surprising, because https://www.drupal.org/project/ckeditor5 is explicitly using core's commit-code-check.sh 🤔Also, #2909370: Fix 'Drupal.Commenting.VariableComment.IncorrectVarType' coding standard just landed, which causes new phpcs violations.

I cannot reproduce those failures: #3233107-3: [ignore, testing issue] Fake bug report 😬 So instead I worked on a PoC fix, tested it in a helper issue, and am now confident it will be green here too.

Built using #3227826-51: Preparation for moving CKEditor 5 to core using commit a587204ef3678612991237bf5a5dc8b5e6cf7a6c against 3eba4b3c583e94b3e2306ca0c141251e0939d7b1 in 9.3.x. Upstream commit history since the previous build:

* a587204ef3678612991237bf5a5dc8b5e6cf7a6c Issue #3246448 by Wim Leers: Fix cspell & phpcs failures caused by both becoming more strict
larowlan’s picture

we now also have a fully operational linkit module with CKEditor 5: both UX and upgrade path

Wow! That is amazing and will be a huge win for D10 uptake - thank you!

wim leers’s picture

StatusFileSize
new2.81 MB

Highlights since #69:

I believe the following issues should still block commit, and 2/3 are very close; all should land early next week:

  1. #3246524: Make more (all?) classes @internal
  2. #3246169: Embedded media are not linkable through UI; already linked embedded media are unlinked (data loss!)
  3. #3246280: Defense in depth: add anti-CSRF token to this module's routes

Built using #3227826-58: Preparation for moving CKEditor 5 to core using commit 07dbfdc24c0cf332c40a7d379d5d7f816324e723 against 707121c9cc46266be7d922b5ff096f07cb9461ee in 9.3.x. Upstream commit history since the previous build:

* 07dbfdc24c0cf332c40a7d379d5d7f816324e723 Issue #3222808 by lauriii, Wim Leers, longwave, effulgentsia, Reinmar: Follow-up for #3201646: markup in image captions is lost
* 78888b4b378b914e7906c263e551cd2c40ef924d Issue #3229174 by lauriii, Wim Leers, rkoller, tim.plunkett, webchick: Making changes directly in the source view drops the made changes on save
* 53a6bbe4dbf66a793bb00258bb836944ae81757f Issue #3247246 by lauriii, Wim Leers: Attribute value encoding not compatible with Xss::filter()
* 55cb04ce3119c1ac7abdb4e307ad75794c97f8cb Issue #3246168 by Wim Leers, bnjmnm, yash.rode, lauriii: Images are not linkable through UI; already linked images are unlinked (data loss!)
* b9c6084974ed14a075e7cdc9c597eac00ca60b72 Issue #3247711 by lauriii, bnjmnm, Wim Leers: Simplify and accelerate builds: update our use of the CKEditor 5 DLL manifest
* 7f5bc51e9bdad2ec89d5099934a687fa07aae723 Issue #3246955 by lauriii: Harden drupal-media by namespacing model attributes
* f6be9296f365fe1e177fb7c5c3387dc3cbecde48 Issue #3246521 by Wim Leers, yash.rode, effulgentsia, lauriii: Make plugin.manager.ckeditor4to5upgrade.plugin a private service
* 7c8c0002cf01779957f7efbc45131ea927225280 Issue #3246647 by bnjmnm, lauriii: Filter settings are not removed when a filter is disabled
wim leers’s picture

StatusFileSize
new193.11 KB

After hours of prep work to make sure the core patch is green on the first attempt I of course forget the interdiff 😅

wim leers’s picture

StatusFileSize
new93.51 KB
new2.82 MB

Since #71, #3246524: Make more (all?) classes @internal and #3246280: Defense in depth: add anti-CSRF token to this module's routes have landed.

#3246169: Embedded media are not linkable through UI; already linked embedded media are unlinked (data loss!) is 95% ready, will be finished tomorrow.

Built using #3227826-65: Preparation for moving CKEditor 5 to core using commit 3ca84023f364eb773b723fa075f9be30f79e837f against d63941bc1af2e1a31debad1f202e46351eaa149d in 9.3.x. Upstream commit history since the previous build:

* 3ca84023f364eb773b723fa075f9be30f79e837f Issue #3245400 by yash.rode, Wim Leers, lauriii, effulgentsia: Add an @throws PHPDoc everywhere exceptions are thrown
* d623f091e664119f1db53303d07d78c9584b424c Issue #3246280 by Wim Leers, effulgentsia, yash.rode, lauriii: Defense in depth: add anti-CSRF token to this module's routes
* cbbae5df2f044a7303d784552f17eb3b32f0677c Issue #3246524 by Wim Leers, lauriii, effulgentsia, tim.plunkett: Make more (all?) classes @internal
effulgentsia’s picture

I did the (backend) framework manager review on this. The critical issues that I filed are fixed and in #73, so removing the "needs framework manager review" tag. I filed some normal priority issues that haven't yet been fixed, but I'm fine with them happening post beta.

I did not review the frontend code, but this issue still has the "needs frontend framework manager review" tag for that.

lauriii’s picture

I've updated the roadmap with issues I've discovered while reviewing the code. I have to acknowledge that I'm not fully impartial to review this since I've done a lot of work on the JavaScript aspects of the module. That said, I still feel comfortable removing the tag given that all of the work has been peer reviewed, the frontend APIs provided by the module are very minimal (almost all of the frontend code is marked as internal), and there will be still some time for additional reviews until the module is marked as stable.

These issues should be addressed before the module is ready to be marked as beta:

  1. It seems like #20 moved the CKEditor plugins to core/assets/vendor directory which I don't necessarily agree with. Image and media plugins are heavily coupled with the modules, and cannot be outside of that context. For consistency, I think the other plugins should be there too.
  2. The CKEditor license should point to a specific version, not the master branch
  3. @ckeditor/ckeditor5-dev-utils is listed twice in the package.json
  4. We need to do dependency evaluation for jsdom library which was added in #71
wim leers’s picture

StatusFileSize
new79.17 KB
new2.85 MB

#3246169: Embedded media are not linkable through UI; already linked embedded media are unlinked (data loss!) landed this morning.

#75.2 and .3 are already fixed. I'll need help to address #75.1 — but I 100% agree with that!

Built using #3227826-67: Preparation for moving CKEditor 5 to core using commit 7e3cf3bacce08f39c3c69b1081cefc2a9a15cf8b against d63941bc1af2e1a31debad1f202e46351eaa149d in 9.3.x. Upstream commit history since the previous build:

* 7e3cf3bacce08f39c3c69b1081cefc2a9a15cf8b Make ckeditor 5 asset library license link point to the currently used tag.
* 28ffe11a66060e54e1f44e4ba78677c9cae3238d Issue #3248443 by lauriii: Mark drupalMedia utils as internal
* c4b6d451672d7fde5b95698b0701409cfa237745 Issue #3243867 by Wim Leers, effulgentsia, lauriii: ckeditor5_module_implements_alter() looks like it has incorrect logic
* b3bca6c17de8c15205f7fb312da0afa13667c4c4 Issue #3246169 by Wim Leers, bnjmnm, lauriii: Embedded media are not linkable through UI; already linked embedded media are unlinked (data loss!)
wim leers’s picture

StatusFileSize
new487 bytes
new2.85 MB

Built using #3227826-67: Preparation for moving CKEditor 5 to core using commit 48d0ae0dc22ff864e2c5b057d9be5646254460d0 against d63941bc1af2e1a31debad1f202e46351eaa149d in 9.3.x. Upstream commit history since the previous build:

* 48d0ae0dc22ff864e2c5b057d9be5646254460d0 cspell:ignore downcasted

I once more really wish core/scripts/dev/code-commit-check.sh were available for contrib projects 🥲No idea why our monkeypatched variant of it did not catch this 🤷‍♂️

effulgentsia’s picture

Multiple committers have already commented on this issue, most recently #74 and #75, so removing the "needs committer feedback" tag.

wim leers’s picture

Green! Now just to address #75.1 (requires new patch) and .4 (requires addition to issue summary).

FYI: a few hours before #75, I updated #3238333 thoroughly for everything that happened in the past ~40 days, see #3238333-7: Roadmap to CKEditor 5 stable in Drupal 9. @lauriii as part of #75 added all additional issues he identified as FEFM: #3238333-8: Roadmap to CKEditor 5 stable in Drupal 9.

tim.plunkett’s picture

Status: Needs review » Reviewed & tested by the community

#3248522: Move custom CKE5 plugins outside of core/assets/vendor is one issue that should ideally land first, but I do not think it blocks commit.

After discussion with the team and my own review of the module, I am marking this RTBC.
Thanks to everyone who worked on this!

bnjmnm’s picture

Issue summary: View changes

Added jsdom dependency evaluation to issue summary

lauriii credited nod_.

lauriii credited rkoller.

lauriii’s picture

Crediting folks who have contributed to the development of the patch.

wim leers’s picture

StatusFileSize
new229.65 KB
new2.85 MB

And now #3248522: Move custom CKE5 plugins outside of core/assets/vendor is done! 🥳

Built using #3227826-73: Preparation for moving CKEditor 5 to core using commit fbacec8247208f39472d3d8544c540676404dfe5 against bd80b71a6f0539a792b1f925b59d607564706fd1 in 9.3.x. Upstream commit history since the previous build:

* fbacec8247208f39472d3d8544c540676404dfe5 Revert part of #3248522: the changes in `css` that converted double quotes to single quotes.
* b2dfb1c35102cddebee8c6415d71d453474c2ac3 cspell: fix typo
* b3050c8cd622cc6775db68c46d9810a9660bd56d Issue #3248522 by lauriii, Wim Leers, bnjmnm: Move custom CKE5 plugins outside of core/assets/vendor
* 8466bb067212e3374cad037224c51df5baeef4cf Issue #3248662 by Wim Leers, lauriii: Move drupalHtmlEngine from ckeditor5.internal
* 2bb9e33411221c239d0c621d08199c2c1e063e70 Issue #3248615 by Wim Leers, lauriii: Remove dependency on zrpnr/ckeditor5-drupal-layercake

P.S.: we promise the interdiff is only scary because we moved things around 😇

lauriii’s picture

StatusFileSize
new2.86 MB
new1.22 KB

This should fix the commit-code-check.sh 😇

bnjmnm’s picture

StatusFileSize
new2.85 MB
new1.71 KB

This fixes the Nightwatch failure that appeared in the post credits stinger.

tim.plunkett’s picture

Great, thanks! As I mentioned when I RTBC'd, that was important to land but not a commit blocker. But happy to have ironed out all the resulting changes now rather than later.

Consider this re-RTBC'd

catch’s picture

Discussed this quickly with @xjm since it's still tagged for release manager review. I haven't managed to do a full code review here, although I'm confident that plenty of other people have.

I think there were two remaining concerns (now that a lot of (all known?) data loss issues are fixed):

1. Docs for contributed modules porting - this is somewhat blocked on upstream, so we should move it to a stable blocker instead of a beta blocker (it's also mostly going to live on Drupal.org, so not directly part of this patch anyway).

2. Some kind of plan for dealing with third party production js dependencies (updates, reviewing updates etc.), but that's also not blocking and not specifically a ckeditor issues (although it makes it more pressing).

Overall I think it's much more important to have this in core in 9.3.x so that it gets run through its paces earlier than later.

effulgentsia’s picture

This is failing some pre-commit checks. I'll come back to it later today to see if it's just on my machine or if it's a real issue with the patch.

larowlan’s picture

Issue tags: +Needs change record

Can we get a change record for this amazing piece of work? Thanks

The pre-commit checks passed for me, FWIW

larowlan’s picture

  • effulgentsia committed 35972c9 on 9.4.x
    Issue #3231364 by Wim Leers, lauriii, bnjmnm, webchick, xjm, tim....

  • effulgentsia committed cfb5106 on 9.3.x
    Issue #3231364 by Wim Leers, lauriii, bnjmnm, webchick, xjm, tim....
effulgentsia’s picture

Title: Add CKEditor 5 module to Drupal core » [Needs change record] Add CKEditor 5 module to Drupal core
Status: Reviewed & tested by the community » Needs work

Phenomenal work on this, everyone! Pushed to 9.4.x and cherry picked to 9.3.x.

Needs work for the change record, but I didn't want that holding up getting this into the beta.

larowlan’s picture

Status: Needs work » Fixed
Issue tags: -Needs change record
gábor hojtsy’s picture

Title: [Needs change record] Add CKEditor 5 module to Drupal core » Add CKEditor 5 module to Drupal core
wim leers’s picture

@lauriii just published a change record (basically matching the https://www.drupal.org/project/ckeditor5 project page, which was indeed written as a change record for an experimental module): https://www.drupal.org/node/3249061.

We will expand that change record with guidance on how to port modules providing CKEditor 4 plugins (most can be found at https://www.drupal.org/project/ckeditor/ecosystem and https://www.drupal.org/node/2735151).
That is impossible to provide right now because:

  • CKEditor 4 has a centralized place for plugins: https://ckeditor.com/cke4/addons/plugins/all — much like d.o for Drupal modules
  • No such place exists for CKEditor 5. They're generally just somewhere on npm.
  • Most importantly: there are no official docs, no official recommendations on how to find 1:1 ports or equivalents or recommended successors in CKEditor 5 for CKEditor 4 plugins. The CKEditor team is working on this upstream. 👍
wim leers’s picture

Can we get a ckeditor5.module component in the Drupal core project, so we can move over all open issues from https://www.drupal.org/project/issues/ckeditor5?categories=All into it? 🙏😊

(Or would we prefer to move 100% of issues over? 🤔 I do not have a strong opinion. I think it's probably best to move only over the remaining open ones; the rest predate the commit history in Drupal core anyway.)

lauriii’s picture

Created the ckeditor5.module component 👍 I think we should move all issues from the issue queue to the core queue under the new component.

wim leers’s picture

Component: ckeditor.module » ckeditor5.module

… starting with this one then 😊

xjm’s picture

Component: ckeditor5.module » ckeditor.module
Status: Fixed » Reviewed & tested by the community
Issue tags: +Needs release manager review, +9.3.0 release notes
xjm’s picture

Component: ckeditor.module » ckeditor5.module
Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs release manager review

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

nod_’s picture

issue broke the yarn vendor-update command #3258371: fix yarn vendor-update command

rgpublic’s picture

I sincerely hope, "No Drupal dialogs in CKEditor anymore" doesn't mean support for it will be removed completely...? After all Drupal.ckeditor5.openDialog() in core/modules/ckeditor5/js/ckeditor5.js exists and for some use-cases it's in fact very nice to have this option still available. Not everything can be crammed into a tiny bubble and sometimes you need really need Drupal's backend features, form validation, form fields etc. I have nothing against the link feature in a bubble, though. Just wanted to argue for keeping the dialog feature alive.