From 180dcd3e512802242fc4a51be5373c6113ebb3c8 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Thu, 14 Oct 2021 12:27:01 -0400 Subject: [PATCH] Various corrections --- lib/Parser/Serializer.php | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/Parser/Serializer.php b/lib/Parser/Serializer.php index 11b969a..ac749e4 100644 --- a/lib/Parser/Serializer.php +++ b/lib/Parser/Serializer.php @@ -97,24 +97,28 @@ abstract class Serializer { # U+003C LESS-THAN SIGN character (<), a U+002F SOLIDUS # character (/), tagname again, and finally a # U+003E GREATER-THAN SIGN character (>). - if (($n->namespaceURI ?? Parser::HTML_NAMESPACE) === Parser::HTML_NAMESPACE && !in_array($tagName, self::VOID_ELEMENTS)) { + if (($n->namespaceURI ?? Parser::HTML_NAMESPACE) !== Parser::HTML_NAMESPACE || !in_array($tagName, self::VOID_ELEMENTS)) { # If the node is a template element, then let the node instead # be the template element's template contents # (a DocumentFragment node). if ( - $n instanceof \DOMElement - && ($n->namespaceURI ?? Parser::HTML_NAMESPACE) === Parser::HTML_NAMESPACE + ($n->namespaceURI ?? Parser::HTML_NAMESPACE) === Parser::HTML_NAMESPACE && $n->tagName === "template" && property_exists($n, "content") && $n->content instanceof \DOMDocumentFragment ) { - // NOTE: Treat template contents as any other document fragment and just invoke the inner serializer + // NOTE: Treat template content as any other document + // fragment and just invoke the inner serializer $s .= self::serializeInner($n->content).""; } elseif ($n->hasChildNodes()) { + // If the element has children, store its tag name and + // continue the loop with its first child; its end + // tag will be written out further down $stack[] = $tagName; $n = $n->firstChild; continue; } else { + // Otherwise just append the end tag now $s .= ""; } } @@ -175,30 +179,32 @@ abstract class Serializer { } else { throw new Exception(Exception::UNSUPPORTED_NODE_TYPE, [get_class($n)]); } + // If the current node has no more siblings, go up the tree till a + // sibling is found or we've reached the original node while (!$n->nextSibling && $stack) { + // Write out the stored end tag each time we go up the tree $tagName = array_pop($stack); $s .= ""; $n = $n->parentNode; } - if (!$stack && $n->isSameNode($node)) { - break; - } $n = $n->nextSibling; - } while (true); + } while ($stack); // Loop until we have traversed the subtree of the target node in full return $s; } public static function serializeInner(\DOMNode $node): string { # Let s be a string, and initialize it to the empty string. $s = ""; - # If the node serializes as void, then return the empty string. - # If the node is a template element, then let the node instead - # be the template element's template contents - # (a DocumentFragment node). + if ($node instanceof \DOMElement && ($node->namespaceURI ?? Parser::HTML_NAMESPACE) === Parser::HTML_NAMESPACE) { + # If the node serializes as void, then return the empty string. if (!in_array($node->tagName, self::VOID_ELEMENTS)) { return ""; - } elseif ($node->tagName === "template" && property_exists($node, "content") && $node->content instanceof \DOMDocumentFragment) { + } + # If the node is a template element, then let the node instead + # be the template element's template contents + # (a DocumentFragment node). + elseif ($node->tagName === "template" && property_exists($node, "content") && $node->content instanceof \DOMDocumentFragment) { // NOTE: template elements won't necessarily have a content // property because PHP's DOM does not support this natively $node = $node->content;