Problem/Motivation
CKEditor 5 currently supports inline <code>…< /code>
thanks to:
ckeditor5_code:
ckeditor5:
plugins: [basicStyles.Code]
drupal:
label: Code
library: core/ckeditor5.basic
admin_library: ckeditor5/admin.basic
toolbar_items:
code:
label: Code
elements:
- <code>
But we do not yet have support for code blocks: <pre><code>…< /code></pre>
. That's where https://ckeditor.com/docs/ckeditor5/latest/features/code-blocks.html comes in.
We did support this in CKEditor 4 too, thanks to the Format
dropdown:
The full list of tags supported by that:
<p>
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<pre>
All of those are already supported (thanks to ckeditor5_paragraph
and ckeditor5_heading
), with the exception of the last one: <pre>
.
For that, we need this additional plugin. Right now, you're forced to use "view source" to create such content, which is a regression compared to CKEditor 4.
Steps to reproduce
N/A
Proposed resolution
Add https://ckeditor.com/docs/ckeditor5/latest/features/code-blocks.html to provide an equivalent UX in CKEditor 5.
Remaining tasks
- Add package to
core/package.json
and build the JS. - Add definition to
core/modules/ckeditor5.ckeditor5.yml
. - Expand update path test coverage in
\Drupal\Tests\ckeditor5\Kernel\SmartDefaultSettingsTest
- Expand update path for
Format
button in\Drupal\ckeditor5\Plugin\CKEditor4To5Upgrade\Core::mapCKEditor4ToolbarButtonToCKEditor5ToolbarItem()
. Note that this is tricky becauseFormat
now needs to be mapped to multiple toolbar buttons if<pre>
is allowed in the text format. This is not yet supported byCKEditor4To5UpgradePluginInterface
and will likely require an API addition.
User interface changes
Better UX for
API changes
TBD
Data model changes
None.
Release notes snippet
TBD
Comment | File | Size | Author |
---|---|---|---|
#44 | 3263384-44-d93.patch | 48.25 KB | lauriii |
#37 | 3263384-37.patch | 50.59 KB | Wim Leers |
| |||
cke4-code-blocks.png | 57.88 KB | Wim Leers |
Issue fork drupal-3263384
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
Wim LeersIronically, the d.o code filter is brittle …
Comment #3
DamienMcKennaComment #4
nod_Comment #6
Wim Leers#3261600: Update to CKEditor5 v32.0.0 landed just now, we'll need to get this rebased I'm afraid 🤓
(Interesting BTW that you already had pinned this plugin to 32.0.0, and the rest was still on 31.1.0 — I think that would not always be possible.)
Comment #7
Wim Leers@nod_ discovered the current
\Drupal\ckeditor5\Plugin\CKEditor4To5UpgradePluginInterface
does not allow expressing this upgrade path yet!Opened #3268174: Bug in CKE 4 → 5 upgrade path "format" does not always map to "heading", it could map to "codeBlock" too, or both, or neither for that (working on it now), that is hard-blocking this.
Comment #8
nod_We should probably split the adding of 0lugin and the upgrade path?
Comment #9
Wim Leers#8++ — that would actually allow me to add the upgrade path in #3268174: Bug in CKE 4 → 5 upgrade path "format" does not always map to "heading", it could map to "codeBlock" too, or both, or neither too :)
Comment #10
Wim LeersTest failure analysis
The tests are only failing due to
expectations all over the place.
Solution: #3231328
#3231328: SmartDefaultSettings should select the CKE5 plugin that minimizes creation of HTML restriction supersets is related to that: it wants to make
SmartDefaultSettings
… well … smarter … about which CKEditor 5 toolbar item/plugin it selects to fulfill a certain markup need.Because, here's the thing:
code
toolbar item supports only<code>
codeBlock
toolbar item supports both<pre>
and<code>
basic_html
text format does not support<pre>
out of the box, so this really is literally another showcase for the exact problem that #3231328 is selecting!Trickier still
To make matters more complex: we actually don't want only the
codeBlock
toolbar item in there, we want both:<pre>
and<code>
are supported in the original text format, we want both<code>
and<pre>
<pre>
is allowed, we don't want either, not evencodeBlock
, which is specifically for the<pre><code>…< /code>< /pre>
structure, which obviously requires both tags to be allowed → this is something we currently cannot express@nod_ mentioned this in a meeting earlier today and I finally 100% get why he started talking about this! 🙈😅)
<code>
is allowed, we want onlycode
, notcodeBlock
(See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code.)
Conclusion
I'm not yet sure how the Trickier still section will play out in combination with #3231328: SmartDefaultSettings should select the CKE5 plugin that minimizes creation of HTML restriction supersets … so … postponing this on that issue and starting to work on that right now to hopefully unblock this ASAP.
Comment #11
Wim Leers#3231328: SmartDefaultSettings should select the CKE5 plugin that minimizes creation of HTML restriction supersets is not 100% ready yet, but it is ~80%. It's ready for review.
Note: this issue should add test coverage for the
section, specifically the and scenarios (the scenario is already covered), by adding something toSmartDefaultSettingsTest
like$basic_html_format_with_alignable_p
and adding a new test case to its::provider()
Comment #12
Wim LeersUpdate: #3231328: SmartDefaultSettings should select the CKE5 plugin that minimizes creation of HTML restriction supersets is now fully ready for review :)
Comment #13
nod_Was doing a bit of research, the strict equivalent of the codeBlock plugin is the codeSnippet plugin in CKE4 provided by https://ckeditor.com/docs/ckeditor4/latest/features/codesnippet.html on the CKEditor side and https://www.drupal.org/project/codesnippet on our side. That plugin follows the same html structure as the codeBlock plugin:
<pre><code class="language-*">
There are no equivalent to "just"
<pre>
, which makes me think we would leave the implementation of the codeBlock plugin to contrib and add a simple<pre>
button? that would sidestep the complexity on the upgrade path while allowing contrib to provide one in the codesnippet plugin.Comment #14
nod_I would say this one as won't fix and do #3269059: [PP-1] Add a <pre> button to CKEditor 5 for the upgrade path from CKEditor 4 format dropdown instead?
For blockers, this one is still necessary #3268174: Bug in CKE 4 → 5 upgrade path "format" does not always map to "heading", it could map to "codeBlock" too, or both, or neither but that one #3231328: SmartDefaultSettings should select the CKE5 plugin that minimizes creation of HTML restriction supersets not anymore.
Comment #15
nod_Verified that using this MR with the codeblock plugin on content that only have a
<pre>
tag without the corresponding<code>
tag result in the<pre>
tag being stripped => data loss.Comment #16
Wim LeersThat's invalid HTML for blocks of code, see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code#notes.
😬
Tricky!
I do believe that the UX of the
CodeBlock
plugin covers the 99% use case. But of course we should not have any data loss problem.What if we have a creative combo? What if we ensure that the
ckeditor5_codeBlock
plugin you're adding here also loads thehtmlSupport.GeneralHtmlSupport
plugin and has this configuration:… then it'd ensure
<pre>
is retained always (just like itsdrupal.elements
metadata claims), it just won't be editable using theCodeBlock
UX out of the box. That way we avoid adding a weird<pre>
button with an inferior UX? (Not 100% sure about that, because of #3269059-4: [PP-1] Add a <pre> button to CKEditor 5 for the upgrade path from CKEditor 4 format dropdown).Comment #17
nod_Can we add this while a plugin supports the pre element? I would expect to run into the
The following tag(s) are already supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: Code Block (<pre>).
error.Comment #18
Wim Leers#17: That validation error happens when the user configures a particular tag to be allowed.
What I'm suggesting is something like this patch, which means that it's just the existing
ckeditor5_codeBlock
plugin that does this, simply to ensure that all forms of<pre>
are possible.We used to do that for a whole bunch of tags! See https://git.drupalcode.org/project/ckeditor5/-/commit/9b1a917c502ef5bc5b..., https://git.drupalcode.org/project/ckeditor5/-/commit/393386bd2413424912..., etc.
Comment #19
lauriii#16 That totally should work from data retention perspective. I first had some reservations on how the editing experience would be, and whether the element could be converted to other elements.
It seems like when the CodeBlock plugin is enabled, editing
<pre>
elements work pretty nicely! Conversion to other elements also works, including the markup expected by code block plugin. I think the proposed solution is really smart. 🤓 1) It's easy for us to implement. 2) It allows retaining existing data. 3) There's a way to convert away from the old syntax.Comment #20
nod_cross posted :p I confirmed it works too.
updated the MR
Comment #21
nod_It won't be possible to create only a
<pre>
element without source editing though, there could be valid cases for not wanting a wrapping<code>
tag. Not sure what to do with that.Comment #22
lauriii#21: Maybe that's something we could ask from the CKEditor 5 folks since that change isn't specific to us. Maybe if other CKEditor 5 users haven't needed that feature, the same could apply to Drupal. If there's demand for that, it's probably something that would be added upstream.
Comment #23
nod_That's fair enough. We should ping the folks of the code snippet module they might be able to help, or at least review and make sure we don't conflict with them
Comment #24
Wim Leers+1 — I think not being able to create
<pre>
without source editing seems fine to me. The<code>
-less<pre>
use case is a minority. Even more so because and\Drupal\filter\Plugin\Filter\FilterHtml
both have<code>
enabled by default!Comment #25
Wim LeersThe MR looks great to me — it will pass as soon as those two blockers land.
Marking this as explicitly blocked because there's no other work to be done here for now. 👍
Comment #26
nod_Added an issue in the codesnippet module to make sure they're aware of the work here.
Comment #27
nod_Comment #28
nod_Comment #29
Wim LeersYou beat me to it :D
Comment #30
nod_So with #3231328: SmartDefaultSettings should select the CKE5 plugin that minimizes creation of HTML restriction supersets looking good, there is a potential minor issue.
When we have a CKE4 toolbar with the Format and code button with html restrictions looking like this:
<h2><code><pre>
, if I add the codeBlock to the return ofmapCKEditor4ToolbarButtonToCKEditor5ToolbarItem
to handle the<pre>
tag, the<code>
tag will automatically be handled, so the code button will not be added to the toolbar. If I don't return codeBlock from themapCKEditor4ToolbarButtonToCKEditor5ToolbarItem
method,<code><pre>
, will be left to be supported, so code plugin will be used to handle code (thanks to the actually smart algo), and codeBlock will be picked up to handle<pre>
. It's just that the position of the codeblock plugin will be at the end of the toolbar instead of next to the heading button. Which is good enough for me at least.Comment #31
Wim LeersArgh! Interesting problem 😅 That is once again where your remark from #10's , point 2 comes in …
I think I agree with your conclusion — which fortunately means this won't be blocked after all. 👍🤞
Comment #32
lauriii#3231328: SmartDefaultSettings should select the CKE5 plugin that minimizes creation of HTML restriction supersets has been committed! 🎉
Comment #33
nod_Comment #34
Wim LeersManually tested both the plugin and the upgrade path. Works perfectly! 🤩🚀
Comment #35
lauriiiPosted feedback on the MR
Comment #36
Wim Leers@nod_ is out, so I'll address the feedback.
Comment #37
Wim LeersI made one trivial change, plus some comment changes. So I can definitely still RTBC.
Also uploading as a patch to test against
10.0.x
and9.4.x
. Cannot yet be cherry-picked to9.3.x
because it is still on version 32 of CKEditor 5. That's waiting for #3269651: Update Drupal 9.3.x to CKEditor 5 v34.0.0 along with other un-backported issues.Comment #40
lauriiiCommitted 6b2eabf and pushed to 10.0.x. Also cherry-picked to 9.4.x. Thanks!
Leaving open for 9.3.x.
Comment #41
lauriiiCommented on #3269651: Update Drupal 9.3.x to CKEditor 5 v34.0.0 along with other un-backported issues that we should consider backporting this when that issue lands.
Comment #42
xjmPostponing for backport after the v33 and v34 update.
Comment #43
lauriii#3274767: Update to CKEditor 5 v34.0.0 has been committed.
Comment #44
lauriiiComment #45
lauriiiAnother straight forward reroll on 9.3.x. Moving to RTBC since tests are passing 😇
Comment #47
bnjmnmAgreed this is a straightforward backport. Committed to 9.3.x.