Needs review
Project:
Linkit
Version:
7.x-dev
Component:
Code
Priority:
Normal
Category:
Feature request
Assigned:
Issue tags:
Reporter:
Created:
11 May 2017 at 03:49 UTC
Updated:
13 Nov 2025 at 22:55 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
singularoAttching patch to call the alias manager not just return the path.
Comment #3
tsymi commentedThanks, patch on #2 works for me and met to my need.
Comment #4
singularoHmm it looks like there is a tiny change required for sites running on a non '/' base path.
Comment #5
singularoComment #6
anonThanks for patch, we need a test for this tho.
Comment #7
thierry.beeckmans commentedUpdated patch for the 8.x-5.0-beta7 version.
Comment #8
simeShouldn't this be done in a text output filter?
Comment #9
simeOn that note, I think this needs to be an optional configuration if this gets applied. We don't want to all our content links breaking when aliases are updated.
Comment #10
dalemoore commentedI just ran into this issue setting up my first D8 site. I was expecting this module to work similarly to CKEditor Link with D7, where it uses the node/id link but outputs the alias for the end-user, so that when aliases change (renaming a title, for instance) the path gets updated. Instead, all URLs break if the alias is updated...
EDIT: Scratch this, I updated to the 5.x-beta10 version, and it works now like I thought it should. I see now that you all were working to fix this on that branch.
Comment #11
marco-sI have updated from 4.3.0 to 5.0.0-beta10 and I was wondering why the links are shown as /node/x afterwards (that wasn't the case with 4.x). I found the filter 'Linkit URL converter' in the text formats settings, but this filter doesn't seem to work?! Patch #7 works for me for my current case. I also don't need the 'Linkit URL converter' filter with this patch. But I agree with slime that this variant doesn't recognize alias updates and you should use the patch deliberately.
Comment #12
pfrenssenPatch didn't apply any more, rebased on 8.x-5.x.
Comment #13
moshe weitzman commentedPatch works for me. FWIW, the link already has durable reference to the linked entity (uuid) so perhaps its OK for this href to be a bit brittle? An example [a] tag when using this patch is
<a data-entity-substitution="canonical" data-entity-type="node" data-entity-uuid="66950305-f906-4f76-90e4-143a0eddc67e" href="/news/bulletin-2020-05-flexibility-in-the-issuance-and-administration-of-insurance-during-covid-19">dfdfdf</a>Comment #14
marco-spath.alias_managerin #12 needs to be changed topath_alias.managerfor D9 compatibility. This patch will now require Drupal >=8.8. (see https://www.drupal.org/node/3092086)Comment #15
marco-sThe patch #14 does not provide the url with a language prefix (because of 2772643).
I updated this patch for that case accordingly.
Comment #16
marco-sThe patch #15 does not consider a possible path prefix configuration. Updated it in this patch.
Comment #17
ciss commentedComment #19
lukusI'm not sure I agree that this is a desirable feature.
- The `href`- will be replaced by the text input filter, once the text is filtered for display.
- The alias is subject to change.
- The system path is actually a true representation of the intended destination.
Comment #20
simeonkesmev commentedHello, I am having this feature requested as well, but I also disagree with the implementation as it introduces dependencies, tries to implement URL building by itself by requesting the path alias manager and breaks the logic by replacing the internal path with an alias which is not stable reference to the target. Here's my take on it where I'm modifying only the representation to the editors and not he saved input.
Comment #22
simeonkesmev commentedCorrections here.
Comment #23
kbrodej commentedPatch from #16 worked for me. However did spot a few issues. Attached a patch with changes and interdiff from #16
If the language detection is domain based the path alias will still use language prefix:
- Added a explicit check if language negotiation source is
path_prefixif path alias does not exist for given language it will use
/{entity_type}/{id}:- Added a method to check the alias for current language and fallback to default langugage.
Comment #24
simeonkesmev commentedHere's an updated patch with my approach which handles base_paths.
NOTE: It's a different approach from the patch in #23, summary in #20.
Comment #25
askibinski commented@SimeonKesmev I agree with your approach since we already have input format
LinkitFilterwhich will transform the internalnode/#url for visitors of the content to the alias.Remaining issue:
With patch#24 you will see the alias in the autocomplete, but after inserting in the editor the link label/text still is
node/#(unless you select text before inserting the link).I think if no text is selected in the editor the default text to insert should be the node title.
Comment #26
dbielke1986 commentedIs there a chance to port this patch to version 6.*?
Because Iam facing the same issue:
If you type in "
/node/<nid>"and you do not select the search result - it will input<a href="/node/nid"....and not the<a data-entity-substitution="canonical" data-entity-type="node" data-entity-uuid="<uuid>" href="/node/<nid>"...which is a big issue. Not everyone is clicking at the search result, which leads to an issue on multilanguage sites.Comment #27
dbielke1986 commentedI created a new issue for version 6.*
https://www.drupal.org/project/linkit/issues/3222939
Comment #28
mark_fullmerI agree with the approach stated in #20. The approach here should be **not** to overwrite the internal path with the URL alias, since the latter could change. The patch in #24 , which is the latest version of that implementation, works well but does not include logic for adjusting the autocomplete logic to properly query the internal url in parentheses. In other words, it successfully populates the input area, but upon triggering a subsequent autocomplete search by clicking the input area, the autocomplete query fails because it's trying to match
[alias] ([internal-url]), rather than[internal-url].The attached patch accounts for that, and is otherwise identical to #24.
(I'm not quite clear what #25 is referring to, so I didn't address that.)
Comment #29
tvalimaa commented#28 fix my issue so node/xxx links are working now as aliases
Comment #30
pixelwhip commentedHere's a re-roll of #28. That patch had some extra changes related to the license file that did not look intentional and were not represented in the interdiff.
After fixing that, I was able to apply this patch via composer to 6.0.0-beta3.
Comment #31
sutharsan commentedJust checking, is this variable name
$patch_matchintended or was it supposed to be$path_match.Comment #32
spadxiii commentedI tried the patch in #30 and it seems to work, except that the wrong value is saved to the database. The alias (as internal url) is saved instead of the internal path. When selecting a node path, the form field shows "/alias-to-node" and the database contains "internal:/alias-to-node" instead of "entity:node/".
Here's a different patch that uses the #30 as starting point, but makes sure the correct value is saved to the database.
Comment #33
spadxiii commentedI seem to have uploaded a patch that doesn't apply. Here's a fresh one.
Comment #35
spadxiii commentedAnd I seem to have copied the deprecated service name :(
Fixed in new patch.
Comment #37
akhouryThis patch adds a configurable option to use alias instead of internal path navigate to
/admin/config/content/linkit/manage/{linkit_profile}/matchers/{plugin_instance_id}and check "use alias" checkboxThe autocomplete value and href attribute will contain the alias.
Comment #38
rossidrup commentedwhy dont you hardcode it into latest release?
Comment #39
pghaemim commentedmaking the #12 D9 compatible.
Comment #40
seanbLinking duplicate issues.
Comment #41
leon kessler commentedLots going on this issue. Three separate patches in #35, #37 and #39. Very confusing.
I'm hiding patch #39 and #37, as they go against the agreed approach of storing the internal (node/id) url in the unprocessed text.
I tested patch from #35, all looks good. Except you still see the internal node/id url immediately after selecting the link. After closing the dialog and re-opening to edit, you then see the url alias. This seems a bit broken to me, the value should be consistent so the behaviour is predictable to the user.
After having a look into the patch, I realised that the added code in
Drupal\linkit\Element::valueCallbackmeans that the internal url will always be used when submitting the form. This means it's safe to use always use the alias on the suggestions.Patch attached updates the matches to always use the alias.
Also, I've wrapped the use of
\Drupal::service('path_alias.manager')in a check for the installation of thepath_aliasmodule. As otherwise we would need to add a hard dependency to this module. Also this should hopefully make the tests pass.Comment #43
GasparM commentedHad the issue on linkit 6.0.x-dev, patch #41 works for me. I'm on PHP 8.1, drupal core 9.5.1
Comment #44
mark_fullmerNote: Linkit 6.0.0-beta4 was released on 5 March 2023. The patch from #41 still applies to the latest changes.
However, this only works with CKEditor 4 currently. CKEditor 5 support would need to be added.
Comment #45
mark_fullmerI take it back! This *does* work with CKEditor 5 as-is (I was expecting a different display output, but the aliased path is what is displayed in the CKEditor 5 context, which makes sense based on what the change is targeting).
This should still be "Needs work" since the failing tests need to be addressed. Also, I think it makes more sense to classify this as a "Feature" rather than a "Task."
Comment #48
jds1Rerolled #41 against 6.0.x https://git.drupalcode.org/project/linkit/-/merge_requests/16. Everything passes. Patch applies cleanly locally against both 6.0.x-dev and 6.0.0-beta4. Tested locally and now I'm getting aliases instead of node URLs! Marking as "Needs Review" – thank you!
Comment #50
damienmckennaThe merge request in patch format.
Comment #51
lxpcfly commentedThe linkit-n2877535-50.patch is successfully changed the URL Link field from "node/xxx" to URL Alias, but it still needs to do extra work, as the saved URL is still "node/xxx" rather than saved as its path alias, 'canonical' is not active.
eg:
1. put node/xxx into the link field and click save straight away without selecting the autocomplete result, it only saves node/xxx .
2. edit link, you can see the node/xxx has changed to its path alias, save as is, it is not changing the url, the url link on the mouse hover is still node/xxx.
Comment #52
damienmckennaIt's ok that the saved value is "node/xxx" because it's converted to the correct URL when the content is rendered; it's a feature.
Comment #53
lxpcfly commentedThank you Damien, but I think once it has the path alias also it appears in the Link field, it should save as path alias with canonical active.
Comment #54
damienmckennaThat would need to be a separate discussion.
Comment #55
vladt commentedI'm encountering an issue after applying patch #50 to Linkit 6.0.0-rc1 (as well as Linkit 5.0-beta 13), the data-entity-substitution, data-entity-type, data-entity-uuid attributes are no longer being added to the link, so the LinkitFilter is no longer working.
This seems to be happening because
$href !== $href_dirty_checkon line 129 of linkit.module is unsetting the values.Comment #56
moshe weitzman commentedSounds like this is right status.
Comment #57
moshe weitzman commentedIn my instance, that check is preventing the values from being unset, not unsetting them. Changing status after my review.
Comment #58
mark_fullmerComment #59
r_h-l commentedTesting this in 9.5, #50 breaks the a tag extra attributes. The tag gets put in as just the bare '/node/x' without any data attributes.
Comment #60
mark_fullmerAddressing the comments in #51, #53, and #59, all of which are suggesting that the URL alias is what should be saved to the database, rather than the internal route, I agree with Damien McKenna's statement in #52:
Comment #61
mark_fullmerAfter testing to confirm, I take back my comment. Using the latest patch, the comments in #51, #52, and #59 are effectively pointing out a problem -- not that the internal URL is what is saved (that's fine), but that when the resulting page is rendering, the internal URL is what is rendered to the end-user, rather than the URL alias.
Changing status to "Needs work" to address this. I'm also surprised that there is apparently no test coverage to catch this. I'd like to add test coverage for this going forward: the URL alias should be rendered on the page after save.
Comment #62
moshe weitzman commentedThis patch no longer applies to the most recent release (Sep 30) :(
Comment #63
mark_fullmerHere's a revised patch that replicates verbatim what was in the patch in #50, and which will apply to the current development release for 6.0.x and 6.1.x.
Noting that the comments from #51, #52, and #59 still need to be addressed: when the resulting page is rendered, the internal URL should not be rendered to the end-user. The URL alias should. Test coverage needs to be added for this, too. Leaving status as "Needs work."
Comment #64
arthur.baghdasar commentedIve removed this part from the patch everything seems to be working fine for me.
In the code below $input variable comes with an Alias and I don't understand why we should get the $path from it.
In My case the $path variable is converted back to the node/[nid] which is then being set to be the new input.
Comment #65
damienmckennaComment #66
kthullPatch from #64 applied to 6.1.2 for me and solved the generic node path on D10.1.5
Comment #67
greenskin commentedThe LinkitFilter doesn't look to work with the patch. I'm not seeing the additional attributes getting added to the tag.
Comment #68
spadxiii commentedI tried to get something working, but did not succeed.
My goal was to use the alias during editing and store the node-url in the database. The link would then show the node alias in the editor, but in the database the node/ was stored. By adding another data-property (data-entity-path) I tried adding a editorDowncast and dataDowncast in the plugin, but that didn't work correctly: it would create a new a-tag wrapping the one that was being made by the base link plugin.
By adding a general upcast conversion, the href is changed to the alias:
But I failed trying to move the other way around. I tried adding a dataDowncast (which would set the path back to the href), and an editorDowncast (which would use the alias as href). This didn't work, because when creating an element with the same attribute, would add another element to the html instead of merging them (effectively overwriting the href-attribute)
I also tried using a data downcastDispatcher, but that doesn't seem to be able to get the correct viewElement (or rather, it couldn't find any element at all).
ps. there are some other code changes required as well to not only pass but also use the alias and path in the links.
Comment #69
mrweiner commentedFor anybody who needs a quick and dirty fix for this, I'm handling it in hook_preprocess_field() with:
Note that this was generated by chatgpt, so I'm not sure that all of the args in $dom->loadHTML() are needed, but it seems to do the trick for me.
Comment #70
mark_fullmerComment #71
klidifia commentedI updated this issue with some code that will use the entity title (already obtained via Linkit) as the default link text for a brand new inserted link without a selection range: #3388565: Populate displayedText with entity title when left blank
Comment #72
federiko_ commentedPatch from #64 applied to 7.0.0-alpha1 seems to be working well for me ; here is the generated link markup :
<a class="test-css" href="/fr/mentions-legales" target="_blank" aria-label="test-aria" id="test-idd" rel="test-rel" data-entity-type="node" data-entity-uuid="7a012594-8e2f-446f-8559-ac377b1ec0d5" data-entity-substitution="canonical" tabindex="-1" data-title="Test title">Test link</a>Comment #76
casey commentedSorry for the noise;
First I rebased the existing MR branch on the latest 6.1.x branch but apparently you can't change the destination of MRs. I then reverted that existing MR.
I then applied the patch from #64 to both the 6.1.x and the 7.x branch; apparently the 6.1.x branch has more (recent) changes than the 7.x branch. I've created MRs for both branches.
Comment #77
casey commentedSnapshots of latest state of MRs for both 6.1.x and 7.x for safe usage with composer-patches
Comment #78
drpldrp commenteddelete
Comment #79
drpldrp commenteddelete
Comment #80
drpldrp commenteddelete
Comment #81
drpldrp commentedLoading alias info into global drupalSettings allows it to be available to the ckeditor5 linkit plugin on init so the alias can be upcast into the model. Storing in drupalSettings also allows it to be available to all text formats and persistent between switching text formats.
My version does entity lookup by the link href instead of uuid and entity type because I do not use the linkit url conversion filter. It is not currently compatible with linking images.
If you need to do entity lookup by the existing uuid/entity type method, alter
linkit_field_widget_single_element_form_alter()so it does the entity load similar to how it's done insrc/Plugin/Filter/LinkitFilter.php.Comment #82
kasey_mk commentedI think this no longer applies on 7.0.5. The patch from #77 applies, but appears to be causing the error reported on Can't Insert or Update Link after Upgrading to Drupal Core 10.5
Comment #83
kasey_mk commentedAh! My patented "wait a while and see if things 'magically solve themselves'" technique seems to have worked!
Thanks to all the wizards out there!
Comment #84
vah67007@gmail.com commentedPatch #64 worked fine for me. Running 10.5.x version of core.
Comment #85
dcasanovaI tested the last patches, but it didn't work for Drupal 10.5.x and Linkit 7.0.8. If anyone has any idea how to solve this, I would greatly appreciate it.
Comment #86
mark_fullmerWeighing in as a maintainer of the Linkit module, I would point out that there are others in the community who want the entity title to show: #2966320: Show entity title after autocomplete selection instead of internal route (e.g., /node/123). This, plus the fact that it is possible to configure the Linkit metadata to render the entity title in the matcher information, makes me disinclined to plan to include this in a release of Linkit. Community members are free to use the patch here, of course, but I'd really recommend going the route of adjusting the autocomplete metadata in the Linkit settings.
Comment #89
realityloop commentedMR 138: for 7.x Continue to use internal route so links don’t get broken, but display url alias in linkit widget and CKeditor when present.
Comment #90
realityloop commentedmoved to new comment
Comment #91
realityloop commentedComment #92
realityloop commentedComment #93
realityloop commentedComment #94
realityloop commentedApologies for the commit noise.. Now that all tests are passing for my MR138....
Drupal Link Handling Changes
1. Main Change: Internal Routes for Storage, Aliases for Display
/my-page), which could break if the alias changed (e.g., to/updated-page).entity:node/1), but the UI shows the current alias (e.g.,/my-page). This prevents broken links.#section ?query=1) are preserved in storage and display, but the changes ensure they're appended to the alias in the UI when present.2. Examples of Creating Links
Internal Link (e.g., to a Node):
/my-pagein the link field. Stored asinternal:/my-page. If alias changes to/new-page, link breaks./my-pageor selects from autocomplete. Stored asentity:node/1(internal route). Displayed as/my-page(alias). If alias changes, link still works./my-page#sectionin the link field. Stored asinternal:/my-page#section. If alias changes to/new-page, link breaks./my-page#sectionor selects from autocomplete. Stored asentity:node/1#section(internal route). Displayed as/my-page#section(alias with fragment). If alias changes, link still works.External Link (e.g., to Another Site):
https://example.com. Stored ashttps://example.com. No change in behavior.https://example.com. The change doesn't affect external links.https://example.com#anchor. Stored ashttps://example.com#anchor.https://example.com#anchor.Relative Link (e.g., to a Custom Path):
/custom/path. Stored asinternal:/custom/path. Works as a relative link.internal:/custom/path. If it matches an alias, it might convert to an entity link; otherwise, stays relative./custom/path#part. Stored asinternal:/custom/path#part.internal:/custom/path#part. If it matches an alias, it will convert to an entity link; otherwise, stays relative.3. Examples of Editing Links
Internal Link:
internal:/my-page. User edits to/updated-page. Stored asinternal:/updated-page. If/my-pagewas an alias, editing might not update the entity reference.entity:node/1. User sees/my-pagein the field. If they edit to/updated-page(new alias for the same node), it resolves back toentity:node/1. If edited to a non-entity path, it becomesinternal:/updated-page.internal:/my-page#section. User edits to/updated-page#newsection. Stored asinternal:/updated-page#newsection.entity:node/1#section. User sees/my-page#sectionin the field. If they edit to/updated-page#newsection, it resolves back toentity:node/1#newsection. If edited to a non-entity path, it becomesinternal:/updated-page#newsection.External Link:
https://example.com. User edits tohttps://newexample.com. Stored ashttps://newexample.com.https://example.com#anchor. User edits tohttps://newexample.com#newanchor. Stored ashttps://newexample.com#newanchor.Relative Link:
internal:/custom/path. User edits to/new/path. Stored asinternal:/new/path.entity:...; otherwise, stays relative.internal:/custom/path#part. User edits to/new/path#newpart. Stored asinternal:/new/path#newpart.entity:...#newpart; otherwise, stays relative with the fragment.4. Other Changes in the Commit
path_processing: falsefor internal routes,truefor aliases), with fragment handling.5. Overall Impact
Some screengrabs:
Comment #95
mark_fullmerAssigning to myself for review!
Comment #96
mark_fullmerThe attached patch is a re-roll of the approach taken in #62/#64 -- i.e., a narrower implementation -- that applies cleanly to Linkit 7.0.9, 7.0.10, and 7.0.11 (latest release), in case anyone was using that and still needs it.