Skip to content

[TwigComponent] Add 'require ** as **' to alias components #1209

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: 2.x
Choose a base branch
from

Conversation

maelanleborgne
Copy link
Contributor

Q A
Bug fix? no
New feature? yes
Tickets Fix #1108
License MIT

As suggested in #1108 and #801, this PR adds a new step in TwigPreLexer to replace components aliases by there full name.
This will be useful when reusing many times the same components in your template, especially when making extensive use of components : having a well organized component folder will lead to longer component names.

What do you think ?

TODO:

  • Handle the case when require declaration is commented
  • Handle the case when require declaration is in a verbatim block

@maelanleborgne maelanleborgne changed the title Add 'require ** as **' to alias components [TwigComponent] Add 'require ** as **' to alias components Oct 20, 2023
@norkunas
Copy link
Contributor

Sadly still have to prefix with <twig: 🥲

Copy link
Contributor

@WebMamba WebMamba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoooo thanks @maelanleborgne to get into this 🧡

@@ -167,7 +167,7 @@ public function preLexComponents(string $input): string
throw new SyntaxError(sprintf('Expected closing tag "</twig:%s>" not found.', $lastComponent), $this->line);
}

return $output;
return $this->processRequires($output);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about dispatching an event PostTwigPrelexing and putting the processRequires function's content in a Subscriber?

@WebMamba
Copy link
Contributor

@norkunas what do you propose then? I feel like people like this syntax

@norkunas
Copy link
Contributor

See my issue :)

Copy link
Contributor

@WebMamba WebMamba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maelanleborgne I was thinking again about your PR. And I don't think to use regex is not the good path here. You have to replicate some logic like verbatim or comment blocks... And if for exemple someone made a typo like so {% require Foo as Bar } we not gonna deliver a proper errors. I think we should do the logic from the TwigPrelexer directly. When the TwigPrelexer find {% require then he look for componentName and his alias, store this in property. Then when the TwigPrelexer is opening a component he looks via his property if an alias doesn't exist for this componentName. What you think ?

@norkunas
Copy link
Contributor

For me it's too much of the prefix when using many components..

@smnandre
Copy link
Member

I love the idea... but i'd like to solve our problems with the two lexers first if you're OK to wait a couple of days :|

We may stop resolving the component names at prelex time, so your implementation could be much easier ... or almost impossible depending on what we want to do :)

Currently with your implementation, i fear the following use case would break, no ?

{{ component(a_var) }}
{% verbatim %}
    {{ component('foo') }}
{% endverbatim %}
{% embed %}
    {% block 'inside' %}
        {{ component('foo') }}
    {% endblock %}
    {{ component('foo') }}
{% endembed %}

It seems to me that we would be safer with a NodeVisitor (like trans_domain for example)

@smnandre
Copy link
Member

Another complex case

{% require Foo:Bar as Bar %}
{% require Bar as Foo %}


<twig:Foo:Bar />
<twig:Foo />
<twig:Bar />

@smnandre
Copy link
Member

smnandre commented Oct 21, 2023

Another case

{#  templates/_blocks.html.twig  #}

{% block sidebar_top %}
    <twig:Crocodile:BigCroco />
{% endblock %}

{% block sidebar_bottom %}
    <twig:Crocodile:LittleCroco />
{% endblock %}
{#  templates/homepage.html.twig  #}

{% require Fake:Crocodile as Crocodile %}
{% require Plastic:BigCroco as Crocodile:BigCroco %}

{% use '_blocks.html.twig' %}

<twig:Crocodile:LittleCroco />

{% bloc sidebar_top %}
    <twig:Crocodile:BigCroco />
    {{ parent() }}
{% endblock %}

{% bloc sidebar_bottom %}
    <twig:Crocodile:LittleCroco />
{% endblock %}

(side note: this one is another reminder we should not pre-resolve names before the render @weaverryan ... anything done before the render is a risk some Twig feature stop working)

@jungleman12
Copy link

Nice feature! I hope it will be merged soon!
It will help me a lot in the structure of my components :).

@tibobaldwin
Copy link

Ah yes, this kind of functionality is interesting for organizing components in files.
For example, this will save me from making a <twig:Sidebar:Sidebar>.

@Kocal
Copy link
Member

Kocal commented Feb 16, 2025

Ah yes, this kind of functionality is interesting for organizing components in files. For example, this will save me from making a <twig:Sidebar:Sidebar>.

You can create a templates/components/Sidebar.html.twig file for that

@tibobaldwin
Copy link

The idea is to structure the Sidebar component like this:

  • templates/components/Sidebar/Sidebar.html.twig
  • templates/components/Sidebar/SidebarHeader.html.twig
  • templates/components/Sidebar/SidebarBody.html.twig
  • templates/components/Sidebar/SidebarItem.html.twig
  • templates/components/Sidebar/SidebarLabel.html.twig
  • ...

@Kocal
Copy link
Member

Kocal commented Feb 16, 2025

Why not the following structure?

  • templates/components/Sidebar.html.twig
  • templates/components/Sidebar/Header.html.twig
  • templates/components/Sidebar/Body.html.twig
  • templates/components/Sidebar/Item.html.twig
  • templates/components/Sidebar/Label.html.twig

It would allow you to use components like this:

<twig:Sidebar>
    <twig:Sidebar:Header></twig:Sidebar:Header>
    <twig:Sidebar:Body></twig:Sidebar:Body>
    <twig:Sidebar:Item></twig:Sidebar:Item>
    <twig:Sidebar:Label></twig:Sidebar:Label>
</twig:Sidebar>

@tibobaldwin
Copy link

I understand your logic and that works :). The idea I propose is to group the related components within a single directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Import Anonymous or TwigComponent with custom name
7 participants