Skip to content

Commit

Permalink
[TwigComponent] Fix TwigPreLexer edge case
Browse files Browse the repository at this point in the history
  • Loading branch information
smnandre authored and weaverryan committed Dec 12, 2023
1 parent 7989f27 commit 5c0a30f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
20 changes: 12 additions & 8 deletions src/TwigComponent/src/Twig/TwigPreLexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,6 @@ private function consumeAttributes(string $componentName): string
*/
private function consume(string $string): bool
{
if ($string[0] !== $this->input[$this->position]) {
return false;
}

$stringLength = \strlen($string);
if (substr($this->input, $this->position, $stringLength) === $string) {
$this->position += $stringLength;
Expand Down Expand Up @@ -405,16 +401,24 @@ private function consumeUntilEndBlock(): string
$start = $this->position;

$depth = 1;
$inComment = false;
while ($this->position < $this->length) {
if ('</twig:block' === substr($this->input, $this->position, 12)) {
if ($inComment && '#}' === substr($this->input, $this->position, 2)) {
$inComment = false;
}
if (!$inComment && '{#' === substr($this->input, $this->position, 2)) {
$inComment = true;
}

if (!$inComment && '</twig:block>' === substr($this->input, $this->position, 13)) {
if (1 === $depth) {
break;
} else {
--$depth;
}
}

if ('{% endblock %}' === substr($this->input, $this->position, 14)) {
if (!$inComment && '{% endblock %}' === substr($this->input, $this->position, 14)) {
if (1 === $depth) {
// in this case, we want to advanced ALL the way beyond the endblock
$this->position += 14;
Expand All @@ -424,11 +428,11 @@ private function consumeUntilEndBlock(): string
}
}

if ('<twig:block' === substr($this->input, $this->position, 11)) {
if (!$inComment && '<twig:block' === substr($this->input, $this->position, 11)) {
++$depth;
}

if ('{% block' === substr($this->input, $this->position, 8)) {
if (!$inComment && '{% block' === substr($this->input, $this->position, 8)) {
++$depth;
}

Expand Down
26 changes: 26 additions & 0 deletions src/TwigComponent/tests/Unit/TwigPreLexerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use PHPUnit\Framework\TestCase;
use Symfony\UX\TwigComponent\Twig\TwigPreLexer;
use Twig\Error\SyntaxError;

final class TwigPreLexerTest extends TestCase
{
Expand All @@ -25,6 +26,26 @@ public function testPreLex(string $input, string $expectedOutput): void
$this->assertSame($expectedOutput, $lexer->preLexComponents($input));
}

/**
* @dataProvider getInvalidSyntaxTests
*/
public function testPreLexThrowsExceptionOnInvalidSyntax(string $input, string $expectedMessage): void
{
$this->expectException(SyntaxError::class);
$this->expectExceptionMessage($expectedMessage);

$lexer = new TwigPreLexer();
$lexer->preLexComponents($input);
}

public static function getInvalidSyntaxTests(): iterable
{
yield 'component_with_unclosed_block' => [
'<twig:foo name="bar">{% block a %}</twig:foo>',
'Expected closing tag "</twig:foo>" not found at line 1.',
];
}

public static function getLexTests(): iterable
{
yield 'simple_component' => [
Expand Down Expand Up @@ -62,6 +83,11 @@ public static function getLexTests(): iterable
'Hello {% block foo_block %}Foo{% endblock %}{{ component(\'foo\') }}{% block bar_block %}Bar{% endblock %}',
];

yield 'component_with_commented_block' => [
'<twig:foo name="bar">{# {% block baz %}#}</twig:foo>',
'{% component \'foo\' with { name: \'bar\' } %}{# {% block baz %}#}{% endcomponent %}',
];

yield 'component_with_component_inside_block' => [
'<twig:foo><twig:block name="foo_block"><twig:bar /></twig:block></twig:foo>',
'{% component \'foo\' %}{% block foo_block %}{{ component(\'bar\') }}{% endblock %}{% endcomponent %}',
Expand Down

0 comments on commit 5c0a30f

Please sign in to comment.