Problem/Motivation
It's high time we bring the essential parts of Linkit -- the ability to provide autocomplete suggestions for internal node entities -- into Drupal core. The initial implementation will not provide advanced configuration, but will be designed to be extensible so that future iterations can allow configuration for other entity type suggestions as well as link formatting.

Proposed resolution
Start with a simple approach of adding a new 'Entity links' filter that can be enabled to provide link suggestions and rewrite the links to point to the latest alias. By default, the allowed bundles will be hard coded, and there won't be a UI for configuring it, that will be done in a follow up.
Comprehensive acceptance criteria
When the "Entity links" text format filter is enabled on a text format using CKEditor5 and one or more node entities exist, the CKEditor5-enabled text format meets the following criteria:
- [ ] When the CKEditor link toolbar item is selected and text is typed in the "Link URL" field, nodes whose titles start with the same pattern are displayed, grouped by node bundle, showing the node title boldfaced on the first line and author and created date on the second line
- [ ] When an autocomplete suggestion is accepted by clicking on it, the internal node url populates the Link URL field
- [ ] When the "Insert" button is pressed, the CKEditor link interface collapses, showing a tooltip preview of the link, with the node title and node bundle.
- [ ] When that link in the tooltip preview is clicked, the referenced page opens in a new tab/window
- [ ] The link preview can be deselected by clicking anywhere else in the viewport
- [ ] When the link is subsequently clicked once, the tooltip preview is shown again
- [ ] When the node is saved, metadata is saved in the text format field consisting of URL-encoded data-entity-type (e.g., "node"), data-entity-uuid (e.g., "b2a7e77b-4e1a-4cb6-b9c4-adeab54babcc"), and data-entity-metadata (e.g., authoriing information and title)
- [ ] When the link is rendered, it displays a link to the referenced node
- [FAIL] If the referenced node has a URL alias, that alias is rendered
- [ ] Using the CKEditor link interface, after a link has been accepted from an autocomplete suggestion, a query parameter (e.g., ?drupal=good) or fragment (#section) can be manually appended to the Link URL value and, when saved, is retained when the link is rendered
- [ ] When the text format includes the Image upload toolbar item, an image can be inserted and, using its CKEditor5 balloon interface, can be hyperlinked using the same autocomplete interface. When rendered, the image is wrapped in a hyperlink to the referenced node
- [FAIL?] When the text format includes the Drupal Media Library toolbar item and the "Embed Media" text format filter is active, a media entity can be inserted and, using its CKEditor5 balloon interface, can be hyperlinked using the same autocomplete interface. When rendered, the image is wrapped in a hyperlink to the referenced node
- [ ] When two links exist in body text and one of the links is selected by clicking inside the link and then is updated to have a different URL, the target link is successfully updated and the other link is not affected; specifically, the updated link has the updated metadata and has not been split into multiple link elements.
- [ ] When two links exist in body text and one of the links is selected by highlighting the entire link, and then is updated to have a different URL, the target link is successfully updated and the other link is not affected; specifically, the updated link has the updated metadata and has not been split into multiple link elements.
- [ ] When two links exist in body text and one of the links is selected by clicking inside the link and then is updated to have a different "Displayed text", the target link is successfully updated and the other link is not affected; specifically, the updated link has the updated metadata and has not been split into multiple link elements.
- [ ] When two links exist in body text and one of the links is selected by highlighting the entire link, and then is updated to have a different "Displayed Text", the target link is successfully updated and the other link is not affected; specifically, the updated link has the updated metadata and has not been split into multiple link elements.
- [FAIL] When two separate lines of text exist the body text and one is selected by triple-clicking, the link interface can subsequently be used and a link inserted on the entire link (currently this is failing with console error Original error: TypeError: can't access property "attributes", s[a] is undefined)
- [ ] When this is used in conjunction with link decorators (test either with custom code per the link, or using a contrib module like Editor Advanced Link or CKEditor Link Styles), using the new autocomplete selector does not interfere with the addition of attributes/classes inserted into the link markup by those decorators
Based on @catch's suggestion in #184:
- Define this at the bundle level in hook_entity_bundle_info(), defaulting to off
- Set sensible defaults in core (i.e. on for all node bundles, off for media, comments and menu links)
- Sites can use hook_entity_bundle_info_alter() to customise it, and either core or a contrib module could do that via config with a UI later
Remaining tasks
Review
Create follow-ups
Commit
User interface changes
Users can search for items when creating links in CKEditor.
API changes
- Addition: new
entity_linksfilter plugin - Addition: new
ckeditor5_link_entity_suggestionsCKEditor 5 plugin
Data model changes
None.
Release notes snippet
TBD
| Comment | File | Size | Author |
|---|---|---|---|
| #306 | entity-links.gif | 1013.38 KB | pameeela |
| #285 | Recording 2025-10-22 at 09.56.25.gif | 278.33 KB | acbramley |
| #284 | Recording 2025-10-22 at 09.52.46.gif | 372.63 KB | acbramley |
| #282 | data-attributes.gif | 1.92 MB | mark_fullmer |
| #276 | drupal-linking-dupes.gif | 1.78 MB | mark_fullmer |
Issue fork drupal-3317769
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:
- drupal-3317769-11.x
changes, plain diff MR !10351
- 3317769-link-suggestions-minimum
changes, plain diff MR !9807
- 3317769-cke5-entity-link-suggestions-11.x
changes, plain diff MR !6277
- 3317769-cke5-entity-link-suggestions
changes, plain diff MR !2909
- 3317769-link-suggestions-minimum-2
changes, plain diff MR !10036
- 11.x
compare
- 3317769-fix-link-api-ckeditor45
compare
- drupal-3317769-11.x-1
changes, plain diff MR !10361
- drupal_3317769-drupal-3317769-11.x
compare
Comments
Comment #3
wim leersWhile this is not complete yet, it absolutely is reviewable already.
Note that I did not write the CKEditor 5 plugin — it's @lauriii, @bnjmnm and @nod_ who did that in #3232190: CKEditor 5 readiness.
Comment #4
wim leersI worked on getting https://www.drupal.org/project/linkit ready for Drupal 10 and CKEditor 5. So that was the perfect time to extract that work into a core patch 😊
Note that the many test failures are because the new CKE5 plugin is enabled automatically right now.
The commit I just pushed adds explicit test coverage for the functionality introduced here. Next up is addressing this
@todo:… that will make other tests pass again 👍
Comment #5
wim leersNext up: test coverage for
\Drupal\filter\Plugin\Filter\EntityLinks.Comment #6
longwaveHaven't reviewed or tested yet, but big +1 to Linkit in core.
Comment #12
wim leersCrediting the maintainers of https://www.drupal.org/project/linkit as well as the people mentioned in #3 😊
Comment #13
dieterholvoet commentedGreat idea! Ideally this wouldn't only exist in context of CKEditor, but also when using link fields. LinkIt has an open issue for this functionality, having used it in multiple projects I must say it's a big improvement: #2712951: Linkit for Link field.
Comment #14
wim leersImproved issue summary.
#13: @DieterHolvoet Ideally, yes! But I consider that out of scope for this issue.
Link (and URI) fields have a very different set of constraints: the configuration associated with them means that the autocomplete should take that into account — for example to determine which entity types should be searched. It also means that you probably want a formatter that is entity-aware to resolve to the most current entity URL alias at render time.
Furthermore, many (most?) link/URI fields really should be
entity_referencefields, because A) they come with autocompletes already, B) it captures the data model with more clarity.EDIT: hah — that's literally what
linkitmaintainer @anon wrote at #2712951-3: Linkit for Link field 6.5 years ago! And I see that the current patch there indeed has a custom formatter & widget.In other words: a very different beast, with relatively little code in common, and with lots of data modeling questions associated with it that make the case far less clear. The fact that Linkit has lived all these years without supporting that feature is further confirmation IMHO 😊
Comment #15
damienmckennaThe difficulty is serving multiple use cases with a single field - entity reference fields can only point to entities, they can't point to a remote URL or a local URL that is not part of the entity type the field was designed for.
You can use something like https://www.drupal.org/project/link_fix_absolute_urls to convert Link fields to internal paths if the hostname is recognized, which can help a little.
Comment #16
wim leers#15: sure. That's where https://www.drupal.org/project/dynamic_entity_reference comes in. But that's also out of scope here.
Let's please keep this focused and not solve all linking problems 🙏 Retitling to make the scope more explicit 🤓
Comment #17
wim leersExpanding the issue summary to cover A) what this doesn't do that the contrib module does do (i.e. why stay on the contrib module), B) upgrade path.
Comment #18
berdirWarning: I have a lot of thoughts on this. Like many others, we've used linkit for years extensively including the link field patch. I did not yet look at the patch, this is just feedback on the concept/idea. I generally like the idea of having this in core, but this is a complex case, there are many existing issues and use cases to consider.
* You mention that medias are already covered, but it's not quite so simple. A very common link use case is linking to documents to download, which is quite tricky. Linking that is exactly where the usefulness of substitution plugin comes in, because media entities should then link to the file. But then there are modules like http://drupal.org/project/media_entity_download which provide alternatives (our solution to the replace-file-results-in-broken-links problem). We even have a custom addition on top of that that allows to add a new media document through a link in a new tab and then that gets auto-selected. I don't know yet how to support that with the ckeditor5 integration, it's an important frequently used feature for us.
* there is a reason that drupal core has entity reference selection plugins, it is not enough to just do an entity query. to be fair, these plugins are older than entity queries, but there still edge cases to consider. published content for example, core does not properly implement entity access and exposing unpublished content to users who are not allowed to see it is a security issue. users have no entity label and weird logic around anonymous users, and so on. Instead of hardcoding the entity query, you must at least use those selection plugins.
* Plus, matchers aren't just about entities. there is for example an email matcher in linkit that ensures it's prefixed with mailto because editors don't know how to do that properly. maybe ckeditor5 has something for that built-in, I don't know? They often also don't know how to properly link to external content, that often results in broken links as well.
* I'm generally fine with core not having the same level of configuration as linkit module, but it is important that it is extensible IMHO and can be customized (As entity browser maintainer, I'm kinda frustrated about the media library and it's decision to to _not_ be extensible). For example, you claim that users are not often linked, but core has user profiles and on community sites and also blog/news sites where it absolutely can be a common use case to link to author profiles. If core thinks that's not useful as a default, fine, but it shouldn't require a contrib module to entirely replace what core does to change that.
* #2712951: Linkit for Link field is a complex topic. I fairly strongly disagree with many things you said in #14. First, linkit has been mostly unmaintained for many years, and anon later on agreed that this is useful and he is willing to commit it. The issue has 188 followers and 20 or so different people worked on it over the years. You will not find many contrib issues with the same level of interest and activity. Second, the core link widget has built in node autocomplete and reference support already, it's not like this is a crazy idea. And our URL API has built-in support to link to entities as well. That was a lot of hard work and we did it because we know that it's being used. You might only be thinking about configurable link fields here, but keep in mind that menu links are a regular link field and widget too. Mixing external links and content links and other things in menus is absolutely a common use case. Dynamic entity reference does not solve that use case. I do agree with you in one aspect. That it is indeed a rather different beast and as the ckeditor integration of this module gets integrated more tightly into ckeditor5, that will make it much harder to reuse it for link fields. But there are aspects of this that are generic and should not be limited to ckeditor5 module/integration. Specifically the logic and API, and then it could be separate client/js logic.
* Kind of a small thing, but what happens with longer titles, the window seems quite narrow? On sites with a lot of content, titles tend to be a lot longer and you need to see much more to differentiate them.
* The issue summary and title is a bit dramatic :) Yeah, we don't have good link functionality for ckeditor, but we have link and entity reference fields. It's one scenario of many.
See #2423093: Allow multiple target entity types in the 'entity_autocomplete' Form API element for example as an existing issue, and #2427803: [PP-1] Expose target type, selection handler and selection settings in LinkWidget. I know that it is tempting and easier to just create isolated things from scratch, but I think it's important to consider these other use cases. If we can reduce the linkit module to a backend/configuration/UI for this then it will be much easier to maintain in the future and I'd be willing to help as well.
Comment #19
acbramley commentedGreat to see this issue! I'd add my +1 in for including substitution plugins as well. It seems like a fairly straightforward system to implement that would make it far more extensible, as Berdir mentions for things like linking to media files, etc.
Comment #20
wim leersYAY, thank you @Berdir and @acbramley for the very thoughtful feedback! 😊🙏
#18:
It's not quite clear yet to me what you propose to use instead … is it "just" that you are saying this should not be using entity field queries directly, but
EntityReferenceSelectionplugins instead? I'm happy to refactor this MR to use that for sure! 😊(What I did was removing the
MatcherInterfaceabstraction layer in Linkit and just used the level below directly, because this configurability does not make sense in Drupal core.)I think that would address most of your concerns?
UserandMediacommon reference targets, that those would instead be ignored by default, but it'd be configurable in the CKEditor 5 plugin settings?core/drupal.autocomplete. The API (I think you mean the route/controller and which arguments it receives?) also necessarily needs to be different, since link fields can have their own configuration of which links are allowed (not to mention field access), but that is not the case in CKEditor 5 (which currently has zero config, but based on the above it probably soon will). So I think there's very little in common here, other than the entity field queries that are generated? What am I missing? 🙈Note: I'm happy to restrict the scope of this issue further to only linking to
Nodeentities. That alone is probably the 80% use case, and it avoids many of the problems here.#19: You say "media files", and that one I understand. But you say "etc." — can you provide other examples? 🙏
Comment #21
berdira little bit of feedback.
> is it "just" that you are saying this should not be using entity field queries directly, but EntityReferenceSelection plugins instead? I'm happy to refactor this MR to use that for sure! 😊
that's the main thing yeah, that we likely have to go through that to find matching entities. As for the security thing, it's complicated and has a very long history, but as of now, everyone querying and displaying nodes is responsible for respecting the status field themself as you don't rely on an active node grants system. That's one reason why there are fairly frequent information disclosure security issues in that space. There are also plenty of related limitations, like node/core entity having a view own unpublished permissions, so you need to mix it with a check on uid. See the special views filter that the default admin/content view has.
The sad truth is that "$query->accessCheck(TRUE);" does absolutely nothing with just core, only when you add contrib or custom modules using node grants or directly implementing those query alter hooks it starts to do anything at all.
> Am I right in concluding that the 99% use case for linking to media is for linking to downloadable media such as documents, archives, etc — not images/videos/embeds? The answer to that question could help inform a direction to tackle this too.
Yes, but that's where it gets complicated and why it's configurable in linkit. This depends on your media types, which are configuration, there isn't really a reliable way to automatically detect that. you could look for media types with a file field instead of image, but we have an svg media type with a file field for example. So not just entity types but also their bundles. And then you quickly approach the config UI that entity selection plugins offer. user does it on the roles for example, which for entity reference fields is a very common use case (e.g. only being able to reference user with the author role).
Comment #22
wim leersIt's clear that at minimum this needs to be refactored to use
EntityReferenceSelectionplugins instead of direct entity field queries.Will think about the media linking aspect too when I do work on that.
Note: I won't have time on this in the next few weeks.
Comment #23
emil stoianov commentedComment #24
wim leersTime to get this going again! I'm working on addressing @Berdir's superb feedback — stay tuned 😊
Comment #25
mark_fullmerVery small user-experience suggestion for the naming of the text format filter. Enabling this text format filter will be the trigger that enables the autocomplete within the Drupal core link plugin. The title "Entity Links" may not be intuitive to users here, and the current description text only explains the text filter part of the behavior (""Updates entity links with
data-entity-typeanddata-entity-type-uuidattributes to point to the latest entity URL aliases.").What about something like "Drupal Linking" for the title, and include "Adds autocomplete suggestions for Drupal entities into the link plugin" in the description?
Comment #26
johnpitcairn commentedAm I right in thinking this means sites will need two editor toolbar buttons for what practically all users consider a single purpose?
Comment #27
andrew.macpherson commentedCan I just check that you're considering one absolutely essential use case, please?
The media library contains documents as well as images. When we link to a media document container (whether in a field reference or in CKEditor), we need to have the path resolve to the file itself rather than the media entity. So that when we link to a PDF that's in the media library, for instance, the browser displays (or optionally downloads) that PDF.
Linking to the media container should be an option, though, because I imagine some people may have a need to let people see the container itself.
If made from CKEditor, that link must also be a normal inline element.
The second requirement, which follows naturally from the first, is that if we replace the file in the media container (with an updated version of the PDF, for instance), any existing links then resolve to that updated version.
I hope I explained that well enough because it really is an absolutely critical need!
Thanks, Andrew
Comment #28
wrd-oaitsd commentedTo expand on #27, the way we want our links to behave by default in the editor depends quite a bit on the media type we're linking to. For the most part, we link to the entity with PDFs, and display them in an embedded viewer using the PDF module and PDF.js library. For other document types (for which we use a different media type), we want the link to download the file. I imagine we'd want to be able to configure the default behavior for a link based on entity type and bundle of the target.
Comment #29
dalemoore commentedI would echo what the two above have said. If we can replicate what CKEditor Link and CKEditor Link File did in Drupal 7 in core, it would be freakin' amazing. Right now the CKEditor 5 dialog just presents a popup for the editor to enter a URL, but expecting them to go and hunt down a URL and paste it in there is expecting way too much. Additionally, if the title is updated or some other change is made to the alias, they'd have to go in and update it manually everywhere! A nightmare for sure. This is a great initiative to get Linkit functionality in core!
Comment #30
wim leersI said in #24 that I'd start working on this again. And I meant it. But then https://www.drupal.org/project/automatic_updates took my full attention 😅 — see https://wimleers.com/blog/high-concurrency-composer for a fun anecdote 🤓.
Tomorrow is entirely dedicated to this. If not tomorrow, expect progress early next week. Both test coverage and addressing the feedback posted so far.
#29: my neck hurts from nodding along so strongly 🤣
EDIT: I just noticed this has become the 138th most followed open Drupal core issue in the 5 months and 1 days that it has existed — with 86 followers 🤯 That is across all versions of Drupal core. The only other issue less than a year old ahead of it is #3313520: Single-directory components in core — which understandably scores higher 🤓.
Comment #31
wim leers@mark_fullmer has stepped up to maintain LinkIt in contrib until this issue lands. That's wonderful news! That's why #3232190: CKEditor 5 readiness actually shipped in https://www.drupal.org/project/linkit/releases/6.0.0-beta4, meaning sites using CKEditor 5 can finally use LinkIt since March 5! 🥳🚀
In his closing comment on that issue, he mentioned 2 major issues, which we should take into consideration here too:
linkfield type has landed since then: on March 10, that landed: #2712951-334: Linkit for Link field. With over 200 followers for that issue, we'll need to carefully consider how to bring that into core as well, which @Berdir has so articulately argued for :)Comment #32
wim leersToday, I got back into this MR and added test coverage for the filter → removing tag. I hardened & cleaned up LinkIt's filter test and in the process I discovered that:
Fileentities — because it did not yet support substitution plugins. I would still like to try to avoid adding new API surface, and instead rely on the existing general plugin API capabilities for overriding/extending this. So instead of adding substitution plugins, for now, I addedprotected static function getUrl(EntityInterface $entity): GeneratedUrl { … }which means customizing this is as easy as: subclass, override::getUrl(), then:I'm working on an analysis of the entire contrib ecosystem to check if this is viable or not! Before responding to this, please wait for that 🙏
The filter test coverage is now stronger for this core MR than it is in the contrib module! 😊
Next up:
@Substitutionplugins, to articulate either an alternative or indeed add@Substitutionplugins here tooComment #33
wim leershttps://github.com/ckeditor/ckeditor5/commit/c276c45a934e4ad7c2a8ccd0bd9... caused this JS error, and it's actually a performance improvement in CKEditor 5. After a long search, I found a minimal solution 👍
→ finished #32.1, onto the next item!
Comment #34
mark_fullmerThanks for the compatibility fix for the JS error, Wim! I'll follow suit in Linkit's implementation for the time being.
Comment #35
wim leers@mark_fullmer in #25: You're totally right that "Entity Links" is perhaps even more meaningless than "Linkit" — worse, it probably sounds scarier! 😳🙈 I don't quite like "Drupal linking" either, because we should not be using the word "Drupal" in any UI text except the most high-level ones. A Drupal site built for an end user will not (or rather should not 😅) mention "Drupal" at all! What about "Local content links" as the filter title and "Suggests local content when creating links" as the description?
@John Pitcairn in #26: fortunately you're wrong 😄 Single Link button, single UI, but whatever you type in the
<input type=text>will try to find autocompletion matches. For external URLs it will simply not find matches.@Andrew.Macpherson in #27, @wrd-oaitsd in #28 and @dalemoore in #29: Thanks for stating that explicitly! I did notice that the Linkit contrib module has an explicit
@Substitution=mediaplugin which does what you describe (its description:Direct URL to media file entity. I'm not sure you're all saying the same thing though 😅(#29 also explicitly mentioned 2 CKEditor linking modules, but not
ckeditor_entity_link, which also has special logic for multiple entity types, including ones not mentioned before such asMenuLinkContentandShortcut: https://git.drupalcode.org/project/ckeditor_entity_link/-/blob/8.x-1.3/s...)This does tie in closely to what @Berdir has raised in #18 about Linkit's
substitutionplugins and @acbramley confirmed in #19, even though none of you use that term.I've been doing a comprehensive analysis as promised in #32.
I've worked my through all that, and am still working on a comment that summarizes my analysis, but I do have a working solution that I believe to be better than Linkit's Substitution plugins. Looking forward to y'all reading my next comment, and especially @Berdir 😁🤞
Comment #36
jelle_s@Wim Leers in #35: I'm not sure "Local content links" makes sense for non-technical end users. To them "local" could just as well mean geographically. I do agree that it makes more sense than the previous suggestions, and that "Drupal" should be avoided in the UI. Maybe "Site content links"? Just spitballing.
Comment #37
lauriiiI'm wondering if just "Content links" would be clear enough? I don't know if site adds anything to the name. We will have to complement the name with a description either way.
Comment #38
mstrelan commentedHow about "internal links"?
Comment #39
wim leers🕵️ Analysis of Linkit's
substitutionplugins in contribMediaentities as what Linkit in contrib does today. That's obviously reasonable 👍 Pushed equivalent test coverage to ensure we match the behavior.. The subsequent commit added the missing logic.But that does not yet address @Berdir's and @acbramley's concerns!
substitutionplugin implementations in total:dam_asset: 526 sites using itlinkit_custom_link: 8 sites using itmedia_download_inline+media_download: 6480 sites using itstatic_asset_cache_buster: 0 sites using itmedia_file_redirect: a href="https://www.drupal.org/project/usage/media_entity_file_redirect">470 sites using itcanonical+file+media: built-in to LinkIt since version 5, so 88195 sites using itThat's only 7484 out of 88195 sites using Linkit, or less than 10%.
dam_assetuses a custom media source plugin (which is exactly why the Media system is designed this way), and the Media module cannot possibly know or anticipate every possible scenario ⇒ REQUIREMENT: we need to somehow enable each media source plugin to be able to generate these URLslinkit_custom_linkis similar tockeditor_entity_link's support forMenuLinkContent&Shortcutentities (see #35), and is simply an addition to LinkIt'scanonical(fallback for all entity types) +file(Fileentities) +media(Mediaentities) ⇒ REQUIREMENT: we need to somehow enable each entity type to be able to generate these URLsmedia_download+media_download_inline+media_entity_file_redirectoverride Linkit's default media linking behavior to provide stable URLs that themselves whose controller redirects to the current actual file ⇒ REQUIREMENT: we need to somehow enable contrib modules to override the URLs that are generated by default for a particular entitystatic_asset_cache_buster: decorates every existing substitution plugin and rewrites all local file URLs to contain a cache-busting querystring ⇒ same thing: contrib overridability (although in this case one could argue it should be implemented as afilterplugin that runs late)Collected requirements: we need optional logic to generate link targets for a linked entity of A) any entity type, B) for the media entity type: any media source plugin, C) it must be overridable.
🕵️ Analysis of CKEditor Linking modules in contrib
Node,TermandMenuLinkContent— it has 37,203 sites using it despite it not having D8/9/10 support!), https://www.drupal.org/project/ckeditor_link_file (Fileentities) and https://www.drupal.org/project/ckeditor_link_user (Userentities, which was also mentioned by @Berdir!).ckeditor_entity_linkfor Drupal 8 & 9 (with 5219 sites using it), which allows linking toMenuLinkContent,Shortcut,FileandMedia(supporting BOTHfileandoembed:videomedia sources!) using custom logic and to everything else falls back to the sane default of using the canonical URL.In essence, this module does more than most substitution plugins combined with just two dozen lines of code 👏
📝 Proposal
I wrote this in the original issue summary:
"substitution" plugins:(introduced in #2786049: Make entity URL substitutions pluggable to support a wider variety of use cases. and the accompanying\Drupal\linkit\SubstitutionInterface
data-substitutionattribute — I don't think it's necessary in 99% of cases — if you need this advanced feature, just use contrib Linkit 🤓I was wrong. There is a proven, justified need for something like this, otherwise too many entities are excluded from being linkable.
I just do not believe that Linkit's
substitutionplugin architecture is acceptable in Drupal core: a new plugin type that is maintained entirely separately from the owner of the domain knowledge: the entity type itself.That's why I propose instead:
link_targethandler that can be specified for anyEntityTypeplugin → this automatically means that it's overridable!link_targethandlers would have to implement\Drupal\Core\Entity\EntityLinkTargetInterfacewhich has a single method:getLinkTarget(EntityInterface $entity): GeneratedUrl.FileLinkTarget+MenuLinkTargetMenuLinkContent+Shortcut(both of which are essentially metadata containers for other (accessible) targets (\Drupal\menu_link_content\MenuLinkContentInterface::getUrlObject()+\Drupal\shortcut\Entity\Shortcut::getUrl()) → also ensures that this supports just as much as contrib modules do todayMediaentity type should let@MediaSource=fileand@MediaSource=oembedimplement the actual logic, with a fallback in case standalone media URLs are enabled🚀 Implementation of proposal
Initial change record created: https://www.drupal.org/node/3350853
😅 TBD:
<a download>I think that means the only thing I have not yet addressed is http://drupal.org/project/media_entity_download's support for triggering a download. That could be addressed in one of three ways:
downloadattribute (which was not sufficiently supported a few years ago but now enjoys >96% browser support) on<a>using CKEditor 5 itself — see https://ckeditor.com/docs/ckeditor5/latest/features/link.html#demo-2 for a nice demo of that. The problem: that'd expose a "Download" toggle for all links, not just Media links. But that is something we could definitely work on.<a href data-entity-type="media" data-entity-uuid>elements, loads the entity, checks its bundle and/or source and based on filter configuration adds thedownloadattribute to these links at render time — that'd definitely guarantee consistency, but perhaps that's not desired … in which case option 1 is betterMediaLinkTargetand override the generated links, with even the freedom to choose to reuse or not reuse the logic in the media source plugins→ finished #32.2 + #32.3 — next up: adopt entity reference selection plugins (#32.4)
@Berdir: Really curious about your thoughts! 😊 Marking for the
link_targethandler stuff.Comment #40
wim leers#36 + #37 + #38: Thanks for the input!
Good point regarding the ambiguous meaning of "local"! 😬 I have a similar concern about the "internal" in "Internal links": it could too easily be interpreted as links to internal paths, not to entities.
I like as the human-readable label (even though that appears to imply it works only for
Nodeentities since "Content" is the label for that entity type… 🙈), but then I thinkEntityLinkscontinues to make sense as the name in code?Comment #41
wim leersUpdating issue summary per #39.
Comment #42
tijsdeboeckFirst of all, thanks for all the hard work! Having this in core would be amazing!
I like "Content links" as it conveys the message. The term "Content" is broad enough here to contain more than just nodes from an average content admin viewpoint.
Comment #43
dalemoore commented#35: I wasn't aware of CKEditor Entity Link tbh, I used CKEditor Link + User + File in D7 and (sadly) most of our sites are still on D7. When we started working to convert stuff to D8+ it seemed like Linkit was the way forward due to the sheer numbers of users it has so I've been trying to use it. (I work at a university with a small Drupal dev team... well, actually, the dev team is, uh, me... everyone else works on non-Drupal 😅).
Re: whether we're all saying the same thing in #27-29, I think so. My use of CKEditor Link File is also due to its ability to choose which method you want to present the link, either as a link to the entity (/media/id), as a path to the file (sites/[site]/files/file.pdf), or as a forced download link. My main complaint with CKEditor Link File though was that it was an all-or-nothing setting, you could choose from three link methods: File, URL, or Download and that applied universally to all files linked in CKEditor. You couldn't configure it per-link. 😢 I think that is the feature that we in #27-29 are requesting, and this may be possible already in Linkit.
#39: I think adding an additional "Download" toggle similar to the "Open in new window" toggle in this screenshot might work, but as you mention it also allows for the download of non-Media things. Not sure if that could "automagically" appear if they select Media only and go away if not.
#40: I think "Content links" works IMO, I'm not sure of any term more generic than that other than "internal link." I could go either way with content links or internal links. Thinking like a content editor, I'd say either one works, I'd assume that "internal link" means any type of link on my site (whether it be a node, media, paragraph, etc.). CKEditor Link uses the term "internal path" and I've had no confusion from editors about what that is.
in the screenshot above, internal path: any link to a file, user, node within Drupal. URL: external links (with the option to choose http:// or https:// protocol from select dropdown, but if you manually type it in there it selects it for you)
Comment #44
dalemoore commentedErgh, linked to the wrong thing above and it won't let me upload the image by editing... adding here :D
Comment #45
mrshowerman#40: We've been using the terms "internal links" (that point to content from the site) and "external links" (that point elsewhere on the internet) for some time and it has been helping editors to understand the difference.
Comment #46
wim leersTurns out that switching to use Entity Reference Selection plugins was surprisingly simple! 🤩
Remaining things related to the conversion to Entity Reference Selection plugins:
class MediaWithLinkTargetSelection extends MediaSelection, to ensure that no link suggestions are made for Media entities that do not actually have a link. That is a working PoC, but I'd first like confirmation from an entity reference selection plugin expert such as @Berdir that this is direction he'd like to see this being taken, before spending a lot more time on a potential dead end.CKEditor5ImageController::upload()is already checking whether image uploads are enabled. By default, only common reference targets are allowed, but you can change this to whatever you want.Comment #47
smustgrave commentedTested this out on Drupal 10.1x
On Node B
I could search for content in the link.
The alias appeared correctly.
On Node A
Changed the alias.
On Node B
Alias is updated properly.
Looks good so far!
Comment #48
tedfordgif commentedThis is fantastic work.
Adding to #43, the ability to select within the link dialog which type of link you want (e.g. for a given media item, do you want to link to media detail page vs file download) could be done in a follow-up issue. However, it might make sense to have some architectural review now to make sure it is possible in the future. For most of my sites a single link type will suffice, but there are occasional sites with e.g. a public media asset catalog where it would be nice to have that flexibility.
Options include:
Comment #49
wim leers#48: see at the bottom of #39, which lists 3 proposals. Looking back at it, the 3rd proposal does not allow choosing one media entity to be downloaded and not another, so that leaves only 2 proposals. The first 2 proposals are really only dealing with the UI part, not the "how to generate the link" part.
Well, the second proposal does deal with that part, but shifts that responsibility to a separate filter plugin, which is not consistent. I like your "multiple handlers" choice best, which would change it from:
to
(The link templates on entity type definitions are not an option — if they were I'd have picked that! The problem is that those link templates correspond to routes and routes must have a pre-defined URL structure and must be generated using the router. That's not the case here: file URLs do not involve the router at all and are often rewritten to be served from a CDN.)
But honestly, the bigger challenge here is how to surface this in the UI. As @dalemoore said in #43 (thanks for the thoughtful write-up! 👏), he really wants the ability to choose per-link whether it should be a "download" link or not. The first proposal I made in #39 would make it choosable per link. But the second and third would not. And that'd be equivalent to what CKEditor Link did in Drupal 7, but in Drupal 8/9 you would've been able to choose it per file thanks to the
data-entity-substitutionattribute. So channeling my inner @Berdir: this should support it too.Thinking some more about how to make this UX possible… I'm currently thinking that for every suggestion, we also have a
isDownloadable: true|falsekey-value pair. If that'strue, we'd expose the "download" toggle that https://ckeditor.com/docs/ckeditor5/latest/features/link.html#demo-2 demonstrates. That'd mean we can't use CKEditor 5's built-in manual link decorators (at least probably not), but it should be theoretically possible. I'll see what I can cook up. 👨🏻🍳It feels like this is the last stumbling block? 🤓 I've noticed that literally nobody has mentioned the
titleattribute that Linkit generates… 😇 Seems like people really don't quite use that?Comment #50
lauriiiGreat job @Wim Leers! 👏
I really like how the
link_targetoption implements theSubstitutionplugins as part of the entity system. 👏 It solves the problem withFileandMediaelegantly. 🤩 I definitely didn't think ofMenuLinkContent+Shortcutbefore but it makes total sense that this could be used for those too. 🤯The only concern I have at this point is that let's make sure that we focus on articulating clearly the intended use cases in
\Drupal\Core\Entity\EntityLinkTargetInterfaceandlink_targetso that people understand how these are different compared tolinks. This quote here seems to do a pretty good job at explaining the differences conceptually.💯 I really like this proposal for allowing multiple keyed handlers for specific use cases like downloading a file.
+1 to this.
I'm wondering if there should be some site level control over this because I'd assume in most cases this would be fairly consistent for same type of data across the site. IMO this can be handled by a follow-up too, so long as we are on an architecture that provides enough flexibility for us to consider these different options in future.
Comment #51
wrd-oaitsd commentedOur accessibility people discourage the use of the title attribute, to encourage our content people to use descriptive link text rather than relying on the attribute. I'm not sure if this is a common reason, but that's why we don't use it on our government sites.
Comment #52
wim leers#51: ah, TIL! That's a strong reason not to do it in core then! 👍 Thanks!
The 3 commits I just pushed fix a regression I introduced while converting to entity reference selection plugins: it would fail to find the currently linked entity based on the
hrefattribute 😅Fixed now, and simultaneously made it set expectations better: rather than pretending to link to
/media/3/edit, which is blatantly wrong, I'm now generating an entity URI instead:entity:media/3. That's not familiar for the end user, but it's equally recognizable, it just doesn't set the wrong expectations. So it's IMHO a net improvement.In the future we could switch to the actual link target, but that's not without downsides either. Curious what y'all think.
Comment #53
wim leersSo, here's a PoC for the
<a download>UX dilemma I mentioned in #49. It's rough, but proves it can work! 🥳(The hardcoded part today: only allows
Fileentities andbundleMediaentities to be made downloadable — I'll need to add metadata to allow this to be set in a generic way. We have a plan for that already: the presence of alink_target.downloadhandler. Which will work for everything except for Media — but that's entirely solvable. And it relates to what I said in #46.1.)It does do all state handling correctly: shows the toggle when editing/creating a link to an entity that is downloadable, and retaining the current toggle state while changing the link to another entity that is also downloadable.
Here is a demo:
Looks pretty cool, no? 😁 (I neglected my actual responsibilities of today because I got excited about building this 🙈) Zero cognitive overhead when it doesn't make sense: the toggle is only presented when it is actually relevant. I think that addresses the concerns that @Berdir, @dalemoore and others have raised? To an implementation like this I am not opposed, precisely because we're not making the UX painfully complicated 100% of the time for the 1–10% that use this.
Next: implement the multiple
link_targethandlers and remove the hardcoded piece in the PR.Comment #54
dalemoore commented#53 looks amazing! You’re awesome Wim. That’s exactly what I was picturing it would work like in your demo. 😍
Re: the title attr, I don’t use it often either, but I have seen in the past it used by some sites to generate a clickable/hover styled tooltip for different things using JS. I don’t think I’d ever do that personally, but that’s one use case for it. Probably modern methods would use data-*. That may be something that should be handled with contrib like Editor Advanced Link (what I have enabled in a screenshot up above, I think…)
Comment #55
nick hope commentedRe #51/#52, I always thought that the title attribute is useful for accessibility, and "should" be used. But here's another claim that it isn't useful.
Some want to use title attributes for SEO purposes. They were always on the checklists for old-school SEO, although it's debatable whether search engines still give them any credit or not.
Personally speaking, I like them for the tooltips they generate, and they can be helpful for me as an editor to quickly know what my links are pointing at. I would very much like to be able to automatically use the name of the target entity as the anchor text for a link. I made a feature request for that on Linkit here.
Comment #56
dwwThe
titleattribute would be useful for accessibility, but there's a huge variation in what, if anything, various assistive tech (and regular browsers!) do with the attribute. So the end result is that developers thinking they put useful info into the title attribute to "help blind users" is actually making it less accessible since that info is only rarely announced as the developer imagined it would. 😅 Now, the clear consensus of accessibility folks is to not use thetitleattribute at all, and make the actual text of each link descriptive enough to make sense on its own.A related consideration is that many users with a screenreader (blind or otherwise) use a "tell me all the links on the page" style command (that nearly all assistive tech provides). This listing of links gets read "out of context", so each link has to be able to make sense on its own. These listings generally do not announce the
title(although it's inconsistent). But this browsing methodology is a big part of why we need to make sure the link text itself makes sense, and why having 100 "Read more" links on your page is a bad idea. That's where the whole<a href="#">Read more<span class="visually-hidden"> about The Name of That Thing</span></a>practice comes from, instead of trying to put "about The Name of That Thing" into thetitleattribute...Comment #57
larowlanLeft some comments, leaving at NR to ensure more eyes on this.
Comment #58
wim leers@larowlan's review (responded!) made me realize that I have
failed to credit @bnjmnm, @lauriii and @nod_ herewhew fortunately I did think of that back in #3 😮💨 — they did 99% of the JS work on getting the Linkit contrib module to support CKEditor 5 in #3232190: CKEditor 5 readiness. 🤩 I'm less well-versed in the CKEditor 5 JS APIs than they are, and less well-versed in JS in general. So I'm hoping that either one of them wants to do a round of clean-up on the JS in this MR 😅🤞 I'm certain they would do a far better job than me.I've also updated the issue summary with a list of contrib modules this functionality partially or completely replaces.
I will be out next week — it'd be great if others can push this forward and/or review this in the meantime 😄
Comment #60
mherchelJust pushed some code to add the

.ck-reset_all-excludedCSS class to the entity link container. This class prevents CK5's CSS reset from affecting the styles within the container. Here's what it looks like now (updating IS)Comment #61
mherchelI just want to say this is awesome and 100% should make it into core!
Suggestion: Finer grain control over entities that can be linked to
In most cases, I don't want my editorial team to be linking either to users, taxonomy terms, or custom entities. I would love the ability to restrict what can be linked to.
It would also be fantastic if we could limit by content type. Frequently there are "microcontent" content types that are solely used to be embedded in other nodes. Ideally these wouldn't be exposed for linking.

Suggestion: Preview link and title when selecting entity-linked content
When selecting linked text, Entity Link will give a popup that says
entity:node/9or something. This data doesn't tell the content editor anything useful. I'd love to have it show the same info that the dropdown menu shows (title, author, date, etc), and have it actually link to the content (open in a new window)Comment #62
drdam commentedJust a test-review of MR2909 with Drupal 10.1-dev : Just work as promise ! Thanks, I'll see how I can help
Comment #63
smustgrave commentedBelieve the 1 failure is legit.
Also this was tagged for additional tests which probably still need to happen (could be wrong)
Testing wise
It searches for content, media, and users. Wonder if could add a config to the editor to limit what can searched. What if an editor doesn't have permission to link to users?
This may be by design but noticed the filtering was case sensitive.
Scrolling was a nice touch.
Comment #64
geek-merlinAmazing progress!
As of the handler idea:
Great pattern (and it would be even greater if all handlers were services like group does it, but that's another ceterum-censeo ;-)!
I have one concern though:
- To generate nearly identical target links in different classes feels like an anti-pattern, and it fragments code.
- It does not scale to a dynamic set of targets (i don't have a good example in mind, CDN links in different world regions might be one, but i bet soon s.o. will come up with sth)
Maybe sth like this
Comment #66
chris matthews commentedJust found this issue and pardon the random comment but this might be the most exciting new feature in Drupal. Long Live Drupal. 🎉
Comment #67
chris matthews commentedFWIW, agree with #45
Comment #68
wim leersNow working on:
link_targetto avoid confusion withlinksper @lauriii's first response to a quote in #50Not yet working on as requested by @mherchel in #61, but we should totally do that too!
First pushing a rebase on top of latest
10.1.x(I'll rebase on11.xlater — this is hard-blocked on reviews anyway, so it's not urgent).Comment #69
wim leers#68.1–3 are implemented, CR updated 👍
link_targethandler work is done for now.Next up: filter settings as requested by @mherchel.
Comment #70
wim leersWill continue this tomorrow, but … meanwhile, what do you think about this proposed configuration UI, @mherchel? (And thoughts from anybody else are welcome too of course!)
Comment #71
pyrello commentedSeeing the configuration UI concept makes me wonder about whether this should be something that is configured outside of CKEditor. Link fields already provide suggestions but I don't think there is any ability to configure it. I'm just wondering if the settings should be the same for both. Actually wiring up the config to link fields is probably out of scope for this issue, but maybe we should set this up to be compatible with a future state like that.
Comment #72
mherchelIf I'm understanding correctly, I'd worry that it might be a pain to jump around to the various entity types to configure this if this were the case.
Anyway, from my point of view, the UI laid out in #70 is absolutely beautiful! I'd love to see an option to selectively enable specific node types, but I can see that UI being really confusing. I like the help text at the bottom that points to a URL where developers can see how to do this, and I expect that contrib will create a module that does this though a UI.
Big +💯 from me!
Comment #73
mherchelComment #74
chris matthews commentedI would also add media types, comment types, and block types. But, as @mherchel mentioned, not sure a UI for that would be possible.
Comment #75
chris matthews commentedIn the UI, I'm not sure the word 'entities' is necessary in 'Comment entities' and 'Media entities'. Could just be 'Comments' and 'Media'
Also, would it make sense to add 'Webforms' as an Entity Link Suggestion with logic to only include if the Webform module is installed?
Comment #76
e0ipsoWould a dialog be appropriate here? The checkbox label could have a Refine Configuration link that triggers the dialog.
Comment #77
solideogloria commentedI'm not sure. It probably depends on the Webform configuration. If you're using the Webform Node submodule, you'd probably want the nodes linked instead of the webforms. You'd also have to do access checking to figure out who has access to which webform.
Comment #78
solideogloria commentedIs there a hook or something so that a contrib module can add link suggestions?
If a hook is added, then Webform can add its own functionality.
Comment #79
pyrello commented@mherchel I wasn't thinking about a per-entity/bundle configuration form. Probably a basic version of what LinkIt provides where you can turn on/off entities to be shown as link suggestions. Whatever is selected would be used in providing suggestions for Link fields. The CKEditor config UI would just be to turn on the suggestions for CKEditor and it would inherit link suggestion settings.
LinkIt could still be used to provide more fine-grained control (e.g. having different profiles, more control over the output for each entity/bundle type).
Comment #80
wim leers@pyrello Link fields are a different beast altogether, see #16 :)
Yep, already taken care of: this uses
\Drupal\Core\Entity\EntityTypeInterface::getCollectionLabel()😊@mherchel is enthusiastic in #72 but would like to see per-node type configuration. @Chris Matthews echoes this and would like to also see it for other bundleable types. @e0ipso proposes a UI approach that could work but that would AFAICT be an entirely new UI concept in Drupal: I don't know of any form which essentially contains a subform that's not visible but only accessible via a modal dialog? Also, it'd imply that we'd need that modal dialog to alter form state of the actual form, to be able to collect that information, because the data entered in that dialog cannot be saved directly 🤔😅
So … for now going with
#type => fieldset+#states:Comment #81
ckrinaThis is really cool!
I think #80is the most usable solution to solve the problem at hand with the patterns we have nowadays in Drupal.
Comment #82
artusamakIt looks great but beware of #states, since it only hides / shows the subform fragment, you may end up with inconsistent form states values if no cleanup is managed afterward (maybe you already did, i didn't examine the MR).
Use case would be:
* Check an entity type
* Check several bundles
* Uncheck the entity type
* Submit the form
The bundle might end up selected since they are still checked in the final submitted form.
Please ignore this if it's irrelevant with what has already been implemented, i just wanted to wave a caution flag!
Comment #83
wim leersAnd now it's actually respecting that configuration 👍 Including for bundles! 🤩 I'm done here for now. There are still clear next things that should happen:
I'm hoping to find the time to tackle the test coverage part. But at the same time I want to make sure that this can actually land. I think we need a @Berdir review 🇨🇭🍫, since he's posted the most thorough, most critical review so far, in #18. I believe I've addressed all of his concerns. Perhaps with the exception of bringing this to link fields as well. With the shift towards A) entity reference selection plugins, B)
link_targetentity handlers to enable more complex use cases, C) configuration that is structured in a way that is not at all CKEditor-specific, I hope the current MR shows sufficiently clearly that we can bring the same UX to link fields. I'd rather not increase the scope to actually build this for link fields too, because this MR is already 2500 lines long! 😅@ckrina Thank you for confirming that this is the best possible approach for now! 🙏😊
@Artusamak I'm very much aware! 😊 Because I've decoupled the design of the form from the design of the configuration, this very problem was avoided. Most configuration forms are 1:1 representations of the underlying config, which indeed leads to the brittleness you're referring to. The configuration you see at the end of the GIF in #80 results in this configuration:
bundles: nullmeans no bundle restrictions (bundles: []is not allowed: either a non-empty array must be present ornull, to make it an explicit configuration choice. This happens to match exactly how thetarget_bundlesoption for entity reference selection plugins already works! 🥳)Comment #84
wim leersOne last thing: as part of tying the last pieces together for bundle restrictions, I realized there is another thing that probably should be configurable: the priority of the search results. Right now, link suggestions to the same entity type as the host entity type are listed first. But other than that, there's no control over the ordering.
But wouldn't it be better to be able to specify the priority of each as well? For example, content entities before tags before media. And articles before pages, document and remote media before images and videos.
We already have a UI pattern for this: a table with drag-and-drop handles. And … in searching for that, I happened to find a UI that actually provides the nice modal dialog popover to select … bundles for an entity type (yes, literally the same use case!) in
\Drupal\content_moderation\Form\ContentModerationConfigureForm::buildConfigurationForm(), which you can see at/admin/config/workflow/workflows/manage/editorial.So …. yeah, I think I'm arguing I should scratch the UI I just finished 🤪😶🌫️ in favor of the table-style UI, with the same "Select" button to trigger a modal dialog, but with the drag-and-drop handles added to those rows. It'd be similar to the "list of entities with operations" pattern that we see everywhere (f.e.
/admin/config/content/formats), but with the addition of the drag-and-drop handles to the beginning of each table row. To be fair, the form state problems I mentioned in #80 would still need to be solved, so it's not trivial. (But at least the config validation means that no validation logic needs to change at all! 🤓)Thoughts?
Comment #85
wim leersComment #86
acbramley commented@Wim Leers you're a legend mate! Love the progress, it's looking great.
Comment #87
smustgrave commentedThis is amazing
Testing out on Umami install
Setup a Entity link settings for
Filter for Article content only
Creating a basic page
Adding a link
Search for a Recipe no results = Expected
Search for a Basic page, no results = Expected
Search for an Article, results = Expected
While updating text format I get this error, could be unrelated but wanted to note
Also even though I've only selected content I now see
Seems like these should be hidden.
Updated filter to include Basic page
Creating a basic page
Adding a link
Search for a Recipe no results = Expected
Search for a Basic page, results = Expected
Search for an Article, results = Expected
Updated filter to only include Media, images and NOT content
Creating a basic page
Adding a link
Search for a Recipe no results = Expected
Search for a Basic page, no results = Expected
Search for an Article, no results = Expected
Search for Image, results = Expected
Search for Documents, results = Expected
Minus the one error in bold functionally this appears to be working.
Also drupalci.yml needs to be reverted.
For the ticket are additional tests still needed or can the tag be removed?
Can the issue summary be updated for the TBD sections.
This is looking great @Wim Leers!! super excited to see this land.
Comment #88
mark_fullmerAdmirable work, Wim! More to come as a dig into the code, but here's some feedback from functional testing.
A. Confirmations from functional testing
1. Media URLs work as expected, dependent on whether "Standalone media URL" is enabled.
2. Anchor links and query parameters can be appended after autocomplete and are preserved.
3. Custom entity types are available in the configuration UI and as autocomplete suggestions.
B. Minor bugs
1. "Download link" toggle, if set to "on," retains the correct value in the source but reverts to "off" in the UI when link is editing via balloon.
2. "Download link" set to "on" populates download="true" in the link, which results in a filename of "true." The filename should be the original file entity.
3. After saving a link, clicking to edit the link presents a functional link without a preceding slash (e.g., "node/1"). Clicking on this will result in being taken to something like "example.com/node/3/node/1". This is *not* a *new* issue introduced in this MR, FYI, but I didn't see an existing issue in the queue. I'm even sure whether there *should* be a functional link in that context.
4. Entity metadata ("by admin on Friday, June 30") does not show on entity types other than nodes, files, and media.
C. Minor enhancements
1. Add the standard "autocomplete" icon to the link input.
2. Currently, unpublished entities are shown as autocomplete suggestions. I think showing them *is* a reasonable default, since content editors frequently stage interlinked content. However, it would be valuable to indicate the unpublished status as part of the metadata shown in the matching suggestions. (Content moderation states are another conversation.)
3. Suggested rewrite of "Entity Links" description text: "Provides autocomplete-style suggestions for entity links from a list of allowed entity types/bundles."
D. Architectural considerations
1. Berdir has advocated for a standalone configuration entity that stores the link behavior settings, external from the text format configuration settings, largely on the principle that the same configuration should be available to link fields. Another benefit of this architecture would be that sites could configure once and then reference it across multiple text formats. My hunch is that on most sites, most text formats would want the same link configuration, so it's valuable from a UX standpoint. (It would also leave open the possibility, down the road, of referencing the entity linking settings on link fields, rather than closing off that possibility). Is there a technical reason that having the configuration within the text format settings is preferable? (To be clear, I do *not* think that the scope of the MVP should include link fields.)
E. Responses to comment thread questions
1. I agree: priority would be good, and that the drag-and-drop table UI is the convention. I don't think this needs to be in the MVP, though.
2. I see potential disadvantages to showing the title. Many sites will have multiple entities with the same (or similar) titles. Seeing "United Kingdom" as the title and not knowing whether it's referring to a node or a taxonomy term, etc., would be problematic. Seeing /term/3 or /node/5 is at least unambiguous.
Comment #89
daddison commentedGreat work! I also test on a clean install of the umami profile.
Why are content blocks available as a linkable entity? Blocks do not have url paths.
When I link to a content block in the wysiwyg, the rendered output points to the admin configure form for the block. I think this behavior is of limited utility, and potentially confusing for many users.
I think content blocks should be removed from the available entity types that can be linked.
Comment #90
smustgrave commentedSee https://www.drupal.org/project/drupal/issues/3342998 which should make the blocks better.
Comment #91
wim leers@smustgrave in #87: Thanks for the detailed testing! Reproduced the PHP warning you got, fix pushed. More tests are still needed IMHO, so the tag is still relevant.
@mark_fullmer in #88: Thank you so much, especially for B!
<a download>is a boolean attribute. AFAICT https://ckeditor.com/docs/ckeditor5/latest/api/module_link_linkconfig-Li... and https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_view_downca... do not support these. So reached out to the CKEditor 5 team to get guidance 👍This is happening because the CKEditor 5 link plugin helpfully strips the protocol … which means it changes fromNope, this is actually caused byentity:media/1tomedia/1😬\Drupal\editor\EditorXssFilter\Standard::filterXss()! A simple addition tocore.serv ices.ymlfixes that. But that still leaves CKEditor 5 very much wanting to open that link as a relative link in a new tab 😅 We'll need to intercept that and point to the (current!) path alias. I've added preparational work to improve this, but I'd rather have a CKEditor 5 JS expert like @lauriii write this logic 😇\Drupal\ckeditor5\Controller\EntityLinkSuggestionsController::computeDescription()— it already does one of these 3 if possible:So … suggestions? 😊
\Drupal\node\Plugin\EntityReferenceSelection\NodeSelection::buildEntityQuery()'s logic? But you certainly describe a nice-to-have.config_dependenciesand optional overriding. Except that config dependencies can only declare a dependency on config entities, not simple config. So both the technical and UX parts of these would be entirely novel approaches AFAICT. (The only thing that comes kinda close is the "Inherit exposed filters", "Inherit pager" etc settings in Views I think, but Views has the concept of a "Main display" vs other displays, so it's inheritance within a single config entity. So still very different.) There are many things in Drupal core where ideally you'd specify some setting once and then re-use it everywhere. All throughout the Field UI and the Entity View/Form Display UIs one can find many examples of this. IMHO it's a problem independent of this one. I think the very example you give even indicates this already: → most of those text formats will have similar or identical settings for most filters, typically with different "levels" of allowed HTML tags. The exact same kind of "inheritance" would be helpful there. Unless somebody can think of a conceptually clear way to implement this, I think it'd be unfortunate to block the benefits this issue brings on fixing a problem that is pervasive throughout Drupal already.@daddison in #89: fixed! 😄
Comment #92
wim leersComment #93
smustgrave commentedCan confirm the issue I was seeing has been resolved and everything still functional.
Comment #94
berdirI'm not sure why D1 would require the ability to override the referenced "link configuration"? If you want something else, you'd create a different configuration entity then and select that.
Comment #95
mark_fullmerRegarding: B.1 ("Download link" toggle, if set to "on," retains the correct value in the source but reverts to "off" in the UI when link is editing via balloon), here's a demonstration of the problem as I'm encountering it (latest commit to Drupal 10.1.x, latest commit to this MR). Based on my experience, there are no 'special steps' involved here, so I'm not sure why it may not be reproducible by others.
1. Configure a text format to use the new "Entity link suggestions" text format filter, with "Allow the user to create download links" enabled.
2. Create a file entity.
3. In a CKEditor-based text field, click the "Link" icon and start typing something that will suggest the file entity. Accept the suggestion. The "Download link" toggle should be set to "on."
4. Save the page.
5. Return to the edit screen of with the CKEditor field.
6. Click the link.
7. Click the "pencil" icon to edit the link.
8. The "Download link" toggle is now set to "off."
Comment #96
mark_fullmerRegarding the most far-reaching point of still-debated architecture -- that of whether to have the link configuration be external from the CKEditor configuration setting -- Wim's points in D.1 of https://www.drupal.org/project/drupal/issues/3317769#comment-15135481 make sense to me now: there are many other things in core where it would be nice to have inheritable settings from an external config, but I accept that it is not a paradigm that works for core architecture. Put another way, it may be fine for a contrib module like Linkit to take that approach, but that doesn't mean the same architectural approach will follow core patterns.
So, for the record, I'm on-board with moving ahead with the current approach -- that of defining the config for the link settings within the CKEditor plugin config.
Comment #97
wim leers@Berdir in #94: I see, I had not understood your proposal that way! So you're proposing to introduce a wholly new configuration entity type that this CKEditor 5 plugin would depend on. That could work! In theory, at least.
In practice, I worry about:
Editorconfig entity 😬😬😬😬 See #2950795-29: CKEditor 5 plugin module dependency not added to text format configurationOf course, you can flip the UX argument around: some prefer disjointed-but-once-and-reusable, others prefer
I'm not opposed to it. But I personally don't believe it's the right trade-off. It reminds me of extreme database normalization. I think that which link suggestions (entity types + bundles) are desirable is highly contextual, and so will likely be subtly different per link field. For text formats/editors I agree there's likely less need for contextual variation (because the context is unknown!), but … repeating the same configuration for the few text formats/editors like you already have to doesn't seem like that big a deal?
IMHO it boils down to this: do we want to block this issue on a nicer admin UX ("configure once, reuse") before we can ship a better content creation UX (the demonstrated linking experience)?
@mark_fullmer in #96: thanks! (And will look into #95 in the near future!) What you write in #96 is rather different from what @Berdir writes in #94. I'm curious if you had written #96 after having read #94 (and hence disagree with @Berdir) or if you perhaps overlooked #94?
Everybody else: please chime in! 😊🙏 I want to make sure this addresses the needs of the majority!
Comment #98
pyrello commentedI'm not necessarily in favor of blocking this issue in favor of a nicer admin UX, but I do think there is something to the idea of moving in that direction eventually. My point earlier is that there is already link suggestions built into link fields in core. It seems like the user might expect, out-of-the-box, that link suggestions in CKEditor would work the same as the link suggestions in those links. It might be surprising to discover that you had no control over link field suggestions and that the best you could do to make CKEditor link suggestions work similarly is to configure them as close as possible.
I think this is obviously a much bigger issue and probably out of scope for what is being done here.
Comment #99
smustgrave commentedSince it's been a few weeks seems the agreement is to least forward with this improvement. Should follow ups be opened for others?
@wim.leers are additional tests needed?
Comment #100
smustgrave commentedMoving to NW for the additional tests if needed.
As far as #97 I think even if it can be improved later, it would be good to get in and provide users with a much desired feature.
Comment #101
texas_tater@wim-leers, MASSIVE THANKS for all your time and energy in making this issue a priority. It’s been a long time coming! As stated eloquently in your issue description, this will go a long way to truly enhance the “M” in CMS.
As for #5 in Proposed Resolution, may I suggest a few adjustments based on many years as a site builder who trains many other site builders. In our enterprise/university setting, we often find that content editing is delegated, but site management is not. This is an effort to protect the site’s integrity, specifically the Information Architecture (IA). By limiting who can add/delete nodes but allowing the content editors to “fill in the blanks”, site managers are able to control the IA while delegating content maintenance. This delegation often reduces the usefulness of entity “author“ and “create datetime”, as they carry little meaning going forward.
With the expectation that we don’t want to overload the dropdown list with too much metadata, I suggest replacing the “who” of entity author with the “status” reflecting the Published/Unpublished state of the node, as mentioned in C2 by my colleague @mark_fullmer https://www.drupal.org/project/drupal/issues/3317769#comment-15132055
I’m hopeful this is possible/easier with the landing of https://www.drupal.org/project/drupal/issues/3073554!
With regards “when”, I believe the datetime stamp of the most recent Published/Unpublished status change would be most useful.
Lastly, if a “who” needs to be included, I suggest the last person to change the Published/Unpublished status (which I deduce would involve revisions info and may be too much for this effort).
Again, THANK YOU very much for spearheading this most important feature!
Comment #105
omkar.podey commentedNow we have a failing test so in
\Drupal\Tests\ckeditor5\Kernel\EntityLinkSuggestionTestwe want\Drupal\ckeditor5\Controller\EntityLinkSuggestionsController::suggestionsto actually use $host_entity_langcode and fetch the correct results.Comment #106
tim.plunkettComment #107
wim leersPicking this up again! Since #30 ~6 months ago this issue doubled in follower count and is now the 19th most followed open issue in Drupal core 🤯 It's only 13 followers behind SDC now (161 vs 174) 😦
I last worked on this ~3 months ago — see #83 for where I left things, with minor follow-ups in early July.
That lists 3 areas of improvement. 2 of which I deferred to CKEditor 5 JS expert @lauriii, who wrote most of the logic for
linkit, plus more test coverage:ckeditor5.plugin.ckeditor5_link_entity_suggestionsAND test edge cases for them. Right now, it's only testing'ckeditor5_link_entity_suggestions' => ['allow_download_links' => TRUE, 'suggestions' => NULL,],.#84 lists one more thing: the ability to specify a priority for each entity type+bundle suggestion. But that can be left to a follow-up? Thoughts?
Self-assigning for tackling the test coverage.
Last but not least:
FieldType=linksupport, which @Berdir and others feel strongly about. But it's hard to gauge how many people think that should block this. Based on @smustgrave in #100, it seems at least some people are in favor of landing this issue without support for the Link field type. Do we consider that a hard blocker or not?Comment #108
wim leersI think this is actually a more accurate title? The title I picked in #16 was still too broad.
I'll continue working on the missing test coverage. Also, I think that all of the "improve JS" bits mentioned in #83 (the part of #61, plus tightening the JS per @larowlan's review) could IMHO happen in follow-ups.
Also, the last JS-related remark from @larowlan was this one: … and the kernel test part is now done, but the functional JS test is still present. And that's exactly what (randomly) failed just now! 😬 Will tackle that too.
Comment #109
mark_fullmerI don't think it should be a hard blocker. Assumptions/rationale:
1. An future enhancement to link fields that make them behave like this CKEditor interface doesn't need to have the same implementation.
2. In the meantime, people can use the contrib module Linkit for this.
Comment #110
mherchel+💯
Perfect is the enemy of good. That can come later IMO
Comment #111
wim leers#109 + #110: noted. 👍
Just pushed the missing test coverage 🥳
AFAICT the remaining feedback since #83 that has not been addressed:
EntityReferenceSelectionplugins are used to provide link suggestions. That means that unless you have thebypass node accesspermission, which usually only is user 1. I think 99% of Drupal sites do not grant content creators that permission? (See also #88.C.2 by @mark_fullmer, and my response to it.)Furthermore, removing the name of the author seems to be something that most sites would not want…
So IMHO in your use case, it seems reasonable to instead override the
ckeditor5.entity_link_suggestionsroute's_controller: '\Drupal\ckeditor5\Controller\EntityLinkSuggestionsController::suggestions'to point to your own controller which subclasses that class and overrides\Drupal\ckeditor5\Controller\EntityLinkSuggestionsController::computeDescription(). Then you can use arbitrarily complex logic to generate suggestions tailored with the knowledge about both your data model and your end content creators!P.S.: I've not been able to reproduce the sole failure locally. Can anybody else reproduce this? 😬
Comment #113
wim leersThanks to @witeksocha from the CKEditor 5 team, I learned that a "boolean attribute" (https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean...) can be created in CKEditor 5 by setting the attribute value to
''. Which is apparently a thing in the HTML spec too: https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute#pa... — so weird! 🫣 TIL.(I pinged them long ago, thanks @mark_fullmer: he had already pointed out the incorrect attribute and the resulting behavior in #88.B.2.)
The bug in #95 was caused by my implementation (
af48eacbfrom March 29) blindly assuming thattrueandfalsewere valid attribute values. As explained above, that's wrong.truegets cast to the string'true'.So test coverage for this is already present, and we can just tweak it:
Next: push the fix! 😊
Comment #114
berdirSlightly adjusted copy & paste from slack.
> FieldType=link support, which @Berdir and others feel strongly about. But it's hard to gauge how many people think that should block this.... Do we consider that a hard blocker or not?
that is not what I'm suggesting. I'm just suggesting that we allow to configure it in a way that is extensible and the link field can build on. once the configuration structure is in place, it is very very hard to change it. so adding it custom now for text formats, and then refactoring it later isn't going to work imho.
It might be less of an issue in the text format UI, but putting a whole configurable entity type/bundle UI into a formatter settings UI, which is quite limited in space, is going to be painful.
> #97: because it'd imply a disjointed experience: first go configure this new configuration entity type somewhere else, then come back here. Is that truly better than configuring the same stuff multiple times? Because … this perspective on how it should work is very different on how core does this in general — that's why I wrote that long D1 response in #91
I don't really get the argument that it would be a new concept for core to first configure something and then use it. many things work like that? you set up an image style and then select that in an image formatter. and that image formatter is part of a view display, that you then select in a view or in an entity reference formatter to use it.
> it's currently impossible to define config dependencies from within a text editor plugin for a Editor config entity 😬😬😬😬 See #2950795-29: CKEditor 4+5 plugin module dependency not added to text format configuration
I see how that's an issue, and I didn't look to closely at the current implementation a while, but fwiw, entity types, bundles and selection plugins *all* are things you already would need to depend on as well. Entity types are plugins provided by certain modules, so you'd need to depend on those modules too if you want to do it correct.
If I'm the only one to think like that then I'm not going to hold this up on that. but I I really think that core should provide extensible and flexible systems that contrib can build on and doesn't have to redo things from scratch. I'll try to do another code review as well when I find the time. Haven't done that since #18.
Comment #115
omkar.podey commentedI went through the issue and found some remaining things @wim.leers , is there anything that should be prioritised from this list or something remaining not mentioned here ?
Comment #116
wim leers#114:
That's fair. In what's below, that's definitely taken care of 😄
#115:
Thanks, @omkar.podey, that's very helpful and much appreciated!
Just spent 1.5 days working on this:
Merged in
origin/10.1.x— since the last commit (Sep 19), Drupal core adopted GitLab CI, and so now this MR gets GitLab CI too 🥳 Much faster test results 👍#115:
I still need to work on updating the actual suggestions to respect this, but … here's a demo of where things are at — I think y'all will like it 😄
👆 This (from #84) did not pan out. It's far too complicated, with additional modals, additional routes, etc. After I scrapped that, I built on top of
'#type' => 'field_ui_table',😅 That also didn't pan out, because it has a weird "parent" thing (that I still don't understand). So I went with a hybrid of all that, with a much more compact UI. And thanks to some of the infra it makes available, it also is able to provide a guaranteed consistent UX across the different screens 😊What do you think?
Comment #117
mherchel😍😍😍
Comment #118
aaronmchaleThis will be a really great addition, very exciting!
Based on the GIF in @Wim Leers comment, one minor concern I have is the use of striking-out entity type names that are disabled. This isn't usually a pattern that we would use, and could be a problem from an accessibility perspective. As in, we still want people to be able to read and understand what the currently disabled options are so that they can decide if there is one there that they want to enable, but striking those options makes it harder to read them. I think have a checkbox is enough to communicate the state.
Thanks
Comment #119
wim leersAll done. The experience for the end user is identical to what it's been for many months now — the only change is that now priorities are respected.
I did improve the admin UX slightly more after #116:

Next up:
entity_link_suggesterconfig entity type, not in theckeditor5_link_entity_suggestionsCKEditor 5 plugin11.x— I cannot do this, only core committers canComment #120
aaronmchaleAlso, one other thing, on the editor configuration screen, where the user is selecting the link suggestion. The "create" option, I don't think should be a radio button. The way I understand the pattern, it can never be selected, so as such I see it shows as a disabled element, but we generally do not recommend using disabled form elements, as different browsers can communicate those differently and it may not be clear to all users that the option is disabled. Having the create option as an action link or a normal link may be a better pattern.
Comment #121
wim leers@AaronMcHale in #118: Agreed. I'd prefer to use the
field_uitable pattern. I already spent half a day fighting that the various table UI mechanisms, plus#type => radios, plus opening this in a modal dialog (and I failed to make it update the underlying page — I can't find a single example in core), plus the use of#type => tableselectnot working with#states. IOW: I've gotten an accelerated course in finding broken edge cases in Form API, AJAX API and DX 😅 I need to get something out there that conveys how I envision this before spending days on making that perfect.If we're going to add this new config entity type, it for sure would need to happen in a separate, hard-blocking issue anyway, where the relevant experts in those subsystems would help us get all those details right :)
Comment #122
wim leers@AaronMcHale in #120 (we cross-posted just now): Agreed again, but unfortunately core has AFAIK zero examples of the "reuse or create" UI pattern — kind of like https://www.drupal.org/project/select_or_other. This was again the best approximation I could come up with in limited time.
Comment #123
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #124
aaronmchaleYep that's totally fine :)
+1
That's a great point, probably something our user interface standards should include in the future. Looking at the
select_or_othermodule you mentioned, based on the screenshot on the module page, I could see that pattern working okay because it's possible to interact with the "Other" checkbox. I think in this case if it the user could actually interact with the "create" radio button, then yeah it would probably also be fine.Hopefully we don't cross post this time 😀 And overall I think we're on a really great direction with this, excited to see it land, definitely something Core has needed! Keep up the great work!
Comment #125
mherchelHere's a quick UI review. Note that the diff doesn't apply to 10.2.x or 11.x, but it does apply to 10.1.x, which is how I left my review.
1. This link doesn't work. It links to the same page. It's especially confusing because when you hover the mouse over it, the tooltip says "open link in a new tab"
2. The modal's form doesn't have a "submit" or "create" button.
3. How does the option for "Allow the user to create download links" work? I didn't see how to do it.
4. The help text of the "Entity Links" checkbox doesn't tell the site builder anything helpful.
Maybe something like "Provides an autocomplete interface for creating links to Drupal entities that will auto-update when the entity's path changes."

5. If you create a new suggester via the modal, the page reloads and the original suggester is still selected. The newly created one should be selected if possible.
Overall this is looking amazing! Thanks for the hard work on it!
Comment #126
wim leers#125:
10.1.x. Until a core committer has chaned this MR to target11.xand the MR has been updated, I recommend to test only a checkout of the actual MR.Fileentities (all of them),Mediaentities that use theFileMediaSource. Out of the box that is true for the "Document" media type for example.filterplugin, not theckeditor5plugin. This is a consequence of "Text Format" and "Text Editor" being distinct concepts that are weirdly connected in the UI only. Solution: #3231354: [PP-2] [META] Discuss: merge the Editor config entity into the FilterFormat config entity. For the scope of this issue, we can tweak the description though, to something like — WDYT? 😊Comment #127
alina.basarabeanu commentedBy changing the branch from 10.1 to 11 the patch failed to apply because of the conflicts.
We heavily use this functionality on our 10.1 website. Can we have it back for 10.1?
Comment #128
wim leers😳
Attached is a
10.1.xpatch reflecting the latest state of the MR. Note that it's never safe to apply patches directly from an MR, since the MR keeps changing. That is a much safer patch to apply 😊Comment #129
alina.basarabeanu commentedThank you for the patch. That saved my day.
Will revise all my patches using a pull request (lesson learned).
Comment #130
pyrello commented@Alina Basarabeanu FWIW, we have started copying patches into our project repo rather than pulling them from drupal.org or the Drupal Gitlab instance. That avoids having to make a copy of the MR diff and post it into the comments of an issue, which ultimately creates more noise for folks that are trying to parse through an issue and make sense of what they should use for a patch.
Comment #131
wim leersWRT #125.5: looks like #3386762: Use modals in field creation and field edit flow could be introducing the infrastructure that will make this easy to achieve, because it has a similar UX, but an entire team on it! 🤩🤞🤞🤞
Comment #132
alina.basarabeanu commentedHi @wim-leers
How can I generate a patch for the Drupal 10.2 version?
Comment #133
ben_a commented@alina-basarabeanu This patch works for me on 10.2
Comment #134
alina.basarabeanu commentedMany thanks, @ben_a
Comment #136
wim leersMy git-fu is not strong enough to merge
origin/11.xinto the MR that was originally against10.2.x😅So replayed all commits excluding the merge commits against the
3317769-cke5-entity-link-suggestions-11.xbranch and created a new MR: https://git.drupalcode.org/project/drupal/-/merge_requests/6277. Only 2 conflicts, with:Finished what I did in #116 through #119 — now the new test coverage should pass again. Which makes it ready for @bnjmnm to take over 😄 @bnjmnm, please convert the old MR back to
10.1.xtarget branch so that you can actually see @larowlan's feedback again in a digestible format 🙏Comment #137
wim leers#3401988: Spell-checking job fails with "Argument list too long" when too many files are changed caused the spellcheck job to fail … hard 😅 Please ignore the
11.xbranch I just created; that's the recommended work-around right now.Comment #138
wim leersI've finished getting this MR to green. That means everything except for the JS is ready. I do realize that we'll probably want to extract the new
EntityLinkSuggesterconfig entity type into its own (blocking MR), but for now it's AFAICT better to keep them together, because on its own, such an MR would not make sense 😅Over to @bnjmnm for getting the JS in tip-top shape! 🥳
Comment #139
wim leersGitLab CI reports 100% success rate but a job failed 🤔 This is due to a bug in the GitLab integration:
is not a test failure but triggers a job failure 😅
This is caused by a small bug in
ConfigExistsConstraintValidator. Fixed here, but created issue to fix it elsewhere: #3416549: ConfigExistsConstraintValidator should ignore NULL values.Comment #140
bnjmnmGlad this was mentioned while I had some time to work on this. I have this largely working locally and will push once I've addressed some details. This particular issue is much easier to address when all of the functionality is provided by core plugins, so an especially good call on core-ifying this linkit feature.
Comment #141
wim leers#3416549: ConfigExistsConstraintValidator should ignore NULL values landed, making this one a tad smaller! 👍 (I just merged in upstream.)
Comment #142
el7cosmosThere is a Search component now, with a demo in https://ckeditor.com/docs/ckeditor5/latest/features/ai-assistant/ai-assi...
Can we look into the possibility of using this component?
Comment #143
solideogloria commentedIf an AI component is integrated, then we need to include a way to disable it. Private sites with proprietary data might not want to have that data sent to/through an AI, and it might even be required by law that it isn't.
Comment #144
scott_euser commentedMight be slightly off topic here TBH, perhaps could move the #142 conversation to a separate issue in the openai module.
Comment #145
el7cosmosNot necessarily talking about AI, it's the component used by the AI plugin which is Search along with AutocompleteView and AutocompleteResultsView.
The screenshot is just to demonstrate this component and the views in action which is used by the AI plugin.
Comment #146
scott_euser commentedAh I see, makes sense, thanks for clarifying!
Comment #147
wim leersThanks, @el7cosmos! Good call. Curious to hear what @bnjmnm thinks 😊 I'm willing to bet that @bnjmnm would say that it'd need thorough accessibility review, and that it is very unlikely the CKEditor 5 team got everything right, and that hence it's better to stick with jQuery UI Autocomplete, which has been thoroughly vetted.
@solideogloria I think you misunderstood: this is about using the dropdown UI component, not the AI plugin.
Comment #148
bnjmnmI've largely addressed the JS needs that this issue was assigned to me for, and there are added FunctionalJavascript tests for that functionality. There's one last @todo in the JS I need some clarification on and will ask @wim.leers about that.
The big JS stuff that made it useful to assign the issue to me is bascially done, though. Unassigning myself but leaving at NW since there are still todos in .php and .yml to address before this can switch to "Needs Review".
Comment #149
wim leersThanks so much for pushing this forward, @bnjmnm, I couldn't have done all that! Digging in … 🤓😄
Comment #153
bradjones1Rebased and rebuilt the ckeditor JS artifacts. Let's see if the test baseline changed. I'll take a stab at some of the non-JS @todos, as well.
Comment #154
bradjones1Tagging needs IS update for remaining tasks. I am investigating this issue on behalf of a client and would potentially be helping move this along.
Rebased and it looks like there are just a few errors relating to schema validation against the current test coverage.
https://git.drupalcode.org/issue/drupal-3317769/-/pipelines/201317/test_...
Comment #155
bradjones1Comment #156
prashant.cThis feature would be an excellent addition to the core. I tried it out locally and came across a few issues (maybe not issues they could be intended behaviors :)).
No content suggestions found. This URL will be used as is.which is correctThank you!
Comment #157
hudriIn response to #156, nr. 1-3, please do NOT make any assumptions on link.
"random string" is a valid link. It will be url-encoded to "random%20string" though, but it is a perfectly valid relative url path. This is clearly a user mistake, not a bug. In our projects, we use and need all flavors of relative, absolute and schema links:
Comment #158
prashant.c@hudri
Correct me if I am mistaken but my point (in point 3) is the relative URL should be treated as internal only but currently it is getting converted to an external URL like "https://randomstring" which is not correct in my opinion.
Comment #159
pameeela commented"random string" is not a relative link though, there is no leading slash. If you tried "/random string", that would be an internal link.
Comment #160
hudri"foo" is a path-relative link.
Like domain.com/sub1/sub2/sub3 => domain.com/sub1/sub2/foo
"/foo" is a domain-relative link.
Like domain.com/sub1/sub2/sub3 => domain.com/foo
Different things, both valid and both have their use cases.
Comment #161
pameeela commentedThanks @hudri, yes I meant domain relative :) This functionality works exactly the same way as Linkit, so I do not think there is anything further to discuss and don't want to create more noise, this issue already has 161 comments!
Comment #162
rkollerthe needs another rebase. after adding when i try to checkout the branch i run into the following error:
it happens when the issue fork was created or last rebased before this issue went in https://git.drupalcode.org/project/drupal/-/commit/8b368d712d83900765744 on the 13th of august fixing spelling errors. the switch to camel case is the problem where the none case sensite file systems ( i am on a mac for example) in combination with git struggles and leads into this error.
Comment #164
idebr commentedComment #165
charles belovIf ability to set the link target is added, please make it configurable as to whether it is available or not, to allow setting a site policy, for example:
Further, it would be good to use plain English labels on the field such as "Open in new tab or window" rather than HTML jargon such as "_blank".
Comment #166
pameeela commentedThe ability to set the link target will not be added here.
Comment #167
pameeela commentedTested this manually, the link suggester settings are not saving correctly -- you can unselect a content type but this change doesn't persist:

I've also tried to update the IS to make it a bit easier to read, but it still probably needs more work.
Comment #168
pameeela commentedSeparate to the functional testing I have some overall feedback, but just wanted to say it's really awesome to see this getting so close to ready!
The 'Everything!' label feels a bit unserious for the UI. Would it be better to use 'Default' which I think matches other instances of config that is provided?

I'm -1 to enabling everything by default anyway, it would seem much better to enable the common things: content and files and *maybe* taxonomy terms? Users doesn't strike me as a commonly linked item either, but files does, so I'm not sure what the 'commonly linked' descriptor is based on? I think shortcut sets and comment entities should definitely be disabled at least.

The link itself is prepended with

entity:, which is different from Linkit and IMO this is a Drupalism that we should avoid.Linkit:
This MR:


Comment #169
rkollerI've taken a lookt at the aural interface in voiceover on macos sonoma (see voiceover.mp4), a few observations:
content - article,contact form,fileand so on are unavailable in the aural interface.and unrelated to screenreaders, woult it make sense to leave a pointer either on
admin/config/content/link-suggestersor on the link suggestor edit page either in a help text or a description pointing out that for activating the link suggestor the "Entity Links" checkbox has to be ticked on a text format? At the moment that fact is implied.Comment #170
rob230 commentedHas there been any consideration about showing something other than
node/123orentity:node/123? This is something I get asked/complained about most by clients and editors with the Linkit module in D10.A node number means nothing to them. They want to know what it links to (page title or path alias) and they have no way of finding this out when editing, besides opening the link.
Maybe it's a niche request. For me, the way it works is totally fine, but I think less technical people don't know what "/node/2934" means and they want to know from within the editor what page is linked to. The autocomplete when adding a new link works amazingly and provides lots of information.
Comment #171
ronttizz commentedThis seems almost perfect what I would currently need in one of our project.
My suggestion is that this link could also optionally be utilising the UUID of the target node as in JSONAPI:Extras UUID link enhancer can output:
entity:node/{{contenttype}}/{{uuid}}In the project I am currently working on, we have this need for the UUID in the links inside the text. Would it be possible to implement or could someone point me to correct way how this would be possible?
Comment #172
pameeela commented@rob230 that makes sense to me, sounds like a great follow up feature!
Comment #173
pameeela commentedHave discussed this with @lauriii and @bnjmnm at DrupalCon Barcelona. Here is a summary:
Comment #174
pameeela commentedDiscussing the terminology now with @_deadarm_
Comment #175
wim leersI self-assigned on Feb 29, >6 months ago, in #149. 🙈
Thanks everyone for pushing this forward, based on #173 this seems tantalizingly close ❤️
Comment #176
el7cosmosPushed a fix addressing #167
Comment #177
pameeela commentedThanks @el7cosmos, confirming that issue is fixed.
Also checked that new content types are enabled automatically as long as all content types are enabled. If not, then new ones are not. I think this works as expected.
So the two remaining tasks are:
We discussed it at DrupalCon and a bit after, but have yet to find something that works.
Comment #178
charles belovHmmm, if the behavior of whether or not a new content type is automatically enabled is dependent on whether or not all existing content types are enabled...
Then is there any feedback to the administrator that this logic decision has taken place? While this may be the expected behavior, it is still easy to overlook if it is not the desired behavior for a particular content type. I recognize that the change in configuration may have occurred in code rather than through interaction with the administrative user interface. Just trying to avoid surprises.
I'm thinking it would make sense if there was a checkbox at the top labeled "All" that was checked, but not if it's simply checking to see that all the pre-existing checkboxes were previously checked. At the very least, is this behavior documented somewhere?
Comment #179
johnpitcairn commentedAn established pattern in core and contrib is that all checkboxes unchecked means "all". But what happens in that scenario if the only checked target type is deleted? Now nothing is checked. Is everything then silently enabled?
All checked meaning any new content types also become checked is very weird, don't think I've seen that behaviour anywhere else.
I agree an explicit "all" option would be better than either.
Comment #180
rkollerI've noticed one other detail applying the latest changes that went unnoticed on my first check. if you are on a text format edit form and you are setting up the linking and you have no
link suggestercreated yet you only see thecreate new link suggesterlink on theentity link suggestions vertical tab. there are two problems1) if you are clicking the
create new link suggesterlink theadd link suggesterdialog is opened in a dialog modal. thecreatebutton as well as the button label are both close to invisible at the bottom of the modal. i had to actively search for it. that isnt meeting SC1.4.3 and SC 1.4.11. On hover the styles are correctly applied and the buttons turns dark blue.2) If i create a
link suggestervia the dialog modal, when thelink suggesterwas successfully created theentity linkscheckbox is unchecked. i have to manually recheck the checkbox and then select the newly createdlink suggestorand save. from my perspective that step should be unnecessary. theentity linkscheckbox should remain checked and the newly createdlink suggestershould be auto selected. that was the reason i created the link within the text format page in the first place - to use it in the context of this text format as the suggester.i think point 1 needs to be addressed within this issue, point 2 could be moved to a followup issue.
Comment #181
pameeela commentedI disagree with #178 and #179 that enabling new content types by default is unexpected. I guess I don't have a big issue with adding an 'All' checkbox but I don't think it's needed.
Re: point 1 in #180 isn't this an edge case since it will ship with two suggesters? So this would only happen if someone deleted both of them (which you can only do directly in the link suggester config) and then tried to add one via the modal?
Comment #182
rkollerhm problem is, it is not only the case when a suggester is created on a text format. just explored it a bit more, it is also the case when you edit a suggester on the text format. there, instead of the
savebutton, the problem applies to theupdateanddeletebutton. and on a side note "update" as the button label is kind of unusual, usually "save" is used in that context?update: and it looks like the ui-widget class (in the theme.css from jquery ui line 19) is overriding the background color and setting it from the primary color blue / and grey for the regular button to transparent. and comparing the buttons in the footer of a dialog modal with
admin/structure/display-modes/view/manage/node.full?destination=/admin/structure/display-modes/view, the sizing differs. but that is rather cosmetic. the color contrast is the more serious problem.Comment #183
lauriiiI know that I've reviewed this in the past but I'm having some second thoughts about the UX now that I'm looking at this with fresh eyes, I'm concerned that we may be over complicating the user experience for the site builder. I'm trying to think of the use cases for this. I was able to identify use cases that map under two categories:
It seems that we are optimizing for the 2nd use case, whilst making 1st harder. I'm not sure if that's the right trade-off because this is not an actual restriction for the content authors, because they can still link to any content, they just don't get suggestions to all content.
The UX pattern that we require configuration outside of the Field UI is not great. This is not unique to this patch, for example, Pathauto suffers from this too. I'd imagine the ideal UX for this to be that you could configure this in the context of the content type, e.g., checkbox with label "Allow linking to this content type".
I think we should prioritize the use case 1. first, and do that really well. Once we've nailed that, we could have contrib or core implement a solution for the 2nd use case.
Comment #184
catch@rkoller the button issue you're seeing looks like a CSS bug with modals unrelated to the MR. I can't think of other UIs in core that use a similar modal but if we can find one it would be good to confirm whether it's a general problem or not.
@lauriii The UI does look very complex to me. I have one concern about just allowing all entities though in that I can't see anyone ever wanting to link to a comment from ckeditor, (except in the very specific case of Drupal.org which I realised the irony of as I was typing...), and the same with custom menu links (i.e. you wouldn't link to the link, you'd link to the page that the link points to maybe).
This gave me an idea - what if define this at the bundle level in hook_entity_bundle_info(), defaulting to off.
Then we can try to set sensible defaults in core (i.e. on for all node bundles and media bundles, off for comments and menu links). Sites can use hook_entity_bundle_info_alter() to customise it, and either core or a contrib module could do that via config with a UI later.
But also as long as we're happy to restrict the default available suggestions after the initial lands (i.e. a behaviour change for content editors), even that API level support could happen in a follow-up if it helps this get in.
Comment #185
lauriiiI was thinking that we could provide the setting on different entity types but we should definitely do some curating where content types could default to allowed and others default to not allowed. This would enable use cases such as linking to media, which is a valid use case.
I like this suggestion. I'm wondering if we should also provide an API that makes it possible for contrib to provide multiple link suggesters for the use cases where you specifically want to restrict the list for a specific use case.
IMO this would be fine for this functionality.
Comment #186
rkoller@catch for example if you are editing any of the view modes on
admin/structure/display-modes/view. i just realized that the direct link i've provided for the full content view mode in #182 is displayed as a page instead of in a dialog modal, you have to click the edit button to open it in the dialog modal. but those view modes use a similar modal.Comment #187
pameeela commentedFWIW, even the Drupal.org use case does not really make sense to me, because for one thing comments here don't have a title. I suppose you could search on the comment body but how on earth would you find what you are looking for? So I really do struggle to place the comment use case (same for custom menu links as catch also noted).
I tried to update the IS based on #184 but re-reading it I am not totally sure what is being suggested as the initial approach.
Is this to say it would initially suggest everything linkable? I find myself so strongly opposed to this but at the same time, if you don't have shortcuts, comment or contact installed, you won't see these anyway so maybe it doesn't matter much!
Comment #188
catchI also don't particularly like the idea of this and think we could do a per-bundle opt-in (in PHP, not config) pretty quickly/easily. But also if we can get an initial unfiltered issue and an opt-in issue done in the same minor release window, no-one would ever see the unfiltered version.
I can try to open up the two follow-ups that are implied by the recent discussion a bit later.
Comment #190
catchI thought about this more and re-reviewed the MR.
Because this is using entity reference selection handlers to get the suggestions, it needs some concept of allowed entity types, otherwise it would have to query every entity type one by one.
However if we use bundle info, it's just a few lines of code to rely on that.
I've put up an additional draft branch/MR here: https://git.drupalcode.org/project/drupal/-/merge_requests/9807
This does the following:
1. Hacks out most of the supporting code for the link suggester config entity. There are still more places to remove.
2. Does an untested implementation of using bundle info instead.
I didn't touch any of the test coverage or do anything else except rebase. However, this ought to be enough to show the general direction for someone who wants to take this further.
The next tasks would be:
1. Manually test the MR and debug any obvious bugs introduced, so that the ckeditor plugin actually works.
2. Clean up more remnants of the config entity (including references from the ckeditor5 config).
3. Adjust the tests. Probably mostly removing coverage for things that aren't supported any longer, keeping the actual plugin test just with whatever default entity types/bundles we support.
I also noticed some additional issues in the MR, like CSS is still using .linkit classnames and similar, that also would need to be sorted out before commit.
Comment #191
sourojeetpaul commentedI'm having a look at this!
Comment #192
sourojeetpaul commentedHii,
Wooh quite a pretty long comment thread, probably the longest I've participated yet! I think I was living under the rock till now and just couple of days ago discovered this from Drupal Slack. I'm quite excited and thrilled about this new feature request, it'll be a complete game changer and much awaited one!
After going through all the comments from the beginning, I must acknowledge that I got an enriching learning experience, got to know about many intrecacies that I wasn't even aware of till now!
Though the issue seems to be requiring of supreme experience, but I couldn't resist myself to participate here.
As of now, just noticed some tiny syntactical errors for which after applying the patch, the site and drush was getting crashed, so did some quick tiny fixes. I'll keep on having a look at it from tomorrow again to investigate and test further!
Thanks and Regards :)
Comment #193
catch@sourojeetpaul that's great, sometimes jumping in at the deep end is the best way to learn - both core APIs you might not be familiar with, and also things about core contribution you might not have come across yet.
If you've made any fixes, even very small and incomplete ones, please make a commit and push them to the MR here - makes it easier to get early feedback and/or for people to follow along.
Comment #194
sourojeetpaul commentedHi @catch,
Thanks for your kind words and motivation. Its not that I haven't yet came across Core contributions, I've actually worked on a no of core issues and thankfully enough, got recognised for 3 of them as of now. I'm aware that Core issues are bit tricky and threads go on for a longer period of time. But this one is truly exceptional and interesting to work on, and lengthiest as of my experience. Sharing the similar thought I've started looking forward to Core issues as that provides a solid learning experience.
I've already pushed my changes on your branch before making the previous comment, but I was also wondering why that's not getting shown on the threads. Is it because you've kept the MR as draft?
Here's the commit link: https://git.drupalcode.org/project/drupal/-/merge_requests/9807/diffs?co...
Please have a look and pour in your valuable feedback :)
I'll dig up further from tomorrow, had to scratch my head a lot today on this. Was getting quite a few issues while applying the patch, but luckily resolved those, and now my system also gave up by running multiple instances xD
Comment #195
catchBoth those changes look good, fixing my silly mistakes/typos when I made the draft.
Comment #196
sourojeetpaul commentedHi @catch,
Though after fixing the syntactical errors, the patch is now cleanly getting applied and entity_links filter is getting listed among the available filters to be enabled, but on trying to enable the filter its trowing an Ajax error on the console, which is due to the fact that we're calling the loadMultiple() method of EntityLinkSuggester, but the entity was never defined in the codebase. So I think the MR is still missing some files!
Please correct me if I'm wrong :)
That's why I resorted back to the previous solution that @wim and others have provided, to experience the functionality. Also played around and performed a bit of testing on that to ensure that the previous issues which were mentioned have been addressed well and jotted down few pointers, which IMO will be an enhancement on top of that, or incorporate those in this latest approach.
1. On linking to a downloadable media, and coming back to that again on editing, the toggle as well as the downloadable state remains unchanged. So the issue that @mark_fullmer had mentioned seems to be resolved!
2. I wasn't able to reproduce the 'Update' button styling issue on the Link Suggester modal that @rkoller had mentioned. the 'Update' and 'Delete' button styling over there looks good to me!
3. Though the strike-through over the entity names doesn't seem to be causing much of a big deal in terms of accessibility to visual impaired users, but I think there's a design inconsistency happening. On deselecting the entity type the strike-through happens while deselecting the bundle remains clean with just the unchecking of the checkbox, so IMO it'd be better if we can style both of them in a single pattern.
4. Tested the issue that @pameeela had mentioned that link suggester settings not getting saved properly, but now I see its getting saved properly and coming into effect as expected. Keeping only Node A checked by deselecting Node B, as expected its restricting to the contents of Node A only and not showing any content of Node B while linking from CkEditor.
5. Performed a quick accessibility testing using Wave tools for the missing 'title' attribute on the a tag, on which there's a discussion on this issue, but honestly that doesn't seem to be an issue to me and Wave is also not reporting any issues for the same!
6. Coming to the linking aspect of Comments, I'll also echo the same as of you and @pameeela. Couldn't find major use case for this one, rather its a super confusing one with the fact that @pameeela already pointed on the earlier threads.
I found one difference from the way we're implementing here vs the way D.O does the same, as D.O uses specific comment id for each of the comments and uses the same as anchor linking, thereby we reach to that specific position of the webpage directly, whereas in our case as we're referring to the comment entity which in turn actually referring to the node, where the comment have been added. And let's say on such a blog post or webpage if there're tons of comments like this issue thread :) then there's no point on landing the user at the very beginning of the same, where the user have to manually scroll down to that specific comment again. It'll be a pretty bad UX IMO.
7.
I'd partially agree with you and @pameeela on the 'Custom Menu Link' aspect. Though it'll link to a page but I think giving the ability to search and link to the page using menu titles might be easier for content editors, specifically when instead of referring to a node or any other internal link the link is of an external one.
Now coming to the part, which I think can be a great enhancement on top of it:
1. Moderation State Indication: On incorporating workflows and content moderation, though we can restrict the view permissions based on roles but there are no way we can restrict linking to 'Unpublished/Draft' contents as of now. I don't think that makes any sense at all to link to an Unpublished content that the end users might not access and without any sort of indication for the same on the list the content editor might accidentally link to such a content. So I strongly feel that you should somehow indicate about the content's current moderation state, which IMO will be more helpful than the authoring date information.
2. Permission based suggester access: As of now we can create multiple link suggesters, but there's no way to restrict and assign the same based on user role. Let's say we have multiple content editors and we want to give them different linking privileges and thus having the option of creating multiple suggesters will make more sense!
3. Suggester Clubbing: Though we can define multiple link suggesters and use them in different text formats and editors, I was thinking about from a more user role perspective.What if we give the user an ability to club multiple suggesters. Circling back to my previous example:
On a group of multiple content editors, we defined different link suggesters for each of the roles with defined access privileges, and for the Content Head/Editorial Head instead of creating a new suggester from scratch, we can just club all the suggester groups that we've created for other editors.(basically a multi-select of the existing ones).
Attaching the screenshots of my testing for quick reference!
I’ll be all ears for your feedback soon! Thanks :)
Comment #197
catchYes so the idea from the last few comments here is to completely get rid of the link suggesters from this issue, and use the bundle info instead. I didn't try to get to a working MR, I just tried to point in the direction things should go. It sounds like you found the next step that would need to be done.
The eventual UX of using the plugin in ckeditor5 should stay the same, we're just trying to get rid of all the configuration infrastructure and interface for that.
Comment #198
pameeela commentedTried to Update the IS based on the latest approach, but there may be corrections needed.
Comment #199
sea2709 commentedI checked out the branch
3317769-link-suggestions-minimum, then I went to Basic HTML configuration and enabled "Entity Links" filter, then I clicked Save configuration. Then I got the fatal errorDoes anyone run into this issue?
Comment #200
pameeela commentedYes, the branch is broken, this issue is set to 'Needs work' as it has to be reimplemented based on the updated plan.
Comment #201
sea2709 commentedI'd like to work on this one if there's no one working on it at this point. I spent a couple of hours to dive into the changes @catch did on the new branch and got the ideas.
My first step is to make the update editor configuration work after enabling the entity links plugin. By default, node entity type is allowed to provide link suggestions when the plugin is enabled. In the plugin settings section, we should be able to configure which entity types and their bundles providing link suggestions.
Comment #202
alina.basarabeanu commentedHi
Can anyone provide a patch for Drupal Core 10.3?
None of the above applies and I can not upgrade the project.
Comment #203
catchWith my MR there should not be any configuration at all, it should only rely on the bundle info - this is the simplification with the new approach.
Comment #204
sea2709 commented@catch: I just pushed some changes mostly for cleaning up the EntityLinkSuggestion entity type, and making the ckeditor plugin work. My next step is to fix unit tests. When you have time, can you take a look at my changes? Just want make sure that I'm on the right direction. Thanks!
Comment #205
catch@sea2709 yes only had a quick look but that all looks along the right direction, thanks for picking this up!
Comment #207
sea2709 commented@catch:
I'm not sure if there is anything I need to work on this issue. But I finished things that you listed in #190 . I added some info about entities providing link suggestions when admin enabled the plugin.

By default, the suggestion plugin only suggests node entities. I'm not really familiar with unit tests, so I don't know if I need to write some unit tests for cases when modules implementing the hook_entity_bundle_info() to enable entity suggestions? And I see that this plugin has an option "Allow the user to create download links", do I need to write a test case for this? If yes, what kind of test case it should be?
I created a new branch
3317769-link-suggestions-minimum-2because I ran into a javascript functional test failed which was not related to the plugin this branch, so I thought the test was failed because the branch was behind the 11.x branch, so I merged 11.x branch into the current branch, and more jobs in the pipeline failed.When you have a chance, can you review my work? If there is anything else I need to work, please let me know. Thanks!
Comment #208
catch@sea2709
There are various random-but-frequent test failures in HEAD at the moment, I think you ran into those. Looks like the MR is green now.
there's already some test coverage for allow_download_links e.g. https://git.drupalcode.org/project/drupal/-/merge_requests/10036/diffs?f... so that is probably covered.
This looks good to me - but I didn't manually test it probably someone should.
We're already testing when node bundles are enabled by the hook, so for me that is enough. Testing other entity types would essentially be testing whether bundle info works.
The one thing we might be missing coverage for is when two different entity types are enabled at the same time maybe?
Comment #209
sea2709 commented@catch
Two different entity types, you mean that we enable one more entity type, for example "Contact Form"? Or a test case covers 2 bundles of an entity type? I just checked this test file https://git.drupalcode.org/project/drupal/-/blob/26f5c7d8f4ab548079d2986... , this test case just covers only "page" bundle, I guess I should create a new test case with 2 bundles "article" and "page"
Comment #210
catch@sea2709 I meant two different entity types like say node and taxonomy. We could add a test module that alters entity info to enable suggestions for a taxonomy vocabulary then make sure a term is suggested. Reason I mention this is because the code path is different for entity types that aren't the host entity so that might be untested code at the moment.
Two bundles of the same entity type we could also add explicit coverage for too if it's not there already however I definitely wouldn't block commit on that since I think the existing coverage should be enough to catch most things that could actually go wrong there.
Comment #211
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #212
sea2709 commented@catch
I added more test cases for enabling multi entity types to provide entity link suggestions! I think the PR is ready for review :-)
Comment #213
sea2709 commentedComment #214
pameeela commentedThis is looking awesome!

Just a few minor things. The node titles need decoding:

And some minor tweaks to the filter settings, to align with what is available now. Also thinking we should probably indicate here that this is not configurable yet (i.e. all bundles are supported for this entity type), but not sure the best way to say that. I don't think it's a showstopper.

Comment #215
sea2709 commentedThanks @pameeela for your feedback.
Will update based on your comments soon!
Comment #216
sea2709 commented@pameeela

I fixed the issue about node title not decoding html entities. I also update the entity links plugin settings
I removed the download configuration from the admin UI, code and test cases as well. Please let me know if we should add any texts to make it clear about this plugin, and how it works or how to extend more entity types.
@catch
I believe the MR is ready to review.
Comment #217
sea2709 commentedComment #218
pameeela commentedThis looks great to me! I just tweaked the filter name to use sentence case to match the other filters.
Happy to leave the other filter messaging as is because it's awkward to try to explain, and the situation is only temporary.
Comment #219
longwaveAdded some review feedback, mostly about return types but some other questions dotted around too - there are still lots of todos that either need resolving or followups. I only reviewed the PHP and did not look at the JavaScript.
Comment #220
drpldrp commentedIs the linked entity data saved in the source, for example title/label, updated when the linked entity is updated?
I apologize if this is covered in the comments, I tried looking for it and didn't see it.
I recently wrote a method for linkit to show path alias in the ckeditor5 link form view (ie. preview/edit link balloon) using synchronous xhr because I thought it would be bad if the info saved to source isn't updated when the linked entity is updated.
--
Maybe the linked entity data can be pre-rendered/form altered into the editor field as data-attributes so they are available to the initial upcast/downcast process and loaded into the ckeditor plugin objects, but also have it be consumed so that it isn't present in the end markup to avoid false new revisions and stale linked entity data.
Comment #221
sea2709 commented@drpldrp
This is how the data is stored
<a href="entity:node/1" data-entity-type="node" data-entity-uuid="708ee5de-a17f-4ed4-a6a7-f90d94998c14" data-entity-metadata="{"description":"by admin on Mon, 11 Nov 2024 - 14:44","entity_type_id":"node","entity_uuid":"708ee5de-a17f-4ed4-a6a7-f90d94998c14","group":"Content - Article","label":"Article 1","path":"entity:node/1","value":"Article 1"}">Article</a></p><p><a href="entity:node/2" data-entity-type="node" data-entity-uuid="af8458ea-1d33-45fb-b9cd-88c8c1f0668b" data-entity-metadata="{"description":"by admin on Mon, 11 Nov 2024 - 14:52","entity_type_id":"node","entity_uuid":"af8458ea-1d33-45fb-b9cd-88c8c1f0668b","group":"Content - Article","label":"Article 2","path":"entity:node/2","value":"Article 2"}">Test</a>Title/label is not supported at this point.
data-entity-metadatainfo is generated when the user click on a suggestion and will not be updated when the suggestion entity is updated.I would say, linkit module has more features than what we're doing it for the core :-)
Comment #222
sea2709 commented@catch & @longwave
When you have some time, can you give another round of review? Thanks!
Comment #226
smustgrave commented@ramprassad why are you opening other MRs when 10036 is pointing to the right branch? Those additional ones should be closed please
Comment #228
quietone commentedThere are @todos in the change record so tagging for an update.
Comment #229
ramprassad commented@smustgrave I have created a merge request for 11.x compatibility (MR10351), please check. There is a JSLint issue reported, will check and post further updates. The additional MR created is closed.
Comment #230
catchhttps://git.drupalcode.org/project/drupal/-/merge_requests/10036 is the merge request to be working from here, it is already against 11.x and just needs a rebase. I'm going to hide all the other branches here now.
Comment #237
martijn de wit-- sry wrong post
Comment #238
longwaveMR needs rebasing, plus the other "needs" tags must be completed before this can be RTBC.
Comment #239
pameeela commentedI updated the issue summary for the new approach so I think at least that is done.
Comment #240
tim.plunkettAttempting a rebase, this is trickier because of all the hook conversions
Comment #241
tim.plunkettCrosspost. There were too many existing merge commits to sanely rebase this, which was sad. So I'm adding to the pile by merging, again
Comment #242
tim.plunkett:facepalm: on the tags
Comment #243
tim.plunkettComment #245
guptahemant commentedObserved one weird autocomplete bug while testing the feature where the content list is not available on adding full keyword.
Here are the steps
Create 2 content of different content types having test in their title.
Observe the result for tes keyword
compare with the results for test keyword.
Attaching the screenshots for reference.
Update note This happened at random, not able to reproduce this consistently.
Comment #246
pameeela commented@guptahemant I'm not able to reproduce this issue.
I also tested it with Linkit already installed. If both Linkit and the new entity links filter are enabled, Linkit takes over which I think is totally fine. I'm not sure why someone would turn this on without turning off Linkit, but it works.
Comment #247
larowlanComment #248
gpf commentedI am currently using Drupal 10 and the Linkit module. Will I encounter any issues if I simply disable it and start using the core functionality in Drupal 11?
Comment #249
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #250
dimitriskr commentedrestored IS
Comment #252
steinmb commentedBot changed status, but I think it is ready for review?
Comment #253
smustgrave commentedTest failure seems relevant to the change here.
Comment #254
deimos commentedI needed changes from MR!10036 for customers project but for Drupal 10.3.14. So I created a patch for D10.3.14. I post it just in case someone needs it same as me.
ps: Note, it doesn't have tests updates.
Comment #255
andrew.wang commentedIt might be easier to simply install the Linkit module on Drupal 10.3?
Comment #256
dbielke1986 commented@andrew.wang
Of course, but that's exactly what this post is about: implementing a nice link experience, like LinkIt has.
This is certainly an enrichment of the core and should therefore also go into it, without the need for a Contrib module.
Comment #257
pere orgaI believe the second one is supposed to say
data-entity-uuidinstead.Comment #258
pere orga@dbielke1986, I believe @andrew.wang is responding to #254 and pointing out that creating a patch for Drupal 10.3 - which isn't even the latest release in the Drupal 10 series - is not better than using the Linkit module. I agree, since this functionality likely won't be merged into any Drupal 10 version (or will it?). This assuming there's a solid migration path from the Linkit module.
Comment #259
catchThis wouldn't get backported to Drupal 10. If the MR was rebased and test failures fixed, and it was reviewed/RTBCd in the next ten days it might be able to land in 11.2.0 still, more likely early in 11.3. That would be a much better use of time than creating 10.x versions of the patch if someone has time to take a look. This has been quite close to being committable for a while now I think.
Comment #260
acbramley commentedWill try to get this green today
Comment #261
acbramley commentedAdded https://www.drupal.org/node/3524296 and linked to it from the other CR.
I don't think we need a CR for the MediaSourceInterface::METADATA_ATTRIBUTE_LINK_TARGET, happy to be told otherwise though :)
Comment #262
acbramley commentedThis is now green
The last outstanding thread is https://git.drupalcode.org/project/drupal/-/merge_requests/10036#note_40...
Not sure how to handle BC for this.
Comment #263
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #264
acbramley commentedThe upgrade to CKE5 45.2 (#3523018: Update CKEditor 5 to 45.2.0) has broken this and I'm struggling to figure out the breaking change, it's not clear from their docs.
Our new plugins does this:
But in the 45.0 upgrade notes:
So
editor.plugins.get('LinkUI').toolbarViewworks but then I'm not sure how to access the equivalent button view from the toolbarViewhttps://ckeditor.com/docs/ckeditor5/latest/api/module_ui_toolbar_toolbar...
Comment #265
acbramley commentedAdding credit for @el7cosmos, we are trying to figure this out in slack.
Notable links so far from him:
The breaking change in CKE5 https://github.com/ckeditor/ckeditor5/pull/17283
This new class looks like what we want to get, but I have no idea how to get it https://ckeditor.com/docs/ckeditor5/latest/api/module_link_ui_linkprevie...
Comment #266
acbramley commentedThis seems to work
But then when submitting the balloon we get
Can't convert undefined to object, this is because of this chunk in_handleExtraFormFieldSubmit:In 45.2,
argshas 3 entries, one of which isundefined, which means it drops into the 2nd condition and it throws the above error.Going back to 44.0, args only has 2 entries at this point so drops into the first condition.
Changing the conditions to
args.length < 4andargs.length === 4sort of fixes it but then the preview of the link is no longer the nice entity label, the preview link is broken, etc.I've stretched my CKE knowledge further than I probably should have and have no idea where to go from here.
Comment #267
el7cosmosI've changed the
actionsViewtotoolbarView.I also removed
previewButton.setTemplateas I'm not sure if it is still required. Instead, I bind the preview buttonhrefandlabelproperty to the entity metadata.There are failed tests, which I think are related to the UI changes, but I don't have the bandwidth to look at them at the moment.
Comment #268
godotislateI think the removed

setTemplate()code has broken some functionality, especially with media and image links. The link preview for those does not show the entity label anymore.This is a regression because it fails a test for that.
Among some other issues to resolve, the CSS for the autocomplete can bust the new link UI by pushing the "Insert" button outside the balloon:
I made some code changes to fix other test failures, but I'll try to another look later today if I have time before pushing those up, since not all the test issues are resolved.
Comment #269
godotislateI've pushed these up in case anyone else wants to pick up. Haven't found solution to issues mentioned in #268.
Comment #270
acbramley commentedYeah as per #268 the preview template is what gave the nice entity label + link preview after selection.
Comment #271
acbramley commented@el7cosmos great job, everything looks to be working well now!
I do wonder if we should strip the
data-entity-metadataattribute on page output, this can expose information that wouldn't have been exposed before when linking to a page, most importantly the author. As an anonymous user I see this in the markup:{"description":"by admin on Thu, 12 Jun 2025 - 23:26","entity_type_id":"node","entity_uuid":"ac3bcdb9-d7b9-4155-9049-e954c113a428","group":"Content - Basic page","label":"test 1","path":"entity:node/1","value":"test 1"}Comment #272
el7cosmosSince this already requires a filter plugin, it is probably worth removing that attribute in the filter.
Comment #273
claudiu.cristeaI have a functional question: There is the
Drupal\filter\Plugin\Filter\EntityLinks, which I see it very useful because it preserves the link alive in the case the file is moved. I had recently such a case handled by LinkIt similar filter, in which the file has been moved and, because of this filter, the file is still reachable on click. However, while editing, the editor can still see the old URL and this can make it confusing. Is it possible that on loading the form we apply the same "check for real URL", so that the link is updated? Or we should totally drop thehrefattribute and use a Drupal-proprietary HTML tag, in the same way as we're embedding media, so we're not confusing anyone about thehrefattribute?Comment #274
larowlanComment #275
lauriiiPer @pameeela, this should be a Drupal CMS release target.
Comment #276
mark_fullmerAs the maintainer for Linkit, and a contributor to Editor Advanced Link, I want to draw attention to an API change introduced in CKEditor v45+, which is used on Drupal 10.5+ and 11.2+: the API now includes a "displayedText" input, as shown in https://ckeditor.com/blog/ckeditor-45-0-0-release-highlights/#smarter-li... . As a result, the way that link attributes are stored must change in the
argsobject. Now, all attributes must be stored inargs[1], namespaced, while the displayedText will go in the finalargsslot.This resulted in multiple refactors required in the Linkit module and Editor Advanced Link to avoid breakage: #3540235: [CKEditor v45] Editing Displayed text from collapsed selection generates multiple links and #3534699: [CKEditor5 v45+] Attributes can overwrite other attributes and editing displayed text from collapsed selection generates multiple links
This problem is present in the current implementation staged for this issue, demonstrated in the video below:
Since there are substantial API changes, I've opted to present remediation as a separate commit on a separate branch/MR, at https://git.drupalcode.org/issue/drupal-3317769/-/merge_requests/1 , so that it can be reviewed in isolation. Ideally, it can be merged into the main MR.
This implementation is modeled after CKEditor5's own logic for links. See packages/ckeditor5-style/src/integrations/link.ts
Steps to reproduce problem shown above
Comment #277
acbramley commented@mark_fullmer happy for you to push that change to the main MR, I'd say you're the expert on this after all!
Only thing that needs changing is to remove the reference to linkit in one of the comments "Clear out linkit attributes..."
Comment #279
mark_fullmerDone. Thanks so much for work on the test cleanup. I'm working on remaining eslint violations now...
Comment #280
acbramley commented@mark_fullmer nice work, I was hoping you'd be able to figure out the linting issues because I couldn't even see the errors in CI or locally! Looks like this is green now and ready for review! I'll be doing some manual testing on it today
Comment #281
acbramley commentedUnfortunately found a bug with manual testing when retesting the issue in #276
At step 6 the link has now changed to
<a href="https://node/3">foo</a>so all data-* attributes were stripped, and the href is busted (but the link text did get updated)Comment #282
mark_fullmerHrm! I'm unable to reproduce this using (I think!) the same steps from #276. Here's a screenshare of what I'm doing, so we can triangulate what the trigger is: https://www.drupal.org/files/issues/2025-10-21/data-attributes.gif
Comment #283
acbramley commented@mark_fullmer woops I should've tested more thoroughly.
I can reproduce it 2 ways:
1. Save the node, then edit it again and follow the same steps.
2. Also, without saving the node, click into the Link URL field to get the suggestions dropdown again then just click Update (don't select anything)
I'm trying to screen record it but currently having issues getting the recording working
Comment #284
acbramley commentedHere's the edit bug
Comment #285
acbramley commentedHere's the other one
Comment #286
mark_fullmerWell, kudos to @acbramley: bugs in #284 and #285 appear to be completely separate from the bug in #276 -- I confirmed that both problems existed prior to the most recent round of code changes -- so Bug Bounty x2 for you!
#285 is resolved with commit 44cbfae0; we need to account for the scenario where the autocomplete is triggered, but no change is made to the selection, in which case the data attributes need to be retrieved from state, rather than the event.
#284 is more weird! Data such as
href="entity:node/1"is saved to the database, but upon load -- apparently prior to any JS code executing from our plugin -- CKEditor converts this tohref="node/1", and things fall apart from there. Not sure if this is CKEditor validation?Comment #287
acbramley commentedConfirming #285 is fixed.
I found the same re #284 - the issue is the href loses the entity: prefix. I have no idea how this is happening.
EDIT 1: So far I've been able to confirm it's not javascript modifying the href (disabling JS shows the same issue), debugging into the TextFormat element plugin shows the correct value exists in
$element['value']['#default_value']tooComment #288
johnpitcairn commentedCould this be everyone's old friend #2544110: XSS attribute filtering is inconsistent and strips valid attributes ?
Comment #289
mark_fullmerIndeed. Manual experimentation shows that with "Limit allowed HTML tags and correct faulty HTML" disabled, this href stripping does not occur.
Comment #290
smustgrave commentedI don't want to derail this at all. Is there functionality from linkit that won't be covered by this change? Just to help evaluate using this later.
Comment #291
mark_fullmerGood point. I'd created a list of functional differences between this and Linkit awhile back shown below. This list is probably outdated at this point, but it's a start. We should do a comprehensive catalog.
Comment #292
charles belovThere would also be the question, when the number of items is limited, how to determine which items get shown in the auto suggest and which items get excluded. You might need to ensure that shorter titles are shown, because if two pages have matching titles up to a certain point, you can exclude the shorter title by adding more characters. But if the shorter title is not shown, there is no way to exclude the longer title by removing characters, so you would never be able to see the page with a shorter title in the auto suggest.
Comment #293
mark_fullmerOkay, so yes, this comes from
filterXss(), as originally called out by Wim in #91. The design indicated there is thatcore.services.ymladds a protocol allowance forentity, along with an update to thedefault.services.yml. But if an existing site has its ownservices.ymlfile that does not include this, then the site will strip outentity:and we have this problem, which is the scenario under which @acbramley presumably found it. If adoption of this new functionality requires existing sites to update theirservices.ymlfile, this seems like it could lead to a lot of headaches. At a minimum we need a big mention of this in the change record.However, I'd like to double-check whether we even should be populating the
hrefwithentity:protocols in the first place. Doing so means that the markup stored will include non-functionalhrefvalues that require the new text format filter (core/modules/filter/src/Plugin/Filter/EntityLinks.php) for them to be "fixed" so that they are functional. Consider what happens if a content editor switches existing markup from a text format that has enabled theentity_linksfilter to one that doesn't? A bunch of broken links.It would seem safer to populate a functional relative link (so, instead of
entity:/node/1, just/node/1), basically as a fallback. For rendering that does usecore/modules/filter/src/Plugin/Filter/EntityLinks.php, that code will update the href anyway from the metadata in the data attributes.Accomplishing this change would involve apparently trivial modifications as shown below. What I'm not sure about is whether there is some other important reason to use the
entity:protocol in thehref? Security?Diff of involved changes
Comment #294
acbramley commentedNice find @mark_fullmer! Yes that makes total sense and was one of the big BC callouts that was still outstanding. I can't see a good reason to keep the
entity:protocol and as you say it makes much more sense to fallback to working links if the filter isn't present, it also solves the BC issue.Comment #295
mark_fullmerOkay, based on discussion in 293-294, I've reworked the logic **not** to use the
entity:prefix in thehref. I also updated test expectations in this MR to match the new syntax. Those tests are passing, but I'm not clear why some low level Unit tests seem now to be failing?Comment #296
godotislateLooking at the previous build, it looks like the failures were on a composer integration test, so it could have been a temporary network issue. Seems like the latest build went fine, other than 3 functional javascript tests failing. Two of them seem directly related to the new linking functionality. The third one is a performance test, and that could be an intermittent failure that just needs a re-run.
Comment #297
acbramley commentedThis is green again, this MR seems extremely prone to random failures in all sorts of tests. I'm not sure if it's because we're over 430 commits or something else transient but just make sure to check the list of related jobs for passing reruns as they don't seem to display in the pipeline results list.
Comment #298
pere orgaThe label is escaped, but not the href, could this lead to XSS? I imagine it would be better to validate it via UrlHelper::isValid.
Also, note that the condition could be simpler, we are already inside a
if ($input)block, and we know$suggestionsis defined, soempty()is not necessary:...
Might be safer to check for null before calling
language()in the loaded entity.I may be missing something, but is there a reason why this is concatenated? Couldn't
Url::setOption()be used with\Drupal\Core\Url, rather than working with a string?.substr()is deprecated in JavaScript. You could use.substring()or.slice()instead.Comment #299
gcotillo commentedNeeded changes from MR!10036 for customers project but for Drupal 10.5.4. So I created a patch for D10.5.4. I post it just in case someone else needs it.
**Wrong patch but cant edit, see next comment
Comment #300
gcots commentedAdded a corrected patch for Drupal 10.5.4.
Apologies for the earlier mistake.
Comment #301
mark_fullmerAll suggestions from #298 incorporated in the latest commits. Thanks! I also added logic matching that of the CKEditor 5 API to handle an edge case that surfaced in Linkit #3555749: Data attributes of a new link are always applied to the FIRST link.
Comment #302
mark_fullmerFrom #298:
Interesting... The code change in https://git.drupalcode.org/project/drupal/-/commit/5368a80366f045fb26d03... appears to have made the link no longer cacheable, according to Drupal\Tests\filter\Kernel\EntityLinks . Is that the reason that the previous code was working with a string instead of URL, or am I just missing something about the code implementation?
Comment #303
mark_fullmerComment #304
acbramley commentedRe #302 this is the difference between using generated urls and a direct toString I believe, can we revert that commit for now?
Comment #305
acbramley commentedI've reverted it for now.
@pere orga for the future please add code review comments directly to the MR, much easier than copy pasting code into comments and easier to discuss. Thanks!
Comment #306
pameeela commentedGave this a manual test with the latest changes, looking good for the basics but I am not sure what edge cases also might benefit from testing.
Comment #307
mark_fullmerI've made an attempt at adding comprehensive acceptance criteria to the issue description, above. Of note, I identified four elements that are failing right now, so setting this back to "Needs work"
Comment #308
mark_fullmerHere are the 4 failing criteria as of 11/14/2025, with commentary on direction for resolution:
- [FAIL] When node titles matching the pattern are long (e.g. greater than 40 characters), the editing interface width expands to accommodate the content without expanding beyond the container. Commentary: this should be a relatively easy CSS fix. See work in #3550187: Linkit Dialog list overflows container (in Layout Builder)
- [FAIL] If the referenced node has a URL alias, that alias is rendered. Commentary: This also should be pretty straightforward to add/fix in the text format filter plugin
- [FAIL] When two separate lines of text exist the body text and one is selected by triple-clicking, the link interface can subsequently be used and a link inserted on the entire link (currently this is failing with console error Original error: TypeError: can't access property "attributes", s[a] is undefined). Commentary: this was recently surfaced in Linkit. See #3557993: [CKEditor v45+] Triple-clicking to select an item for linking triggers JS error.
- [FAIL?] When the text format includes the Drupal Media Library toolbar item and the "Embed Media" text format filter is active, a media entity can be inserted and, using its CKEditor5 balloon interface, can be hyperlinked using the same autocomplete interface. When rendered, the image is wrapped in a hyperlink to the referenced node. Commentary: this may be user error on my part; I seem to be unable to assign the Media Library toolbar plugin in conjunction with this plugin on a text format??
Comment #309
pameeela commentedI think all of those items could be handled as follow ups? None seem super critical and I think this is worth landing with a few known edge-case issues.
But I don't think I understand this one:
Is this not what happens in the screencast I added? Or if not what am I missing?
Comment #310
pameeela commentedI tested this and it doesn't work at all. Not sure about the config issue you mentioned @mark_fullmer as I was testing with Umami so it was already configured.
The media markup got mangled by the link, the image still rendered fine but it is not hyperlinked. This still feels like something to fix in a follow up though? The functionality is still quite limited and not on par with Linkit, so I think it's ok to have a few known issues. It will be so much easier to resolve them if we can do it in separate issues as the thread here is already so hard to follow!
Comment #311
lauriiiThank you @mark_fullmer for pushing this forward! I think the acceptance criteria and testing against those is a good idea. Looking at the failures, I think we should merge this to 11.x even thought this is not passing all of the acceptance criteria. Working on this issue with 300+ comments and commits is a really expensive way to address these issues. We should open follow-ups for the failures and solve them that way before 11.4.0. I think that's fine especially given that this is a completely new feature.
Comment #312
catchIt would be good to have issues open for everything in #308, but I agree they're likely to get fixed quicker in follow-up issues than trying to do so here, and none feel blocking especially if they're known or recently fixed issues in linkit. Note that for links around media embed tags, we also have #3075527: _filter_autop() breaks links around the <drupal-media> tag open.
Comment #313
acbramley commentedI'm surprised the media linking isn't working, I'm sure I tested this semi recently and we have test coverage for it. But I agree that we could accept these edge cases, I can create follow ups today.
Comment #314
acbramley commentedI just tested linking media again and it's working for me. I wonder if it's the order of filters that affects it? My list is ordered like so:
- Limit allowed HTML tags and correct faulty HTML
- Entity links
- Restrict images to this site
- Track images uploaded via a Text Editor
- Lazy load images
- Embed media
- Align images
- Caption images
EDIT: I also can't reproduce the triple clicking bug, triple clicking on a link in CKE5 does nothing for me (and no errors in the console).
I don't see using the alias as a bug, the href is overwritten anyway.
So the only follow-up I can currently see needed is the CSS issue with overflowing titles?
Comment #315
pameeela commentedThat's very weird, I tested in that order and it still didn't work but I'll try to reproduce it again from scratch and will create that follow up if needed.
Comment #316
lauriiiI did pretty extensive manual testing of the MR as well as a high level code review. @pameeela has been doing testing on this too. I checked the change records and they look good too.
Comment #317
pameeela commentedCreated #3558934: Fix styling of link autocomplete with long titles for the CSS issue and removed it from the IS.
Comment #318
charles belovWould it be possible to post the screen recording as a video rather than as a animated GIF? It goes by too fast for me to follow and I can't pause it or run it at half speed because it's an animated GIF.
Comment #319
charles belovI'm not having any luck applying the current patch to 11.3.x-dev on simplytest.me in order to test this. The build fails. Is there a different version of Drupal core that I need to be applying this to or a different patch version that I need to be applying?
(Edit: Resolved as of 11/20/2025)
Comment #320
pameeela commented@charles belov the MR is for 11.x, considering how big the changes are it’s not surprising if it doesn’t apply to 11.3.x (or possibly it’s too large so it’s failing, I’m not sure). Since it’s RTBC already, additional testing is a bonus but not critical so it will probably be best to wait until it’s merged.
Comment #321
catchOK I reviewed the PHP side of this a fair bit around #183 when we shifted from having an admin interface to define which entity bundles are linkable to using bundle info with no UI. The result of that is that the PHP is mainly the new link handlers and the filter. Some of the link handlers (like the media one) are added 'just in case' contrib adds support for them, which I'm not entirely sure about, but also deciding which ones should be in core just in case vs. not feels like it could be another 100 comments, and the amount of code is not much.
The other main change since around then on the PHP side is switching back from
entity:node/1, which was a change @Wim made in #52 to/node/1in what's stored by ckeditor5 plugin, and then eventually replaced by the filter.The reason @Wim made the change is because the unprocessed 'link' is never used, but subsequent discussion (see #293/294) found that:
- XSS filtering will remove it unless site-specific services.yml add in the entity: protocol.
- a site that enables this filter but then disables it again would be able to use the /node/1 links as-is but not entity:node/1 (not really a feature, but also doesn't seem bad).
- restores compatibility with sites that have already run the linkit module and have stored content in the same format, so that they don't need migration/update to use the core filter. This is a big reason for me not to change things.
These all seem like good reasons to switch back, and @Wim's original comment mentioned the possibility of switching back too if there were reasons to do so, which it turns out there are.
I can't meaningfully review the js here since it's over my head, but I know that lots of other people have.
Did my best with issue credit but that is non-trivial with 450 comments and dozens of contributors, I also got a 500 the first time I loaded the contribution record and saving and re-loading the form took about a minute each time. So there will definitely be mistakes/omissions.
There are bound to be follow-ups here, due to the number of comments, it would be great if people could open those issues and relate them back to this issue - if it's critical or major, then linking the other way from here is great, but comments without issues on here are likely to just get lost.
Comment #322
catchForgot to mention in #141 - Committed/pushed to 11.x and cherry-picked to 11.3.x, thanks!
Comment #325
catchComment #328
mgiffordGlad to see this Fixed. I do think that there might be some follow-up accessibility issues that need to be addressed still. That can happen in a new issue, but I do want to see that they get addressed.
Comment #329
smustgrave commentedCongrats on landing this! My only comment would be to have it written somewhere what this provides and doesn’t provide from linkit.
Comment #330
andypostFiled follow-up bugfix for PHP 8.5 compatibility #3559286: Fix EntityLinksTest for PHP 8.5
Comment #331
catch@mgifford the accessibility issues I'm aware of in this issue, such as in #3317769-162: Add support for linking to entities in CKEditor 5 were in the administrative UI for selecting which entities are linkable, which was entirely removed from the MR since - as in we completely removed that entire page from the MR and no equivalent exists in core at all. The only UI is the ckeditor plugin itself.
I'm not aware of any outstanding issues in what was committed but this is a very long issue so may have overlooked something - if you know of something specific in what actually went into core, would you be able to create a follow-up issue and link it from here?
Comment #332
catch@smustgrave I haven't reviewed it for accuracy, but there's a list on https://www.drupal.org/project/linkit already and that seems like a good place for it.
Comment #333
pameeela commentedIt's not currently anywhere near what Linkit provides, it's easier to list what it does rather than what is missing! I think from here it would good to figure out the plan for core from here since we don't plan to provide parity with Linkit but rather a simple solution out of the box.
Comment #334
pameeela commentedCreate #3559370: Define the requirements for link autocomplete in core so we can discuss further there and leave this poor, over-worked issue alone.
Comment #335
mark_fullmerI've created #3560141: Entity linking: Triple-clicking to select an item for linking triggers JS error to address a follow-up in #308
Comment #336
rkollerSorry for being late revisiting this issue, but i had zero capacities for contributions the last few weeks. I've created a few issues mike was referring to in #328.
#3561365: The link panel has a few issues in regard to a too low color contrast
#3561366: By using the voiceover cursor inside the link panel you are able to get outside of it
#3561368: Results for the link panel are not available in the aural interface
The points i've raised in #169 dont apply anymore cuz the entire resulting list became unavailable in the aural interface with the recent changes. I've set that last issue to major cuz the experience is completely broken and inaccessible for screenreader users. One thing to consider i am a bit drawn about at the moment is to maybe open another issue for adding the
aria-haspopup="true"attribute to the link button in the toolbar. that way it would be possible to communicate that by pressing the button you are opening a popup.