Twig link function is tricky to use

Created on 8 March 2024, 11 months ago
Updated 13 March 2024, 11 months ago

Problem/Motivation

When working in a twig template, using link() can have some odd behaviors that can be confusing to developers.

Discussion:
https://drupal.slack.com/archives/C1BMUQ9U6/p1709912605839939

Steps to reproduce

All of these fairly reasonable uses of link will throw and InvalidArgumentException("The URI '$uri' is invalid. You must use a valid URI scheme.")


{{ link('text', '#anchor') }}
{{ link('text', '', {fragment: '#anchor') }}
{{ link('Home', '/') }}

These are simplified use cases and a developer running into this in isolation can just write the HTML and work around it but this can be frustrating and complicated when interacting with generalized templates or templates from core that use the link function.

Proposed resolution

The suggestion in slack was to leverage fromUserInput to work around cases where a link is being built with user input.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Feature request
Status

Needs work

Version

11.0 🔥

Component
Theme 

Last updated about 10 hours ago

Created by

🇺🇸United States neclimdul Houston, TX

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @neclimdul
  • 🇺🇸United States neclimdul Houston, TX

    As a workaround, you _can_ use the internal: prefix. For example link('text', 'internal:#anchor'). We should still address this though because this wouldn't be obvious to your average developer. Or experienced developer since I needed to have catch point it out and I think he had to dig through Url.php to find it 🤣

  • Pipeline finished with Success
    11 months ago
    Total: 524s
    #117604
  • 🇺🇸United States neclimdul Houston, TX

    Realized my concerns about optimizing this for existing conditions is probably not a big deal. Core is passing urls and that's probably the common use case. fromUserInput is probably the expected behavior the rest of the time.

    That said, we can avoid cloning is we just created the object so I've included that in the merge.

    Needs tests but the existing twig extension test needs a lot of scaffolding for each test so I will come back to it.

  • Status changed to Needs review 11 months ago
  • 🇺🇸United States neclimdul Houston, TX

    Needs test but approach could use some review.

  • Status changed to Needs work 11 months ago
  • 🇺🇸United States smustgrave

    The problem makes sense.

    Was hoping we had a method that could check for userInput before calling it. To get around the try/catch block but didn't find anything.

    Think it's probably a good enough approach to add a few test cases for.

    Could you post the link to the slack thread in case others want to chime in there too.

    Thanks!

  • 🇺🇸United States neclimdul Houston, TX

    Yeah, using try/catch as a conditional doesn't feel great. I considered moving the regex to a constant we could use but that felt weird to so open to suggestions.

    https://drupal.slack.com/archives/C1BMUQ9U6/p1709912605839939

Production build 0.71.5 2024