2 declare(strict_types = 1);
20 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
32 protected function setUp(): void
43 'single-line CDATA' => [
44 '/*<![CDATA[*/ <hello world> /*]]>*/',
45 '/*<![CDATA[*/ <hello world> /*]]>*/',
47 'multi-line CDATA #1' => [
48 '/*<![CDATA[*/' . LF .
'<hello world> /*]]>*/',
49 '/*<![CDATA[*/' . LF .
'<hello world> /*]]>*/',
51 'multi-line CDATA #2' => [
52 '/*<![CDATA[*/ <hello world>' . LF .
'/*]]>*/',
53 '/*<![CDATA[*/ <hello world>' . LF .
'/*]]>*/',
55 'multi-line CDATA #3' => [
56 '/*<![CDATA[*/' . LF .
'<hello world>' . LF .
'/*]]>*/',
57 '/*<![CDATA[*/' . LF .
'<hello world>' . LF .
'/*]]>*/',
72 '<body><h1>Title</h1><span>Note</span></body>',
84 '<body><h1>Title</h1><br /><span>Note</span><br /></body>',
94 'splitBlock with attribute' => [
96 '<body><h1 class="title">Title</h1><span>Note</span></body>',
100 '<h1 class="title">Title</h1>',
106 'splitBlock span with attribute' => [
108 '<body><h1>Title</h1><span class="title">Note</span></body>',
111 '<body><h1>Title</h1>',
112 '<span class="title">Note</span>',
116 'splitBlock without extra end tags' => [
118 '<body><h1>Title</h1><span>Note</span></body></div>',
139 public function splitIntoBlock(
string $tag,
string $content,
bool $eliminateExtraEndTags, array $expected): void
141 $this->assertSame($expected, $this->subject->splitIntoBlock($tag, $content, $eliminateExtraEndTags));
152 $result = $this->subject->HTMLcleaner($source, [], 1);
153 $this->assertSame($expected, $result);
162 'Span tag with no attrib' => [
166 'Span tag with allowed id attrib' => [
167 '<span id="id">text</span>',
168 '<span id="id">text</span>'
170 'Span tag with disallowed style attrib' => [
171 '<span style="line-height: 12px;">text</span>',
186 'allowTags' =>
'span',
189 'allowedAttribs' =>
'id',
190 'rmTagIfNoAttrib' => 1
203 'allowTags' =>
'div,span',
204 'rmTagIfNoAttrib' =>
'span',
205 'globalNesting' =>
'div,span'
207 $content =
'<span></span><span id="test"><div></span></div>';
208 $expectedResult =
'<span id="test"></span>';
220 'Valid nesting is untouched' => [
224 'Valid nesting with content is untouched' => [
225 'testa<B>test1<I>test2</B>test3</I>testb',
226 'testa<B>test1<I>test2</B>test3</I>testb'
228 'Superflous tags are removed' => [
229 '</B><B><I></B></I></B>',
232 'Superflous tags with content are removed' => [
233 'test1</B>test2<B>test3<I>test4</B>test5</I>test6</B>test7',
234 'test1test2<B>test3<I>test4</B>test5</I>test6test7'
236 'Another valid nesting test' => [
237 '<span><div></span></div>',
238 '<span><div></span></div>',
252 'allowTags' =>
'div,span,b,i',
253 'localNesting' =>
'div,span,b,i',
266 'Valid nesting is untouched' => [
270 'Valid nesting with content is untouched' => [
271 'testa<B>test1<I>test2</I>test3</B>testb',
272 'testa<B>test1<I>test2</I>test3</B>testb'
274 'Invalid nesting is cleaned' => [
275 '</B><B><I></B></I></B>',
278 'Invalid nesting with content is cleaned' => [
279 'test1</B>test2<B>test3<I>test4</B>test5</I>test6</B>test7',
280 'test1test2<B>test3test4</B>test5test6test7'
282 'Another invalid nesting test' => [
283 '<span><div></span></div>',
298 'allowTags' =>
'span,div,b,i',
299 'globalNesting' =>
'span,div,b,i',
310 [0,
null,
false,
'<h1></h1>',
'<h1></h1>'],
311 [1,
null,
false,
'<h1></h1>',
''],
312 [1,
null,
false,
'<h1>hallo</h1>',
'<h1>hallo</h1>'],
313 [1,
null,
false,
'<h1 class="something"></h1>',
''],
314 [1,
null,
false,
'<h1 class="something"></h1><h2></h2>',
''],
315 [1,
'h2',
false,
'<h1 class="something"></h1><h2></h2>',
'<h1 class="something"></h1>'],
316 [1,
'h2, h1',
false,
'<h1 class="something"></h1><h2></h2>',
''],
317 [1,
null,
false,
'<div><p></p></div>',
''],
318 [1,
null,
false,
'<div><p> </p></div>',
'<div><p> </p></div>'],
319 [1,
null,
true,
'<div><p> </p></div>',
''],
320 [1,
null,
true,
'<div> <p></p></div>',
''],
321 [1,
null,
false,
'<div>Some content<p></p></div>',
'<div>Some content</div>'],
322 [1,
null,
true,
'<div>Some content<p></p></div>',
'<div>Some content</div>'],
323 [1,
null,
false,
'<div>Some content</div>',
'<div>Some content</div>'],
324 [1,
null,
true,
'<div>Some content</div>',
'<div>Some content</div>'],
325 [1,
null,
false,
'<a href="#skiplinks">Skiplinks </a><b></b>',
'<a href="#skiplinks">Skiplinks </a>'],
326 [1,
null,
true,
'<a href="#skiplinks">Skiplinks </a><b></b>',
'<a href="#skiplinks">Skiplinks </a>'],
327 [0,
'',
false,
'<h1></h1>',
'<h1></h1>'],
328 [1,
'',
false,
'<h1></h1>',
''],
329 [1,
'',
false,
'<h1>hallo</h1>',
'<h1>hallo</h1>'],
330 [1,
'',
false,
'<h1 class="something"></h1>',
''],
331 [1,
'',
false,
'<h1 class="something"></h1><h2></h2>',
''],
332 [1,
'',
false,
'<div><p></p></div>',
''],
333 [1,
'',
false,
'<div><p> </p></div>',
'<div><p> </p></div>'],
334 [1,
'',
true,
'<div><p> </p></div>',
''],
335 [1,
'',
true,
'<div> <p></p></div>',
''],
336 [1,
'',
false,
'<div>Some content<p></p></div>',
'<div>Some content</div>'],
337 [1,
'',
true,
'<div>Some content<p></p></div>',
'<div>Some content</div>'],
338 [1,
'',
false,
'<div>Some content</div>',
'<div>Some content</div>'],
339 [1,
'',
true,
'<div>Some content</div>',
'<div>Some content</div>'],
340 [1,
'',
false,
'<a href="#skiplinks">Skiplinks </a><b></b>',
'<a href="#skiplinks">Skiplinks </a>'],
341 [1,
'',
true,
'<a href="#skiplinks">Skiplinks </a><b></b>',
'<a href="#skiplinks">Skiplinks </a>'],
357 bool $treatNonBreakingSpaceAsEmpty,
359 string $expectedResult
362 'keepNonMatchedTags' => 1,
363 'stripEmptyTags' => $stripOn,
364 'stripEmptyTags.' => [
366 'treatNonBreakingSpaceAsEmpty' => $treatNonBreakingSpaceAsEmpty
371 $this->assertEquals($expectedResult, $result);
383 '<div><p><tr><td></td></tr></p></div><div class="test"></div><tr></tr><p></p><td></td><i></i>',
384 '<div><p><tr><td></td></tr></p></div><tr></tr><td></td>'
389 '<div><p><tr><td></td></tr></p></div><p class="test"> </p><tr></tr><p></p><td></td><i></i>',
390 '<div><p><tr><td></td></tr></p></div><tr></tr><td></td>'
405 bool $treatNonBreakingSpaceAsEmpty,
407 string $expectedResult
410 'keepNonMatchedTags' => 1,
411 'stripEmptyTags' => 1,
412 'stripEmptyTags.' => [
413 'keepTags' => $tagList,
414 'treatNonBreakingSpaceAsEmpty' => $treatNonBreakingSpaceAsEmpty
419 $this->assertEquals($expectedResult, $result);
431 $config = $this->subject->HTMLparserConfig($tsConfig);
432 return $this->subject->HTMLcleaner($content, $config[0], $config[1], $config[2], $config[3]);
443 [
'<body><span></span></body>',
'<body>'],
444 [
'<span>Wrapper<div>Some content</div></span>',
'<span>'],
445 [
'Something before<span>Wrapper<div>Some content</div></span>Something after',
'Something before<span>'],
446 [
'Something without tag',
''],
447 [
'text</span>',
'text</span>'],
448 [
'<span class=<other><inner></span>',
'<span class=<other>'],
449 [
'<sp-an class=<other><inner></sp-an>',
'<sp-an class=<other>'],
450 [
'<span/class=<other><inner></span>',
'<span/class=<other>'],
451 [
'<span class="<other>"><inner></span>',
'<span class="<other>">'],
452 [
'<span class=""<other>""><inner></span>',
'<span class=""<other>'],
453 [
'<span class=<other>>><inner></span>',
'<span class=<other>'],
454 [
'<span class="',
''],
455 [
'<span class=""',
''],
456 [
'<span class="<"',
''],
457 [
'<span class=">"',
''],
458 [
'<span class="<other><inner></span>',
''],
459 [
"<span class='<other><inner></span>",
''],
460 [
'<span class="<other>\'<inner></span>',
''],
461 [
"<span class='<other>\"<inner></span>",
''],
475 public function getFirstTag(
string $str,
string $expected): void
477 $this->assertEquals($expected, $this->subject->getFirstTag($str));
489 '<body><span></span></body>',
494 '<body><span></span></body>',
499 '<div class="test"><span></span></div>',
504 '<div><span class="test"></span></div>',
509 '<br /><span class="test"></span>',
514 '<img src="test.jpg" />',
518 [
'text</span>',
false,
''],
519 [
'<span class=<other><inner></span>',
false,
'SPAN'],
520 [
'<sp-an class=<other><inner></sp-an>',
false,
'SP-AN'],
521 [
'<span/class=<other><inner></span>',
false,
'SPAN'],
522 [
'<span class="<other>"><inner></span>',
false,
'SPAN'],
523 [
'<span class=""<other>""><inner></span>',
false,
'SPAN'],
524 [
'<span class=<other>>><inner></span>',
false,
'SPAN'],
525 [
'<span class="',
false,
''],
526 [
'<span class=""',
false,
''],
527 [
'<span class="<"',
false,
''],
528 [
'<span class=">"',
false,
''],
529 [
'<span class="<other><inner></span>',
false,
''],
530 [
"<span class='<other><inner></span>",
false,
''],
531 [
'<span class="<other>\'<inner></span>',
false,
''],
532 [
"<span class='<other>\"<inner></span>",
false,
''],
547 public function getFirstTagName(
string $str,
bool $preserveCase,
string $expected): void
549 $this->assertEquals($expected, $this->subject->getFirstTagName($str, $preserveCase));
558 [
'<span>Wrapper<div>Some content</div></span>',
'Wrapper<div>Some content</div>'],
559 [
'<td><tr>Some content</tr></td>',
'<tr>Some content</tr>'],
561 'Something before<span>Wrapper<div>Some content</div></span>Something after',
562 'Wrapper<div>Some content</div>'
564 [
'<span class="hidden">Wrapper<div>Some content</div></span>',
'Wrapper<div>Some content</div>'],
566 '<span>Wrapper<div class="hidden">Some content</div></span>',
567 'Wrapper<div class="hidden">Some content</div>'
570 'Some stuff before <span>Wrapper<div class="hidden">Some content</div></span> and after',
571 'Wrapper<div class="hidden">Some content</div>'
576 [
'<span class=<other><inner></span>',
'<inner>'],
577 [
'<sp-an class=<other><inner></sp-an>',
'<inner>'],
578 [
'<span/class=<other><inner></span>',
'<inner>'],
579 [
'<span class="<other>"><inner></span>',
'<inner>'],
580 [
'<span class=""<other>""><inner></span>',
'""><inner>'],
581 [
'<span class=<other>>><inner></span>',
'>><inner>'],
582 [
'<span class="',
''],
583 [
'<span class=""',
''],
584 [
'<span class="<"',
''],
585 [
'<span class=">"',
''],
586 [
'<span class="<other><inner></span>',
''],
587 [
"<span class='<other><inner></span>",
''],
588 [
'<span class="<other>\'<inner></span>',
''],
589 [
"<span class='<other>\"<inner></span>",
''],
604 $this->assertEquals($expectedResult, $this->subject->removeFirstAndLastTag($str));
614 '<a href="" data-shortCut="DXB" required>',
616 [
'href' =>
'',
'data-shortcut' =>
'DXB',
'required' =>
''],
618 'href' => [
'origTag' =>
'href',
'dashType' =>
'"'],
619 'data-shortcut' => [
'origTag' =>
'data-shortCut',
'dashType' =>
'"'],
620 'required' => [
'origTag' =>
'required']
625 '<ul STYLE=\'background-image: (url: "fra.png")\' data-shortcut=FRA>',
627 [
'style' =>
'background-image: (url: "fra.png")',
'data-shortcut' =>
'FRA'],
629 'style' => [
'origTag' =>
'STYLE',
'dashType' =>
'\''],
630 'data-shortcut' => [
'origTag' =>
'data-shortcut',
'dashType' =>
'']
649 $this->assertEquals($expectedResult, $this->subject->get_tag_attributes($tag));
660 '<div>Denpassar</div><p> Bali</P><p></p><P></p><ul><li></li></ul>',
663 '<div>Denpassar</div><p> Bali</P>'
667 '<p><div>Klungklung</div></p><p> Semarapura<p></p><p></p><ul><li></li></ul>',
670 '<p><div>Klungklung</div></p><p> Semarapura'
674 '<p><div>Badung</div></p><ul> Mangupura<p></p><p></p><ul><li> </li><li>Uluwatu</li></ul>',
677 '<p><div>Badung</div></p><ul> Mangupura<ul><li>Uluwatu</li></ul>'
681 '<p><div>Badung</div></p><ul> Mangupura<p></p><p></p><ul><li></li></ul>',
684 '<p><div>Badung</div></p><ul> Mangupura<ul><li></li></ul>'
704 bool $treatNonBreakingSpaceAsEmpty,
705 string $expectedResult
709 $this->subject->stripEmptyTags($content, $tagList, $treatNonBreakingSpaceAsEmpty)