Text Formats and Allowed HTML
Anchors are attributes on <a> elements, so they only survive a save if the
text format permits those attributes. This page explains what has to be allowed
and how the module interacts with core's HTML filtering.
The attributes involved
| Attribute | Purpose |
|---|---|
id |
The anchor itself. This is the jump target. |
name |
Legacy form of the same thing, still read for backwards compatibility. |
Limit allowed HTML tags
When a format enables the Limit allowed HTML tags and correct faulty HTML filter, only the listed tags and attributes survive. The anchor plugin declares what it needs, and Drupal merges those into the allowed HTML when you save the format.
A format with the Anchor button typically ends up with something like:
<a href hreflang id name>
You normally do not edit this by hand. Two cases where you might:
- The format was configured before the Anchor button was added and the merge did not run, for example because the configuration was imported rather than saved through the form.
- The allowed HTML is managed in exported configuration and you want it explicit.
To check, edit the format and read the Allowed HTML tags field. If id is
absent from the <a> entry, anchors will be stripped on save.
The name attribute and the post update
Support for the legacy name attribute was added after some sites had already
been using the plugin. Those formats' allowed HTML predates it, so the module
ships a post update:
anchor_link_post_update_allow_anchor_name_attribute
It finds every text editor that has the anchor plugin enabled, and for each one
whose format uses filter_html, appends <a name> to the allowed HTML.
Run it as part of a normal update:
drush updatedb
The post update only touches formats that already have the plugin enabled. It does not enable anything, and it does not widen formats that never used anchors.
Configuration management note
Because the post update edits filter.format.* configuration, running it
changes active configuration. On a site that manages configuration in code, run
drush updatedb and then export:
drush updatedb -y
drush config:export
Otherwise the next config:import reverts the change and anchors start being
stripped again.
General HTML Support
Drupal core's Arbitrary HTML support plugin (General HTML Support in
CKEditor terms) can also claim <a> attributes, which conflicts with the anchor
plugin.
The module resolves this by altering that plugin's definition to disallow it from handling the attributes the anchor plugin owns:
awith attributesidandname
This happens in hook_ckeditor5_plugin_info_alter(). The practical effect is
that a format with Full HTML style arbitrary HTML support and the Anchor
button both enabled behaves correctly, with the anchor plugin in charge of
anchors.
You do not need to configure this, but it is worth knowing if you are debugging attribute loss on a Full HTML format.
Editor class versus saved markup
The ck-anchor class is an editor concern. It marks anchors so CKEditor can
show the "INVISIBLE ANCHOR" flag and let authors select empty anchors.
It is not written to the saved content. If you see class="ck-anchor" in
your rendered HTML, the editor library is out of date. Update to
vardot/ckeditor5-anchor-drupal 2.0.5 or newer.
Troubleshooting
Anchors disappear on save.
id is not in the allowed HTML for <a>. Re-save the text format through the
form so the merge runs, or add it explicitly.
Anchors work on Full HTML but not on a restricted format. Same cause. Full HTML does not filter, so it hides the problem.
ck-anchor appears in rendered output.
Editor library too old. Check
libraries/ckeditor5-anchor-drupal/package.json for the installed version.
Legacy name anchors stopped working after an upgrade.
The post update has not run, or ran and was then reverted by a configuration
import. See the note above.