@@ -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 ' => [
0 commit comments