Browse Source

HTMLTemplateElements are now properly created when importing nodes

wrapper-classes
Dustin Wilson 3 years ago
parent
commit
e22e23da0c
  1. 2
      lib/DOMException.php
  2. 56
      lib/Document.php
  3. 6
      lib/Element.php
  4. 6
      lib/traits/ParentNode.php
  5. 4
      tests/cases/TestSerializer.php

2
lib/DOMException.php

@ -27,7 +27,7 @@ class DOMException extends \Exception {
7 => 'Modification not allowed here',
8 => 'Not found error',
12 => 'Syntax error',
100 => 'Argument #%s (\$%s) must be of type %s, %s given',
100 => 'Argument #%s ($%s) must be of type %s, %s given',
101 => 'Failed to set the "outerHTML" property; the element does not have a parent node'
];

56
lib/Document.php

@ -124,7 +124,11 @@ class Document extends AbstractDocument {
public function __construct($source = null, ?string $encoding = null, int $quirksMode = 0) {
// Because we cannot have union types until php 8... :)
if ($source !== null && !$source instanceof \DOMDocument && !is_string($source)) {
throw new DOMException(DOMException::ARGUMENT_TYPE_ERROR, 1, 'source', '\DOMDocument|string|null', gettype($source));
$type = gettype($source);
if ($type === 'object') {
$type = get_class($source);
}
throw new DOMException(DOMException::ARGUMENT_TYPE_ERROR, 1, 'source', '\DOMDocument|string|null', $type);
}
parent::__construct();
@ -214,9 +218,13 @@ class Document extends AbstractDocument {
public function importNode(\DOMNode $node, bool $deep = false) {
$node = parent::importNode($node, $deep);
/*if ($node instanceof \DOMElement) {
$node = $this->convertTemplate($node);
}*/
if ($node instanceof \DOMElement || $node instanceof \DOMDocumentFragment) {
if ($node instanceof \DOMElement && !$node instanceof HTMLTemplateElement && $node->namespaceURI === null && $node->nodeName === 'template') {
$node = $this->convertTemplate($node);
} else {
$this->replaceTemplates($node);
}
}
return $node;
}
@ -233,13 +241,17 @@ class Document extends AbstractDocument {
public function loadDOM(\DOMDocument $source, ?string $encoding = null, int $quirksMode = 0) {
if (!$source instanceof \DOMDocument) {
throw new DOMException(DOMException::ARGUMENT_TYPE_ERROR, 1, 'source', '\DOMDocument', gettype($source));
$type = gettype($source);
if ($type === 'object') {
$type = get_class($source);
}
throw new DOMException(DOMException::ARGUMENT_TYPE_ERROR, 1, 'source', '\DOMDocument', $type);
}
$this->_documentEncoding = $encoding;
$this->_quirksMode = $quirksMode;
// If there are already existing child nodes then remove them before loading the
// If there are already-existing child nodes then remove them before loading the
// DOM.
while ($this->hasChildNodes()) {
$this->removeChild($this->firstChild);
@ -253,13 +265,16 @@ class Document extends AbstractDocument {
}
}
$this->replaceTemplates();
return true;
}
public function loadHTML($source, $options = null, ?string $encoding = null): bool {
if (!is_string($source)) {
throw new DOMException(DOMException::ARGUMENT_TYPE_ERROR, 1, 'source', 'string', gettype($source));
$type = gettype($source);
if ($type === 'object') {
$type = get_class($source);
}
throw new DOMException(DOMException::ARGUMENT_TYPE_ERROR, 1, 'source', 'string', $type);
}
$source = Parser::parse($source, $encoding, null);
@ -788,13 +803,16 @@ class Document extends AbstractDocument {
while ($element->hasChildNodes()) {
$child = $element->firstChild;
if ($child instanceof Element && !$child instanceof HTMLTemplateElement && $child->namespaceURI === null && $child->nodeName === 'template') {
$newChild = $this->convertTemplate($child);
$child->parentNode->removeChild($child);
$child = $newChild;
if ($child instanceof Element) {
if (!$child instanceof HTMLTemplateElement && $child->namespaceURI === null && $child->nodeName === 'template') {
$newChild = $this->convertTemplate($child);
$child->parentNode->removeChild($child);
$child = $newChild;
}
$this->replaceTemplates($child);
}
$this->replaceTemplates($child);
$template->content->appendChild($child);
}
@ -807,7 +825,17 @@ class Document extends AbstractDocument {
private function replaceTemplates(?\DOMNode $node = null) {
if ($node === null) {
$node = $this;
} elseif ($node instanceof HTMLTemplateElement) {
}
if (!$node instanceof \DOMDocument && !$node instanceof \DOMElement && !$node instanceof \DOMDocumentFragment) {
$type = gettype($node);
if ($type === 'object') {
$type = get_class($node);
}
throw new DOMException(DOMException::ARGUMENT_TYPE_ERROR, 1, 'node', '\DOMDocument|\DOMDocumentFragment|\DOMElement|null', $type);
}
if ($node instanceof HTMLTemplateElement) {
$node = $node->content;
}

6
lib/Element.php

@ -52,7 +52,8 @@ class Element extends \DOMElement {
# 2. Let fragment be the result of invoking the fragment parsing algorithm with
# the new value as markup, and with context element.
$fragment = Parser::parseFragment($value, $this->ownerDocument, 'UTF-8', $this);
$fragment = Parser::parseFragment($value, null, 'UTF-8', $this);
$fragment = $this->ownerDocument->importNode($fragment);
# 3. If the context object is a template element, then let context object be the
# template's template contents (a DocumentFragment).
@ -169,7 +170,8 @@ class Element extends \DOMElement {
# 5. Let fragment be the result of invoking the fragment parsing algorithm with
# the new value as markup, and parent as the context element.
$fragment = Parser::parseFragment($value, $this->ownerDocument, 'UTF-8', $parent);
$fragment = Parser::parseFragment($value, null, 'UTF-8', $parent);
$fragment = $this->ownerDocument->importNode($fragment);
# 6. Replace the context object with fragment within the context object's
# parent.

6
lib/traits/ParentNode.php

@ -225,7 +225,11 @@ if (version_compare(\PHP_VERSION, '8.0', '>=')) {
foreach ($nodes as $n) {
// Can't do union types until PHP 8... OTL
if (!$n instanceof \DOMNode && !is_string($n)) {
throw new DOMException(DOMException::ARGUMENT_TYPE_ERROR, 1, 'nodes', '\DOMNode|string', gettype($n));
$type = gettype($n);
if ($type === 'object') {
$type = get_class($n);
}
throw new DOMException(DOMException::ARGUMENT_TYPE_ERROR, 1, 'nodes', '[\DOMNode|string]', $n);
}
$nn = (!is_string($n)) ? $n : $this->ownerDocument->createTextNode($n);

4
tests/cases/TestSerializer.php

@ -7,9 +7,9 @@ declare(strict_types=1);
namespace MensBeam\HTML\DOM\TestCase;
use MensBeam\HTML\DOM\Document;
use MensBeam\HTML\DOM\Parser;
use MensBeam\HTML\Parser;
/**
/**
* @covers \MensBeam\HTML\DOM\Document
* @covers \MensBeam\HTML\DOM\DocumentFragment
* @covers \MensBeam\HTML\DOM\Element

Loading…
Cancel
Save