Problem/Motivation
Drupal is a CMS. Content creation is its strength — or it should be, at least.
It took until Drupal 8 shipping with CKEditor 4 before content creation had good usability out of the box — you'd have had to install https://www.drupal.org/project/wysiwyg plus a lot of manual tweaking before your Drupal 7 site had a good authoring experience.
Drupal 8 and 9 shipped with CKEditor 4 enabled by default. Drupal 9.5 and 10.0 will ship with CKEditor 5 enabled by default. It improves on the authoring experience on many fronts.
One front remains though: even though content creation covers the "C" in CMS, the "M" in CMS is not quite covered yet: Drupal enables you to manage the content through Views, but it makes no effort at all to facilitate linking from one piece of content to another. Even though that's quite literally the essence of the world wide web: web pages (nodes) linked to other web pages (nodes), forming one enormous graph.
Fortunately, there is a Module For That too: https://www.drupal.org/project/linkit. It has matured for twelve years in contrib! 🤩
I think it's high time we bring the essential parts of Linkit into Drupal core: no configuration required (but possible! think: which entity types and bundles to provide suggestions for), just linking:
Proposed resolution
Add the essence of Linkit to Drupal core:
- while writing content in CKEditor 5, make it easy to link to other content — links and URL fields are completely different beasts because they have
- automatically suggest links based on the host entity type (when writing text on a Foo entity, find Foo entities), as well as entity types marked as common reference targets except User (unlikely to link to) and Media (which has its own optimized CKEditor 5 experience already), which means that by default Nodes and Terms will also be searched
- require the (newly added)
entity_links
filter to be enabled, which is conceptually exactly like\Drupal\editor\Plugin\Filter\EditorFileReference
(which handles HTML elements withdata-entity-type="file" data-entity-uuid="*" src
), but this will instead handle HTML elements withdata-entity-type="*" data-entity-uuid="*" href
) — this ensures links are always pointing to the latest URL alias 👍 - 🚀 improve the responsiveness of the autocomplete by applying the same private client-side caching optimization used by
\Drupal\ckeditor5\Controller\CKEditor5MediaController::mediaEntityMetadata()
and\Drupal\media\Controller\MediaFilterController::preview()
. - 🕵️ for every suggestion: automatically list the author if the entity type has one, automatically list the creation datetime if the entity has one, and list both if the entity type has both — this helps remove the need for some of the configuration surface area
🤔 What does https://www.drupal.org/project/linkit have that this merge request does not?
- ❌
"substitution" plugins:\Drupal\linkit\SubstitutionInterface
(introduced in #2786049: Make entity URL substitutions pluggable to support a wider variety of use cases. and the accompanyingdata-substitution
attribute — I don't think it's necessary in 99% of cases — if you need this advanced feature, just use contrib Linkit 🤓
✅ @Berdir and others made the case that we need functionality like this. Solution: introducelink_target
handlers for entity types. See #39 for details. CR: https://www.drupal.org/node/3350853. - ❌
"matcher" plugins:\Drupal\linkit\MatcherInterface
,\Drupal\linkit\ConfigurableMatcherInterface
, etc. — just using an entity query to match the entity label is sufficient for ~90% of cases — if you need this advanced feature, just use contrib Linkit 🤓
✅ @Berdir in #18 and #21 articulated why using entity queries is problematic, and why we should use Drupal core's existingEntityReferenceSelection
plugins instead! 👍 "linkit profiles" config entities:\Drupal\linkit\Entity\Profile
—to be able to choose exactly which entity types to match, use tokens to generate customized suggestion descriptions, et cetera. I believe point 5 above covers the 99% case — if you need this advanced feature, just use contrib Linkit 🤓
✅ ability to restrict which entity types and bundles suggestions should appear for was added, see #80
✅ ability to set priorities for which suggestions appear first was added, see #116
✅ ability to reuse configuration, by introducingEntityLinkSuggester
config entities, which makes it possible for a follow-up issue to add a similar experience to "link" fields- (optionally) setting the
title
attribute on links based on the linked entity's label — if you need this advanced feature, just use contrib Linkit 🤓 → furthermore, on this issue this was reported to be problematic for accessibility in #51, #55 and #56
🫣 Which contrib modules does this partially or completely replace?
(Usage stats on March 30, 2023.)
- https://www.drupal.org/project/linkit (~128,000)
- https://www.drupal.org/project/media_entity_download (~7,000)
- https://www.drupal.org/project/ckeditor_entity_link (~5,200)
- https://www.drupal.org/project/media_entity_file_redirect (~500)
- https://www.drupal.org/project/ckeditor_link (~37,200 — D7-only)
- https://www.drupal.org/project/ckeditor_link_file (~2,100 — D7-only)
- https://www.drupal.org/project/ckeditor_link_user (~200 — D7-only)
And if this functionality is adopted by a site, then arguably most of the functionality in the following modules becomes obsolete:
- https://www.drupal.org/project/pathologic (~46,500) — in combination with the pre-existing
editor_file_reference
filter in core - https://www.drupal.org/project/insert (~38,000) — in combination with the pre-existing
editor_file_reference
filter in core
🙏 I want to use this but I'm currently using Linkit, how do I switch?
Glad you asked!
https://www.drupal.org/project/linkit used the same data-entity-type
and data-entity-uuid
that \Drupal\editor\Plugin\Filter\EditorFileReference
introduced >8 years ago. It's specifically designed for portability. And it makes the transition from the contrib module to this core feature trivial:
- Disable the
linkit
filter - Enable the
entity_links
filter - Configure which suggestions you would like to appear:
That's it 😊
Remaining tasks
TBD
User interface changes
The CKEditor 5 linking experience becomes vastly better!
API changes
- Addition: new
entity_links
filter plugin - Addition: new
EntityLinkSuggester
config entity type - Addition: new
ckeditor5_link_entity_suggestions
CKEditor 5 plugin - Addition:
#type => radios
's#options
array no longer must be an array of strings, but an array of arrays is accepted too — this allows setting a#description
per radio button for example
Data model changes
None.
Release notes snippet
TBD