Skip to content

Commit c36a143

Browse files
committed
Compiler: added new state HtmlRawText
1 parent 2544c19 commit c36a143

4 files changed

Lines changed: 35 additions & 31 deletions

File tree

src/Latte/Compiler/Escaper.php

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,9 @@ final class Escaper
3333
HtmlText = 'html',
3434
HtmlComment = 'html/comment',
3535
HtmlBogusTag = 'html/bogus',
36-
HtmlCss = 'html/css',
37-
HtmlJavaScript = 'html/js',
3836
HtmlTag = 'html/tag',
39-
HtmlAttribute = 'html/attr';
37+
HtmlAttribute = 'html/attr',
38+
HtmlRawText = 'html/rawtext';
4039

4140
private string $state = '';
4241
private string $tag = '';
@@ -78,18 +77,19 @@ public function enterContentType(string $type): void
7877

7978
public function enterHtmlText(?ElementNode $node): void
8079
{
81-
$this->state = self::HtmlText;
82-
if ($this->contentType === ContentType::Html && $node) {
83-
$name = strtolower($node->name);
84-
if (
85-
($name === 'script' || $name === 'style')
86-
&& is_string($attr = $node->getAttribute('type') ?? 'css')
87-
&& preg_match('#(java|j|ecma|live)script|module|json|css|plain#i', $attr)
88-
) {
89-
$this->state = $name === 'script'
90-
? self::HtmlJavaScript
91-
: self::HtmlCss;
92-
}
80+
$name = strtolower($node->name ?? '');
81+
if ($this->contentType === ContentType::Html && in_array($name, ['script', 'style'], true)) {
82+
$attr = $node->getAttribute('type');
83+
$this->state = self::HtmlRawText;
84+
$this->subType = match (true) {
85+
$name === 'style' => self::Css,
86+
!is_string($attr) || preg_match('#(java|j|ecma|live)script|module|json|plain#i', $attr) => self::JavaScript,
87+
$attr === 'text/html' => self::HtmlText,
88+
default => '',
89+
};
90+
} else {
91+
$this->state = self::HtmlText;
92+
$this->subType = '';
9393
}
9494
}
9595

@@ -155,8 +155,12 @@ public function escape(string $str): string
155155
},
156156
self::HtmlComment => 'LR\Filters::escapeHtmlComment(' . $str . ')',
157157
self::HtmlBogusTag => 'LR\Filters::escapeHtml(' . $str . ')',
158-
self::HtmlJavaScript => 'LR\Filters::escapeJs(' . $str . ')',
159-
self::HtmlCss => 'LR\Filters::escapeCss(' . $str . ')',
158+
self::HtmlRawText => match ($this->subType) {
159+
'' => 'LR\Filters::escapeHtmlRawText(' . $str . ')',
160+
self::HtmlText => 'LR\Filters::escapeHtmlText(' . $str . ')',
161+
self::JavaScript => 'LR\Filters::escapeJs(' . $str . ')',
162+
self::Css => 'LR\Filters::escapeCss(' . $str . ')',
163+
},
160164
default => throw new \LogicException("Unknown context $this->contentType, $this->state."),
161165
},
162166
ContentType::Xml => match ($this->state) {
@@ -202,14 +206,14 @@ public static function getConvertor(string $source, string $dest): ?callable
202206
'html' => 'escapeHtmlText',
203207
'html/attr' => 'escapeHtmlAttr',
204208
'html/attr/js' => 'escapeHtmlAttr',
205-
'html/js' => 'escapeHtmlRawText',
209+
'html/rawtext/js' => 'escapeHtmlRawText',
206210
'html/comment' => 'escapeHtmlComment',
207211
],
208212
self::Css => [
209213
'html' => 'escapeHtmlText',
210214
'html/attr' => 'escapeHtmlAttr',
211215
'html/attr/css' => 'escapeHtmlAttr',
212-
'html/css' => 'escapeHtmlRawText',
216+
'html/rawtext/css' => 'escapeHtmlRawText',
213217
'html/comment' => 'escapeHtmlComment',
214218
],
215219
'html' => [

tests/common/contentType.compatibility.phpt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ test('', function () {
180180
Assert::exception(
181181
fn() => $latte->renderToString('<div>{include style}</div> <STYLE n:inner-block=style>...</STYLE>'),
182182
Latte\RuntimeException::class,
183-
'Including block style with content type HTML/CSS into incompatible type HTML.',
183+
'Including block style with content type HTML/RAWTEXT/CSS into incompatible type HTML.',
184184
);
185185

186186
Assert::match(
@@ -191,7 +191,7 @@ test('', function () {
191191
Assert::exception(
192192
fn() => $latte->renderToString('<div>{include script}</div> <script n:inner-block=script>...</script>'),
193193
Latte\RuntimeException::class,
194-
'Including block script with content type HTML/JS into incompatible type HTML.',
194+
'Including block script with content type HTML/RAWTEXT/JS into incompatible type HTML.',
195195
);
196196
});
197197

@@ -268,7 +268,7 @@ Assert::same('<script> <\/script></script>', $latte->renderToString('context4'))
268268
Assert::exception(
269269
fn() => $latte->renderToString('context5'),
270270
Latte\RuntimeException::class,
271-
"Including 'js.latte' with content type JS into incompatible type HTML/CSS.",
271+
"Including 'js.latte' with content type JS into incompatible type HTML/RAWTEXT/CSS.",
272272
);
273273

274274
Assert::same('<!-- </script>-->', $latte->renderToString('context6'));
@@ -310,13 +310,13 @@ Assert::same('<p title="&lt;hr&gt; &quot; &quot; &lt;"></p>', $latte->renderToSt
310310
Assert::exception(
311311
fn() => $latte->renderToString('context4'),
312312
Latte\RuntimeException::class,
313-
"Including 'html.latte' with content type HTML into incompatible type HTML/JS.",
313+
"Including 'html.latte' with content type HTML into incompatible type HTML/RAWTEXT/JS.",
314314
);
315315

316316
Assert::exception(
317317
fn() => $latte->renderToString('context5'),
318318
Latte\RuntimeException::class,
319-
"Including 'html.latte' with content type HTML into incompatible type HTML/CSS.",
319+
"Including 'html.latte' with content type HTML into incompatible type HTML/RAWTEXT/CSS.",
320320
);
321321

322322
Assert::same('<!--<hr> " &quot; &lt;-->', $latte->renderToString('context6'));

tests/common/contentType.html.css.phpt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,8 @@ Assert::match(
4545
$latte->renderToString('<style type="TEXT/CSS">{="<>"}</style>'),
4646
);
4747

48-
Assert::match(
49-
'<style type="text/html">&lt;&gt;</style>',
50-
$latte->renderToString('<style type="text/html">{="<>"}</style>'),
51-
);
52-
53-
Assert::match(
54-
'<style type="text/html">&lt;&gt;</style>',
48+
Assert::match( // type is ignored
49+
'<style type="text/html">\<\></style>',
5550
$latte->renderToString('<style type="text/html">{="<>"}</style>'),
5651
);
5752

tests/common/contentType.html.javascript.phpt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ Assert::match(
8888
$latte->renderToString('<script type="text/html">{="<>"}</script>'),
8989
);
9090

91+
Assert::match(
92+
'<script type="unknown"><> <\/script></script>',
93+
$latte->renderToString('<script type="unknown">{="<> </script>"}</script>'),
94+
);
95+
9196
// content of <script> is RAWTEXT
9297
Assert::match(
9398
<<<'XX'

0 commit comments

Comments
 (0)