From cb8c748d49fe4e994dbb5878965783f891ead510 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 11 Aug 2023 02:20:20 +0200 Subject: [PATCH] TemplateParserHtml: HTML attribute name can be PrintNode or string (BC break) --- src/Latte/Compiler/TemplateParserHtml.php | 30 +++++---------------- tests/common/Compiler.errors.phpt | 12 +++++++++ tests/common/TemplateParser.nodes.phpt | 33 +++++++++-------------- 3 files changed, 31 insertions(+), 44 deletions(-) diff --git a/src/Latte/Compiler/TemplateParserHtml.php b/src/Latte/Compiler/TemplateParserHtml.php index 57b4568bd..d4760040d 100644 --- a/src/Latte/Compiler/TemplateParserHtml.php +++ b/src/Latte/Compiler/TemplateParserHtml.php @@ -259,19 +259,13 @@ private function parseAttributeWhitespace(): Node private function parseAttribute(): ?Node { $stream = $this->parser->getStream(); - $followsLatte = $stream->is(Token::Latte_TagOpen); - $save = $stream->getIndex(); - try { - $name = $this->parseAttributeName(); - if (!$name) { - return null; - } - } catch (CompileException $e) { - if ($followsLatte && $stream->peek()) { // it is not lexer exception - $stream->seek($save); - return $this->parser->parseLatteStatement(); // attribute name with the value like '' + if ($stream->is(Token::Latte_TagOpen)) { + $name = $this->parser->parseLatteStatement(); + if (!$name instanceof Latte\Essential\Nodes\PrintNode) { + return $name; // value like '' } - throw $e; + } else { + $name = $this->parser->parseText(); } [$value, $quote] = $this->parseAttributeValue(); @@ -284,18 +278,6 @@ private function parseAttribute(): ?Node } - private function parseAttributeName(): ?AreaNode - { - $stream = $this->parser->getStream(); - return $this->parser->parseFragment(fn() => match ($stream->peek()->type) { - Token::Html_Name => $this->parser->parseText(), - Token::Latte_TagOpen => $this->parser->parseLatteStatement(), - Token::Latte_CommentOpen => $this->parser->parseLatteComment(), - default => null, - })->simplify(); - } - - private function parseAttributeValue(): ?array { $stream = $this->parser->getStream(); diff --git a/tests/common/Compiler.errors.phpt b/tests/common/Compiler.errors.phpt index ce922d866..4a03de44c 100644 --- a/tests/common/Compiler.errors.phpt +++ b/tests/common/Compiler.errors.phpt @@ -56,6 +56,18 @@ Assert::exception( 'Unexpected \'"a"{/if\', expecting {/if} (on line 1 at column 22)', ); +Assert::exception( + fn() => $latte->compile(''), + Latte\CompileException::class, + "Unexpected '=a> $latte->compile(''), + Latte\CompileException::class, + "Unexpected '=a> $latte->compile(''), Latte\CompileException::class, diff --git a/tests/common/TemplateParser.nodes.phpt b/tests/common/TemplateParser.nodes.phpt index e0a75135a..63d0d5e68 100644 --- a/tests/common/TemplateParser.nodes.phpt +++ b/tests/common/TemplateParser.nodes.phpt @@ -198,40 +198,33 @@ Assert::match(<<<'XX' | | | | | | content: ' ' | | | | | | position: 1:27 (offset 26) | | | | | 3 => Latte\Compiler\Nodes\Html\AttributeNode - | | | | | | name: FooNode + | | | | | | name: Latte\Compiler\Nodes\TextNode + | | | | | | | content: 'attr5' | | | | | | | position: 1:28 (offset 27) | | | | | | value: FooNode - | | | | | | | position: 1:45 (offset 44) + | | | | | | | position: 1:34 (offset 33) | | | | | | quote: null | | | | | | position: 1:28 (offset 27) | | | | | 4 => Latte\Compiler\Nodes\TextNode | | | | | | content: ' ' - | | | | | | position: 1:57 (offset 56) + | | | | | | position: 1:46 (offset 45) | | | | | 5 => Latte\Compiler\Nodes\Html\AttributeNode - | | | | | | name: Latte\Compiler\Nodes\FragmentNode - | | | | | | | children: array (3) - | | | | | | | | 0 => Latte\Compiler\Nodes\TextNode - | | | | | | | | | content: 'attr6' - | | | | | | | | | position: 1:58 (offset 57) - | | | | | | | | 1 => FooNode - | | | | | | | | | position: 1:63 (offset 62) - | | | | | | | | 2 => Latte\Compiler\Nodes\TextNode - | | | | | | | | | content: 'b' - | | | | | | | | | position: 1:69 (offset 68) - | | | | | | | position: 1:58 (offset 57) + | | | | | | name: Latte\Compiler\Nodes\TextNode + | | | | | | | content: 'attr6' + | | | | | | | position: 1:47 (offset 46) | | | | | | value: Latte\Compiler\Nodes\FragmentNode | | | | | | | children: array (3) | | | | | | | | 0 => Latte\Compiler\Nodes\TextNode | | | | | | | | | content: 'c' - | | | | | | | | | position: 1:71 (offset 70) + | | | | | | | | | position: 1:53 (offset 52) | | | | | | | | 1 => FooNode - | | | | | | | | | position: 1:72 (offset 71) + | | | | | | | | | position: 1:54 (offset 53) | | | | | | | | 2 => Latte\Compiler\Nodes\TextNode | | | | | | | | | content: 'd' - | | | | | | | | | position: 1:78 (offset 77) - | | | | | | | position: 1:71 (offset 70) + | | | | | | | | | position: 1:60 (offset 59) + | | | | | | | position: 1:53 (offset 52) | | | | | | quote: null - | | | | | | position: 1:58 (offset 57) + | | | | | | position: 1:47 (offset 46) | | | | position: 1:4 (offset 3) | | | selfClosing: false | | | content: null @@ -249,7 +242,7 @@ Assert::match(<<<'XX' | position: 1:1 (offset 0) contentType: 'html' position: null - XX, parse("
")); + XX, parse("
")); Assert::match(<<<'XX'