summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Butcher <[email protected]>2014-12-16 08:26:25 -0700
committerMatt Butcher <[email protected]>2014-12-16 08:26:25 -0700
commitde3a3af4aa683d0dae5bd09b62fe74127974c3ea (patch)
tree7f6429fde98cd04c6db71ed732562e0c7a38abda
parentb39dd885966dea2d3d33509af505f4ecef2f6343 (diff)
parent025f3317ad9c3c6cc123b5fceb2fef78f38a76fb (diff)
Merge pull request #70 from Masterminds/non-inline-elements
Auto closing tags if they allows only inline nodes as child nodes
-rw-r--r--src/HTML5/Elements.php9
-rw-r--r--src/HTML5/Parser/DOMTreeBuilder.php15
-rw-r--r--test/HTML5/Parser/DOMTreeBuilderTest.php9
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>