Skip to content

Commit 97ee926

Browse files
committed
improved {syntax} and n:syntax handling
1 parent aee85ca commit 97ee926

File tree

5 files changed

+134
-82
lines changed

5 files changed

+134
-82
lines changed

src/Latte/Compiler/TemplateLexer.php

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@ final class TemplateLexer
3030
private const ReHtmlValue = '[^\p{C} "\'<>=`{}]+';
3131
private const StateEnd = 'end';
3232

33-
/** @var array<string, array{string, string}> */
34-
public array $syntaxes = [
35-
'latte' => ['\{(?![\s\'"{}])', '\}'], // {...}
36-
'double' => ['\{\{(?![\s\'"{}])', '\}\}'], // {{...}}
37-
'off' => ['\{(?=/syntax\})', '\}'], // {/syntax}
38-
];
3933
public string $openDelimiter;
4034
public string $closeDelimiter;
4135
private TagLexer $tagLexer;
@@ -360,14 +354,19 @@ private function popState(): void
360354
/**
361355
* Changes tag delimiters.
362356
*/
363-
public function setSyntax(?string $type): static
357+
public function setSyntax(?string $type, ?string $endTag = null): static
364358
{
365-
$type ??= 'latte';
366-
if (!isset($this->syntaxes[$type])) {
367-
throw new \InvalidArgumentException("Unknown syntax '$type'");
368-
}
369-
370-
[$this->openDelimiter, $this->closeDelimiter] = $this->syntaxes[$type];
359+
$left = '\{(?![\s\'"{}])';
360+
$end = $endTag ? '\{/' . preg_quote($endTag, '~') . '\}' : null;
361+
362+
[$this->openDelimiter, $this->closeDelimiter] = match ($type) {
363+
null => [$left, '\}'], // {...}
364+
'off' => [$endTag ? '(?=' . $end . ')\{' : '(?!x)x', '\}'],
365+
'double' => $endTag // {{...}}
366+
? ['(?:\{' . $left . '|(?=' . $end . ')\{)', '\}(?:\}|(?<=' . $end . '))']
367+
: ['\{' . $left, '\}\}'],
368+
default => throw new \InvalidArgumentException("Unknown syntax '$type'"),
369+
};
371370
return $this;
372371
}
373372

src/Latte/Essential/CoreExtension.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,11 @@ private function parseSyntax(Tag $tag, TemplateParser $parser): \Generator
222222
{
223223
$tag->expectArguments();
224224
$token = $tag->parser->stream->consume();
225-
$parser->getLexer()->setSyntax($token->text);
225+
$lexer = $parser->getLexer();
226+
$saved = [$lexer->openDelimiter, $lexer->closeDelimiter];
227+
$lexer->setSyntax($token->text, $tag->isNAttribute() ? null : $tag->name);
226228
[$inner] = yield;
227-
$parser->getLexer()->setSyntax(null);
229+
[$lexer->openDelimiter, $lexer->closeDelimiter] = $saved;
228230
return $inner;
229231
}
230232
}

tests/tags/expected/syntax.html

Lines changed: 0 additions & 15 deletions
This file was deleted.

tests/tags/expected/syntax.phtml

Lines changed: 0 additions & 36 deletions
This file was deleted.

tests/tags/syntax.phpt

Lines changed: 118 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,134 @@ require __DIR__ . '/../bootstrap.php';
1414
$latte = new Latte\Engine;
1515
$latte->setLoader(new Latte\Loaders\StringLoader);
1616

17+
// double
18+
$template = <<<'EOD'
19+
{syntax double}
20+
{if $var} {$var} {/if}
21+
{{if $var}} {{$var}} {{/if}}
22+
{* comment single *}
23+
{{* comment double *}}
24+
{/syntax}
25+
26+
{$after}
27+
EOD;
28+
29+
Assert::match(
30+
<<<'XX'
31+
{if $var} {$var} {/if}
32+
var
33+
{* comment single *}
34+
35+
after
36+
XX,
37+
$latte->renderToString($template, ['var' => 'var', 'after' => 'after']),
38+
);
39+
40+
41+
// double n:attribute
1742
$template = <<<'EOD'
1843
<ul n:syntax="double">
19-
{{foreach $people as $person}}
20-
<li>{{$person |upper}}</li>
21-
{{/foreach}}
22-
{* comment latte *}
23-
{{* comment double *}}
44+
{if $var} {$var} {/if}
45+
{{if $var}} {{$var}} {{/if}}
46+
{/syntax}
47+
{* comment single *}
48+
{{* comment double *}}
2449
</ul>
2550
26-
<p>Default: {$person}</p>
51+
{$after}
52+
EOD;
53+
54+
Assert::match(
55+
<<<'XX'
56+
<ul>
57+
{if $var} {$var} {/if}
58+
var
59+
{/syntax}
60+
{* comment single *}
61+
</ul>
2762
28-
<p n:syntax="latte">Default: {$person}</p>
63+
after
64+
XX,
65+
$latte->renderToString($template, ['var' => 'var', 'after' => 'after']),
66+
);
2967

30-
<p n:syntax="off">Default: {$person}</p>
3168

69+
// off
70+
$template = <<<'EOD'
3271
{syntax off}
33-
{a}
34-
{ {/ {/syntax
72+
{if $var} {$var} {/if}
73+
{ {/ {/syntax
74+
{* comment single *}
3575
{/syntax}
76+
77+
{$after}
3678
EOD;
3779

38-
Assert::matchFile(
39-
__DIR__ . '/expected/syntax.phtml',
40-
$latte->compile($template),
80+
Assert::match(
81+
<<<'XX'
82+
{if $var} {$var} {/if}
83+
{ {/ {/syntax
84+
{* comment single *}
85+
86+
after
87+
XX,
88+
$latte->renderToString($template, ['var' => 'var', 'after' => 'after']),
4189
);
42-
Assert::matchFile(
43-
__DIR__ . '/expected/syntax.html',
44-
$latte->renderToString($template, ['people' => ['John', 'Mary', 'Paul']]),
90+
91+
92+
// off n:attribute
93+
$template = <<<'EOD'
94+
<ul n:syntax="off">
95+
{if $var} {$var} {/if}
96+
{/syntax}
97+
{* comment single *}
98+
</ul>
99+
100+
{$after}
101+
EOD;
102+
103+
Assert::match(
104+
<<<'XX'
105+
<ul>
106+
{if $var} {$var} {/if}
107+
{/syntax}
108+
{* comment single *}
109+
</ul>
110+
111+
after
112+
XX,
113+
$latte->renderToString($template, ['var' => 'var', 'after' => 'after']),
114+
);
115+
116+
117+
// nested
118+
$template = <<<'EOD'
119+
<ul n:syntax="double">
120+
{if $var} {$var} {/if}
121+
{{if $var}} {{$var}} {{/if}}
122+
<div n:syntax=off>
123+
{$inner}
124+
</div>
125+
{$after}
126+
{{$after}}
127+
</ul>
128+
129+
{$after}
130+
EOD;
131+
132+
Assert::match(
133+
<<<'XX'
134+
<ul>
135+
{if $var} {$var} {/if}
136+
var
137+
<div>
138+
{$inner}
139+
</div>
140+
{$after}
141+
after
142+
</ul>
143+
144+
after
145+
XX,
146+
$latte->renderToString($template, ['var' => 'var', 'after' => 'after']),
45147
);

0 commit comments

Comments
 (0)