Skip to main content
drupalreleases
Release: Cms 2.2.3 — Update released for Drupal core (2.2.3)! Release: Easy Breadcrumb 2.0.11 — Minor update available for module easy_breadcrumb (2.0.11). Release: Bootstrap 8.x-3.42 — Minor update available for theme bootstrap (8.x-3.42). Release: Editoria11y Accessibility Checker 3.0.10 — Minor update available for module editoria11y (3.0.10). Release: Editoria11y Accessibility Checker 2.2.24 — Minor update available for module editoria11y (2.2.24). Release: Leaflet 10.4.13 — Minor update available for module leaflet (10.4.13). Release: Flag 5.1.1 — Minor update available for module flag (5.1.1). Release: MCP Sentinel 2.33.0 — Minor update available for module mcp_sentinel (2.33.0). Module Revived: Bootstrap 8.x-3.41 — Theme bootstrap updated after 6 months of inactivity (8.x-3.41). Security Coverage: Component Library — Module component_library now has official Drupal security advisory coverage.

CKEditor 5 Roundtrip

20 sites No security coverage
View on drupal.org

This module provides plugins to fix issues where CKEditor 5 incorrectly modifies or removes certain HTML elements when switching between editing modes or saving content. It preserves script tags, empty anchor targets, and legacy HTML elements, while also cleaning up unwanted attributes and classes that are added by CKEditor or Drupal core.

Fixes HTML content loss and mutation that occurs when editors toggle between Source and WYSIWYG mode in Drupal's CKEditor 5. CKEditor 5's General HTML Support (GHS) layer and its model normalisation rules silently discard or rewrite certain HTML elements on every toggle — or on every Save.

This module provides 11 independent, opt-in plugins. Each plugin is a documented workaround for a named, tracked defect in Drupal core or CKEditor 5 upstream. The relevant issue links are included so you can monitor upstream progress and retire a plugin when the fix lands in core.

Development of this module involved AI-assisted tooling. All code has been reviewed and tested by the maintainer.

Plugins

ScriptRoundtrip (ckeditor5_roundtrip_script)

Prevents <script> tags from being stripped after a Source → WYSIWYG toggle. Also prevents JS operators (<, >, &&) from being entity-encoded when the script body passes through the DOM parser.

Upstream: drupal.org #3570973, ckeditor5 #10891

⚠ Trusted editors / Full HTML formats only.

ScriptContainerRoundtrip (ckeditor5_roundtrip_script_container)

Preserves <div><script>…</script></div> ad-tag and tracking-pixel patterns. Without this plugin, ScriptRoundtrip consumes the inner <script> leaving the parent <div> childless; CKEditor's model post-fixers then discard the container along with all its data-*, id, and other attributes.

⚠ Trusted editors / Full HTML formats only.

AnchorRoundtrip (ckeditor5_roundtrip_anchor)

Prevents empty <a id="top"></a> and <a name="section"></a> anchor targets from disappearing on toggle. CKEditor's model cannot represent empty inline elements and silently discards them, breaking in-page links.

Upstream: drupal.org #3337298, ckeditor5 #9888

ListIdsRoundtrip (ckeditor5_roundtrip_listids)

Strips the data-list-item-id tracking attributes that CKEditor 5's DocumentList plugin injects onto every <li> before saving. These are editor internals not intended for storage.

Upstream: ckeditor5 #18407, ckeditor5 #19006

TableRoundtrip (ckeditor5_roundtrip_table)

Removes the class="table" Bootstrap class that Drupal core's PlainTableOutput injects on <table> elements. Sites not using Bootstrap receive unintended styling from this injected class.

Upstream: ckeditor5 #11379, #11394, #13164

TableRowspanRoundtrip (ckeditor5_roundtrip_table_rowspan)

Preserves rowspan and colspan attributes on <td>/<th> without requiring the Merge table cells toolbar button. Without this plugin, GHS has no allow-rule for these attributes when the merge UI is absent and silently strips them, collapsing multi-row and multi-column cells.

LegacyHtmlRoundtrip (ckeditor5_roundtrip_legacy)

Prevents <center> from gaining a spurious <p> wrapper on toggle, and preserves attributes on <font> elements. Both are HTML4 elements unknown to CKEditor 5 that are mutated or stripped without explicit registration.

Upstream: drupal.org #3268306, #3418322, ckeditor5 #16203

InlineStyleRoundtrip (ckeditor5_roundtrip_inline_style)

Prevents font-weight:bold and font-style:italic from being converted to <strong> and <em> respectively. CKEditor 5's Bold and Italic plugins consume these CSS properties at normal upcast priority and discard the original inline style declaration.

ListStyleRoundtrip (ckeditor5_roundtrip_liststyle)

Preserves CSS list-style-type on <ol>/<ul> elements instead of converting it to the HTML4 type attribute. Also prevents adjacent <ol> elements with distinct list styles from being merged into one by CKEditor's list normalisation pass.

StyleRoundtrip (ckeditor5_roundtrip_style)

Preserves block <style> elements at their original document position. GHS inserts <style> at model position 0 (the start of $root) rather than at its correct structural position during upcast — every toggle silently hoists the block to the top of the content.

AlignmentRoundtrip (ckeditor5_roundtrip_alignment)

Three fixes in one plugin:

  • CSS classes → inline style — Drupal's Alignment plugin emits class="text-align-center" by default. This plugin overrides the downcast to emit style="text-align:center" instead, so alignment works on themes that provide no class-based rules.
  • Restore align= on table cells — CKEditor's TableCellProperties plugin converts align="center" on <td>/<th> to style="text-align:center" with no corresponding downcast. This plugin post-processes getData() output to restore the attribute, preserving layout in email clients that honour align= but not style=.
  • Strip injected pixel dimensions — CKEditor's ImageSizeAttributes plugin reads naturalWidth/naturalHeight after each image loads and writes them as width/height HTML attributes. This plugin strips those attributes from images already sized via CSS, where the pixel attributes would override the CSS constraints.

Requirements

  • Drupal 10.3 or 11.x
  • Core modules: ckeditor5, filter
  • The Script and Script Container plugins require a text format without filter_html (Full HTML or equivalent) and should only be enabled for trusted editors.

Installation

composer require drupal/ckeditor5_roundtrip
drush en ckeditor5_roundtrip

Then enable individual plugins at Administration → Configuration → Content authoring → Text formats and editors → select a format → Configure → Available plugins.

Related issues

All upstream and Drupal core issues tracked by this module are linked in the README.

Depends on

Dependencies of the latest stable release

No dependencies recorded for this project.

Required by

Tracked projects that depend on this one

No tracked projects depend on this one yet.

Activity

Tracked releases
16
Tracked since
Aug 2026
Latest release
1 month ago
Releases (12 mo)
16 ▲ from 0
Maintenance
Active

Release Timeline

Releases

Version Type Core Release date
1.0.0-beta10 Pre-release 10–11 Sep 7, 2026
1.0.0-beta9 Pre-release 10–11 Sep 7, 2026
1.0.0-beta8 Pre-release 10–11 Sep 2, 2026
1.0.0-beta7 Pre-release 10–11 Sep 2, 2026
1.0.0-beta6 Pre-release 10–11 Aug 21, 2026
1.0.0-beta5 Pre-release 10–11 Aug 20, 2026
1.0.0-beta4 Pre-release 10–11 Aug 17, 2026
1.0.0-beta3 Pre-release 10–11 Aug 17, 2026
1.0.0-beta2 Pre-release 10–11 Aug 14, 2026
1.0.0-beta1 Pre-release 10–11 Aug 14, 2026
1.0.0-alpha6 Pre-release 10–11 Aug 14, 2026
1.0.0-alpha5 Pre-release 10–11 Aug 14, 2026
1.0.0-alpha4 Pre-release 10–11 Aug 14, 2026
1.0.0-alpha3 Pre-release 10–11 Aug 14, 2026
1.0.0-alpha2 Pre-release 10–11 Aug 13, 2026
1.0.0-alpha1 Pre-release 10–11 Aug 13, 2026