public function endTag($name) { $lname = $this->normalizeTagName($name); // Ignore closing tags for unary elements. if (Elements::isA($name, Elements::VOID_TAG)) { return; } if ($this->insertMode <= static::IM_BEFORE_HTML) { // 8.2.5.4.2 if (in_array($name, array('html', 'br', 'head', 'title'))) { $this->startTag('html'); $this->endTag($name); $this->insertMode = static::IM_BEFORE_HEAD; return; } // Ignore the tag. $this->parseError("Illegal closing tag at global scope."); return; } // Special case handling for SVG. if ($this->insertMode == static::IM_IN_SVG) { $lname = Elements::normalizeSvgElement($lname); } // See https://github.com/facebook/hhvm/issues/2962 if (defined('HHVM_VERSION') && ($cid = $this->current->getAttribute('html5-php-fake-id-attribute'))) { $this->current->removeAttribute('html5-php-fake-id-attribute'); } else { $cid = spl_object_hash($this->current); } // XXX: Not sure whether we need this anymore. // if ($name != $lname) { // return $this->quirksTreeResolver($lname); // } // XXX: HTML has no parent. What do we do, though, // if this element appears in the wrong place? if ($lname == 'html') { return; } // remove the namespaced definded by current node if (isset($this->pushes[$cid])) { for ($i = 0; $i < $this->pushes[$cid][0]; $i++) { array_shift($this->nsStack); } unset($this->pushes[$cid]); } if (!$this->autoclose($lname)) { $this->parseError('Could not find closing tag for ' . $lname); } // switch ($this->insertMode) { switch ($lname) { case "head": $this->insertMode = static::IM_AFTER_HEAD; break; case "body": $this->insertMode = static::IM_AFTER_BODY; break; case "svg": case "mathml": $this->insertMode = static::IM_IN_BODY; break; } }
protected function attrs($ele) { // FIXME: Needs support for xml, xmlns, xlink, and namespaced elements. if (!$ele->hasAttributes()) { return $this; } // TODO: Currently, this always writes name="value", and does not do // value-less attributes. $map = $ele->attributes; $len = $map->length; for ($i = 0; $i < $len; ++$i) { $node = $map->item($i); $val = $this->enc($node->value, true); // XXX: The spec says that we need to ensure that anything in // the XML, XMLNS, or XLink NS's should use the canonical // prefix. It seems that DOM does this for us already, but there // may be exceptions. $name = $node->name; // Special handling for attributes in SVG and MathML. // Using if/elseif instead of switch because it's faster in PHP. if ($this->outputMode == static::IM_IN_SVG) { $name = Elements::normalizeSvgAttribute($name); } elseif ($this->outputMode == static::IM_IN_MATHML) { $name = Elements::normalizeMathMlAttribute($name); } $this->wr(' ')->wr($name); if (isset($val) && $val !== '' || $this->nonBooleanAttribute($node)) { $this->wr('="')->wr($val)->wr('"'); } } }
/** * Read text in RCDATA mode. */ protected function rcdata() { if (is_null($this->untilTag)) { return $this->text(); } $sequence = '</' . $this->untilTag; $txt = ''; $tok = $this->scanner->current(); $caseSensitive = !Elements::isHtml5Element($this->untilTag); while ($tok !== false && !($tok == '<' && $this->sequenceMatches($sequence, $caseSensitive))) { if ($tok == '&') { $txt .= $this->decodeCharacterReference(); $tok = $this->scanner->current(); } else { $txt .= $tok; $tok = $this->scanner->next(); } } $len = strlen($sequence); $this->scanner->consume($len); $len += strlen($this->scanner->whitespace()); if ($this->scanner->current() !== '>') { $this->parseError("Unclosed RCDATA end tag"); } $this->scanner->unconsume($len); $this->events->text($txt); $this->setTextMode(0); return $this->endTag(); }
public function testNormalizeMathMlAttribute() { $tests = array('foo' => 'foo', 'definitionurl' => 'definitionURL', 'BAR' => 'bar'); foreach ($tests as $input => $expected) { $this->assertEquals($expected, Elements::normalizeMathMlAttribute($input)); } }