diff --git a/src/TwigComponent/CHANGELOG.md b/src/TwigComponent/CHANGELOG.md index 5813bd612e5..01b08a3f37b 100644 --- a/src/TwigComponent/CHANGELOG.md +++ b/src/TwigComponent/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 2.11.0 + +- Support ...spread operator with html syntax + ## 2.9.0 - The `ComponentAttributes::defaults()` method now accepts any iterable argument. diff --git a/src/TwigComponent/src/Twig/TwigPreLexer.php b/src/TwigComponent/src/Twig/TwigPreLexer.php index 1022a38a5bc..1def6b708aa 100644 --- a/src/TwigComponent/src/Twig/TwigPreLexer.php +++ b/src/TwigComponent/src/Twig/TwigPreLexer.php @@ -22,7 +22,9 @@ class TwigPreLexer private int $length; private int $position = 0; private int $line; - /** @var array */ + /** + * @var array + */ private array $currentComponents = []; public function __construct(int $startingLine = 1) @@ -201,6 +203,15 @@ private function consumeAttributes(string $componentName): string break; } + if ($this->check('{{...') || $this->check('{{ ...')) { + $this->consume('{{...'); + $this->consume('{{ ...'); + $attributes[] = '...'.trim($this->consumeUntil('}}')); + $this->consume('}}'); + + continue; + } + $isAttributeDynamic = false; // :someProp="dynamicVar" diff --git a/src/TwigComponent/tests/Unit/TwigPreLexerTest.php b/src/TwigComponent/tests/Unit/TwigPreLexerTest.php index 37362ac9478..a100f09e45c 100644 --- a/src/TwigComponent/tests/Unit/TwigPreLexerTest.php +++ b/src/TwigComponent/tests/Unit/TwigPreLexerTest.php @@ -216,5 +216,31 @@ public function getLexTests(): iterable '{% verbatim %}{% endverbatim %}', '{% verbatim %}{% endverbatim %}', ]; + + yield 'component_attr_spreading_self_closing' => [ + '', + '{{ component(\'foobar\', { bar: \'baz\', ...attr }) }}', + ]; + yield 'component_attr_spreading_self_closing2' => [ + '', + '{{ component(\'foobar\', { bar: \'baz\', ...customAttrs }) }}', + ]; + yield 'component_attr_spreading_self_closing3' => [ + '', + '{{ component(\'foobar\', { bar: \'baz\', ...attr }) }}', + ]; + + yield 'component_attr_spreading_with_content1' => [ + 'content', + '{% component \'foobar\' with { bar: \'baz\', ...attr } %}{% block content %}content{% endblock %}{% endcomponent %}', + ]; + yield 'component_attr_spreading_with_content2' => [ + 'content', + '{% component \'foobar\' with { bar: \'baz\', ...customAttrs } %}{% block content %}content{% endblock %}{% endcomponent %}', + ]; + yield 'component_attr_spreading_with_content3' => [ + 'content', + '{% component \'foobar\' with { bar: \'baz\', ...attr } %}{% block content %}content{% endblock %}{% endcomponent %}', + ]; } }