Skip to content

Commit 1ed1db7

Browse files
committed
[TwigComponent] Ignore "nested" for Alpine & Vue attributes
Have lost time on Twig & the website 😓
1 parent faaa385 commit 1ed1db7

File tree

4 files changed

+73
-1
lines changed

4 files changed

+73
-1
lines changed

src/TwigComponent/src/ComponentAttributes.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
final class ComponentAttributes implements \Stringable, \IteratorAggregate, \Countable
2323
{
2424
private const NESTED_REGEX = '#^([\w-]+):(.+)$#';
25+
private const ALPINE_REGEX = '#^x-([a-z]+):[^:]+$#';
26+
private const VUE_REGEX = '#^v-([a-z]+):[^:]+$#';
2527

2628
/** @var array<string,true> */
2729
private array $rendered = [];
@@ -41,7 +43,11 @@ public function __toString(): string
4143
fn (string $key) => !isset($this->rendered[$key])
4244
),
4345
function (string $carry, string $key) {
44-
if (preg_match(self::NESTED_REGEX, $key)) {
46+
if (
47+
preg_match(self::NESTED_REGEX, $key)
48+
&& !preg_match(self::ALPINE_REGEX, $key)
49+
&& !preg_match(self::VUE_REGEX, $key)
50+
) {
4551
return $carry;
4652
}
4753

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<div{{ attributes }}></div>

src/TwigComponent/tests/Integration/ComponentExtensionTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,58 @@ public function testRenderingComponentWithNestedAttributes(): void
316316
);
317317
}
318318

319+
/**
320+
* @dataProvider providePrefixedAttributesCases
321+
*/
322+
public function testRenderPrefixedAttributes(string $attributes, bool $expectContains): void
323+
{
324+
/** @var Environment $twig */
325+
$twig = self::getContainer()->get(Environment::class);
326+
$template = $twig->createTemplate(\sprintf('<twig:PrefixedAttributes %s/>', $attributes));
327+
328+
if ($expectContains) {
329+
self::assertStringContainsString($attributes, trim($template->render()));
330+
331+
return;
332+
}
333+
334+
self::assertStringNotContainsString($attributes, trim($template->render()));
335+
}
336+
337+
/**
338+
* @return iterable<array{0: string, 1: bool}>
339+
*/
340+
public static function providePrefixedAttributesCases(): iterable
341+
{
342+
// General
343+
yield ['x:men', false]; // Nested
344+
yield ['x:men="u"', false]; // Nested
345+
yield ['x-men', true];
346+
yield ['x-men="u"', true];
347+
348+
// AlpineJS
349+
yield ['x-click="count++"', true];
350+
yield ['x-on:click="count++"', true];
351+
yield ['@click="open"', true];
352+
// Not AlpineJS
353+
yield ['z-click="count++"', true];
354+
yield ['z-on:click="count++"', false]; // Nested
355+
356+
// Stencil
357+
yield ['onClick="count++"', true];
358+
yield ['@onClick="count++"', true];
359+
360+
// VueJs
361+
yield ['v-model="message"', true];
362+
yield ['v-bind:id="dynamicId"', true];
363+
yield ['v-bind:id', true];
364+
yield ['@submit.prevent="onSubmit"', true];
365+
// Not VueJs
366+
yield ['z-model="message"', true];
367+
yield ['z-bind:id="dynamicId"', false]; // Nested
368+
yield ['z-bind:id', false]; // Nested
369+
}
370+
319371
public function testRenderingHtmlSyntaxComponentWithNestedAttributes(): void
320372
{
321373
$output = self::getContainer()

src/TwigComponent/tests/Unit/ComponentAttributesTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,19 @@ public function testNestedAttributes(): void
258258
$this->assertSame(' class="baz"', (string) $attributes->nested('title')->nested('span'));
259259
$this->assertSame('', (string) $attributes->nested('invalid'));
260260
}
261+
262+
public function testPrefixedAttributes(): void
263+
{
264+
$attributes = new ComponentAttributes([
265+
'x-click' => 'x+',
266+
'title:x-click' => 'title:x+',
267+
]);
268+
269+
$this->assertSame(' x-click="x+"', (string) $attributes);
270+
$this->assertSame(' x-click="title:x+"', (string) $attributes->nested('title'));
271+
$this->assertSame('', (string) $attributes->nested('title')->nested('span'));
272+
$this->assertSame('', (string) $attributes->nested('invalid'));
273+
}
261274

262275
public function testConvertTrueAriaAttributeValue(): void
263276
{

0 commit comments

Comments
 (0)