CKEditor 5 Roundtrip
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.
CKEditor 5 silently discards or rewrites certain HTML elements whenever
an editor toggles between Source and WYSIWYG mode — or on every Save. The
losses are invisible until content is inspected: <script>
tags vanish after the first toggle, in-page anchor targets disappear,
Bootstrap classes appear on tables that never had them, and
data-list-item-id attributes leak into the database on every
list edit.
These are not configuration mistakes. They are documented, tracked defects
in CKEditor 5's General HTML Support (GHS) layer and in Drupal core's
integration. CKEditor 5 Roundtrip provides a set of
independent, opt-in plugins that fix each issue at its root — with the
smallest possible footprint — while upstream fixes work their way through
the issue queues.
Every plugin is a targeted workaround for a named core or upstream issue.
Enable only what you need.
Provided plugins
-
Script tag roundtrip — Preserves
<script>
tags through source ↔ WYSIWYG toggle cycles. GHS registers
<script>as an inline element, which is schema-invalid
at document root; CKEditor's post-fixers hoist or discard it on alternate
toggles. This plugin registers a block schema element so scripts survive
every toggle and every Save. Only enable this plugin on text formats used by trusted editors (Full HTML or equivalent). Drupal's condition system cannot express 'only when filter_html is absent', so this is documented guidance rather than an enforced constraint.
Addresses: #3570973 -
Empty anchor roundtrip — Preserves empty
<a id="..."></a>and
<a name="..."></a>anchor targets. CKEditor
cannot represent empty inline elements in its model and discards them on
Source → WYSIWYG toggle, silently breaking in-page links.
Addresses: #3337298 -
List item ID cleanup — Strips
data-list-item-id
attributes injected by CKEditor 5's DocumentList plugin onto every
<li>element. These are internal tracking identifiers
that must not reach the database. CKEditor regenerates them automatically. -
Table class cleanup — Removes the Bootstrap
class="table"injected onto<table>
elements by Drupal core's PlainTableOutput plugin. Author-supplied
classes are left intact. -
Legacy HTML4 element support — Retains
<center>and<font>elements through
editing cycles. Without registration, CKEditor injects
<p>inside<center>and strips all
<font>attributes (color, size, face).
Addresses: #3268306
Requirements
- Drupal 10.3 or 11.x
- Core modules: ckeditor5, filter
Installation
composer require drupal/ckeditor5_roundtrip drush en ckeditor5_roundtrip
Each plugin appears independently in the text format editor UI under
Available plugins. No additional configuration is required.
Related projects
If you need additional CKEditor 5 authoring features (fonts,
templates, bookmarks, etc.) rather than round-trip fidelity fixes, see
CKEditor 5 Plugin Pack.
If you need empty linked anchor targets, see
Anchor Link — this
module handles the complementary case of anchor targets with no href.