diff options
-rw-r--r-- | src/HTML5/Parser/DOMTreeBuilder.php | 31 | ||||
-rw-r--r-- | test/HTML5/Parser/DOMTreeBuilderTest.php | 21 |
2 files changed, 50 insertions, 2 deletions
diff --git a/src/HTML5/Parser/DOMTreeBuilder.php b/src/HTML5/Parser/DOMTreeBuilder.php index 46353e9..82ec520 100644 --- a/src/HTML5/Parser/DOMTreeBuilder.php +++ b/src/HTML5/Parser/DOMTreeBuilder.php @@ -39,6 +39,9 @@ class DOMTreeBuilder implements EventHandler { const IM_AFTER_AFTER_BODY = 20; const IM_AFTER_AFTER_FRAMESET = 21; + const IM_IN_SVG = 22; + const IM_IN_MATHML = 23; + protected $stack = array(); protected $current; // Pointer in the tag hierarchy. protected $doc; @@ -150,6 +153,12 @@ class DOMTreeBuilder implements EventHandler { case 'body': $this->insertMode = self::IM_IN_BODY; break; + case 'svg': + $this->insertMode = self::IM_IN_SVG; + break; + case 'mathml': + $this->insertMode = self::IM_IN_MATHML; + break; case 'noscript': if ($this->insertMode == self::IM_IN_HEAD) { $this->insertMode = self::IM_IN_HEAD_NOSCRIPT; @@ -158,9 +167,22 @@ class DOMTreeBuilder implements EventHandler { } + // Special case handling for SVG. + if ($this->insertMode == self::IM_IN_SVG) { + $lname = Elements::normalizeSvgElement($lname); + } + $ele = $this->doc->createElement($lname); foreach ($attributes as $aName => $aVal) { + + if ($this->insertMode == self::IM_IN_SVG) { + $aName = Elements::normalizeSvgAttribute($aName); + } + elseif ($this->insertMode == self::IM_IN_MATHML) { + $aName = Elements::normalizeMathMlAttribute($aname); + } + $ele->setAttribute($aName, $aVal); // This is necessary on a non-DTD schema, like HTML5. @@ -211,7 +233,7 @@ class DOMTreeBuilder implements EventHandler { } if ($name != $lname) { - fprintf(STDOUT, "Mismatch on %s and %s", $name, $lname); + //fprintf(STDOUT, "Mismatch on %s and %s", $name, $lname); return $this->quirksTreeResolver($lname); } @@ -226,13 +248,18 @@ class DOMTreeBuilder implements EventHandler { $this->parseError('Could not find closing tag for ' . $name); } - switch ($this->insertMode) { + //switch ($this->insertMode) { + switch ($lname) { case "head": $this->insertMode = self::IM_AFTER_HEAD; break; case "body": $this->insertMode = self::IM_AFTER_BODY; break; + case "svg": + case "mathml": + $this->insertMode = self::IM_IN_BODY; + break; } // 8.2.5.4.7 diff --git a/test/HTML5/Parser/DOMTreeBuilderTest.php b/test/HTML5/Parser/DOMTreeBuilderTest.php index 3620a89..ed8e70e 100644 --- a/test/HTML5/Parser/DOMTreeBuilderTest.php +++ b/test/HTML5/Parser/DOMTreeBuilderTest.php @@ -76,6 +76,27 @@ class DOMTreeBuilderTest extends \HTML5\Tests\TestCase { $this->assertEquals('a', $body2->getAttribute('id')); } + public function testSVGAttributes() { + $html = "<!DOCTYPE html> + <html><body> + <svg width='150' viewbox='2'> + <rect textlength='2'/> + <animatecolor>foo</animatecolor> + </svg> + </body></html>"; + $doc = $this->parse($html); + $root = $doc->documentElement; + + $svg = $root->getElementsByTagName('svg')->item(0); + $this->assertTrue($svg->hasAttribute('viewBox')); + + $rect = $root->getElementsByTagName('rect')->item(0); + $this->assertTrue($rect->hasAttribute('textLength')); + + $ac = $root->getElementsByTagName('animateColor'); + $this->assertEquals(1, $ac->length); + } + public function testMissingHtmlTag() { $html = "<!DOCTYPE html><title>test</title>"; $doc = $this->parse($html); |