diff options
-rw-r--r-- | src/HTML5/Parser/DOMTreeBuilder.php | 10 | ||||
-rw-r--r-- | test/HTML5/Parser/DOMTreeBuilderTest.php | 25 |
2 files changed, 33 insertions, 2 deletions
diff --git a/src/HTML5/Parser/DOMTreeBuilder.php b/src/HTML5/Parser/DOMTreeBuilder.php index e9bca4e..448dec7 100644 --- a/src/HTML5/Parser/DOMTreeBuilder.php +++ b/src/HTML5/Parser/DOMTreeBuilder.php @@ -474,8 +474,14 @@ class DOMTreeBuilder implements EventHandler { $lname = $this->normalizeTagName($name); - // Ignore closing tags for unary elements. - if (Elements::isA($name, Elements::VOID_TAG)) { + // Special case within 12.2.6.4.7: An end tag whose tag name is "br" should be treated as an opening tag + if ($name === 'br') { + $this->parseError('Closing tag encountered for void element br.'); + + $this->startTag('br'); + } + // Ignore closing tags for other unary elements. + elseif (Elements::isA($name, Elements::VOID_TAG)) { return; } diff --git a/test/HTML5/Parser/DOMTreeBuilderTest.php b/test/HTML5/Parser/DOMTreeBuilderTest.php index 00e9a47..af79fda 100644 --- a/test/HTML5/Parser/DOMTreeBuilderTest.php +++ b/test/HTML5/Parser/DOMTreeBuilderTest.php @@ -715,4 +715,29 @@ EOM; $this->assertSame('p', $audio->parentNode->nodeName); $this->assertSame(3, $audio->childNodes->length); } + + public function testClosingBr() + { + $html = <<<EOM +<!DOCTYPE html> +<html> + <head> + <title>testClosingBr</title> + </head> + <body> + <p> + This line ends with a normal line break <br class="attribute-should-be-retained"> + This line ends with a line break marked up as a closing tag </br class="attribute-should-be-discarded"> + </p> + </body> +</html>> +</html> +EOM; + + $dom = $this->parse($html); + + $this->assertSame(2, $dom->getElementsByTagName('br')->length); + $this->assertSame(1, $dom->getElementsByTagName('br')->item(0)->attributes->length); + $this->assertSame(0, $dom->getElementsByTagName('br')->item(1)->attributes->length); + } } |