diff options
author | Asmir Mustafic <[email protected]> | 2014-12-14 22:21:59 +0100 |
---|---|---|
committer | Asmir Mustafic <[email protected]> | 2014-12-14 22:21:59 +0100 |
commit | 025f3317ad9c3c6cc123b5fceb2fef78f38a76fb (patch) | |
tree | 7f6429fde98cd04c6db71ed732562e0c7a38abda | |
parent | c1581031d404574a32c4cb1aa72f59f0f5f74250 (diff) |
Auto closing tags if they allows only inline nodes as child nodes
Fixes #68
-rw-r--r-- | src/HTML5/Elements.php | 9 | ||||
-rw-r--r-- | src/HTML5/Parser/DOMTreeBuilder.php | 15 | ||||
-rw-r--r-- | test/HTML5/Parser/DOMTreeBuilderTest.php | 9 |
3 files changed, 31 insertions, 2 deletions
diff --git a/src/HTML5/Elements.php b/src/HTML5/Elements.php index 819ce0e..6cf72aa 100644 --- a/src/HTML5/Elements.php +++ b/src/HTML5/Elements.php @@ -67,6 +67,11 @@ class Elements const BLOCK_TAG = 64; /** + * Indicates that the tag allows only inline elements as child nodes. + */ + const BLOCK_ONLY_INLINE = 128; + + /** * The HTML5 elements as defined in http://dev.w3.org/html5/markup/elements.html. * * @var array @@ -120,7 +125,7 @@ class Elements "head" => 1, "header" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG "hgroup" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG - "hr" => 73, // NORMAL | VOID_TAG | BLOCK_TAG + "hr" => 73, // NORMAL | VOID_TAG "html" => 1, "i" => 1, "iframe" => 3, // NORMAL | TEXT_RAW @@ -145,7 +150,7 @@ class Elements "optgroup" => 1, "option" => 1, "output" => 65, // NORMAL | BLOCK_TAG - "p" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG + "p" => 209, // NORMAL | AUTOCLOSE_P | BLOCK_TAG | BLOCK_ONLY_INLINE "param" => 9, // NORMAL | VOID_TAG "pre" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG "progress" => 1, diff --git a/src/HTML5/Parser/DOMTreeBuilder.php b/src/HTML5/Parser/DOMTreeBuilder.php index 0e2e907..0349d60 100644 --- a/src/HTML5/Parser/DOMTreeBuilder.php +++ b/src/HTML5/Parser/DOMTreeBuilder.php @@ -139,6 +139,12 @@ class DOMTreeBuilder implements EventHandler protected $insertMode = 0; /** + * Track if we are in an element that allows only inline child nodes + * @var string|null + */ + protected $onlyInline; + + /** * Quirks mode is enabled by default. * Any document that is missing the * DT will be considered to be in quirks mode. @@ -320,6 +326,11 @@ class DOMTreeBuilder implements EventHandler } } + if ($this->onlyInline && Elements::isA($lname, Elements::BLOCK_TAG)) { + $this->autoclose($this->onlyInline); + $this->onlyInline = null; + } + try { $prefix = ($pos = strpos($lname, ':')) ? substr($lname, 0, $pos) : ''; @@ -346,6 +357,10 @@ class DOMTreeBuilder implements EventHandler $ele = $this->doc->createElement('invalid'); } + if (Elements::isA($lname, Elements::BLOCK_ONLY_INLINE)) { + $this->onlyInline = $lname; + } + // When we add some namespacess, we have to track them. Later, when "endElement" is invoked, we have to remove them. // When we are on a void tag, we do not need to care about namesapce nesting. if ($pushes > 0 && !Elements::isA($name, Elements::VOID_TAG)) { diff --git a/test/HTML5/Parser/DOMTreeBuilderTest.php b/test/HTML5/Parser/DOMTreeBuilderTest.php index 5227c40..9a7d5d8 100644 --- a/test/HTML5/Parser/DOMTreeBuilderTest.php +++ b/test/HTML5/Parser/DOMTreeBuilderTest.php @@ -204,6 +204,15 @@ class DOMTreeBuilderTest extends \Masterminds\HTML5\Tests\TestCase $this->assertEquals("http://www.prefixed.com/bar5_x", $prefixed->namespaceURI); } + public function testMoveNonInlineElements() + { + $doc = $this->parse('<p>line1<br/><hr/>line2</p>'); + $this->assertEquals('<html xmlns="http://www.w3.org/1999/xhtml"><p>line1<br/></p><hr/>line2</html>', $doc->saveXML($doc->documentElement), 'Move non-inline elements outside of inline containers.'); + + $doc = $this->parse('<p>line1<div>line2</div></p>'); + $this->assertEquals('<html xmlns="http://www.w3.org/1999/xhtml"><p>line1</p><div>line2</div></html>', $doc->saveXML($doc->documentElement), 'Move non-inline elements outside of inline containers.'); + } + public function testAttributes() { $html = "<!DOCTYPE html> |