Skip to content
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

[TwigComponent] escape nesting separator with :: #1959

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/TwigComponent/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## 2.19.0

- Allow escape nesting separator with `::` #1959

## 2.17.0

- Add nested attribute support #1405
Expand Down
17 changes: 13 additions & 4 deletions src/TwigComponent/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -486,12 +486,12 @@ component use a ``PreMount`` hook::
In its default configuration, the OptionsResolver treats all props.
However, if more props are passed than the options defined in the OptionsResolver, an error will be prompted, indicating that one or more options do not exist.
To avoid this, use the `ignoreUndefined()` method with `true`. See `ignore not defined options`_ for more info.

$resolver->setIgnoreUndefined(true);
The major drawback of this configuration is that the OptionsResolver will remove every non-defined option when resolving data.

The major drawback of this configuration is that the OptionsResolver will remove every non-defined option when resolving data.
To maintain props that have not been defined within the OptionsResolver, combine the data from the hook with the resolved data.

return $resolver->resolve($data) + $data;


Expand Down Expand Up @@ -1127,6 +1127,15 @@ The nesting is recursive so you could potentially do something like this:
row:widget:class="ui-form-widget"
/>

.. note::

If you require an attribute that actually includes a ``:`` (like ``x-on:click``),
you can escape the nested attribute separator by using a double colon (``x-on::click``).

.. versionadded:: 2.19

The ability to escape the nested attribute separator was added in TwigComponents 2.19.

Component with Complex Variants (CVA)
-------------------------------------

Expand Down
4 changes: 3 additions & 1 deletion src/TwigComponent/src/ComponentAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/
final class ComponentAttributes implements \Stringable, \IteratorAggregate, \Countable
{
private const NESTED_REGEX = '#^([\w-]+):(.+)$#';
private const NESTED_REGEX = '#^([\w-]+):(?!:)(.+)$#';

/** @var array<string,true> */
private array $rendered = [];
Expand Down Expand Up @@ -64,6 +64,8 @@ function (string $carry, string $key) {
$value = 'true';
}

$key = str_replace('::', ':', $key);
Copy link
Member

Choose a reason for hiding this comment

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

In a regex to enforce it's only for nested attributes ? (so after a word / before another one) ?


return match ($value) {
true => "{$carry} {$key}",
false => $carry,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,12 +331,12 @@ public function testRenderingHtmlSyntaxComponentWithNestedAttributes(): void

$output = self::getContainer()
->get(Environment::class)
->createTemplate('<twig:NestedAttributes class="foo" title:class="bar" title:span:class="baz" inner:class="foo" />')
->createTemplate('<twig:NestedAttributes class="foo" title:class="bar" title:span:class="baz" inner:class="foo" x-on::click="!open" />')
->render()
;

$this->assertSame(<<<HTML
<main class="foo">
<main class="foo" x-on:click="!open">
<div class="bar">
<span class="baz">
<div class="foo"/>
Expand Down
11 changes: 9 additions & 2 deletions src/TwigComponent/tests/Unit/ComponentAttributesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,21 @@ public function testNestedAttributes(): void
{
$attributes = new ComponentAttributes([
'class' => 'foo',
'data-class' => 'qux',
'title:class' => 'bar',
'title:x-on::click' => '!close',
'title:span:class' => 'baz',
'data-title:class' => 'flo',
'data-title:data-class' => 'shi',
'x-on::click' => '!open',
]);

$this->assertSame(' class="foo"', (string) $attributes);
$this->assertSame(' class="bar"', (string) $attributes->nested('title'));
$this->assertSame(' class="foo" data-class="qux" x-on:click="!open"', (string) $attributes);
$this->assertSame(' class="bar" x-on:click="!close"', (string) $attributes->nested('title'));
$this->assertSame(' class="baz"', (string) $attributes->nested('title')->nested('span'));
$this->assertSame('', (string) $attributes->nested('invalid'));
$this->assertSame('', (string) $attributes->nested('x-on'));
$this->assertSame(' class="flo" data-class="shi"', (string) $attributes->nested('data-title'));
}

public function testConvertTrueAriaAttributeValue(): void
Expand Down