| 96 | type WalkerCallback = (node: AstNode) => void; |
| 97 | |
| 98 | const transferChildren = ( |
| 99 | parent: AstNode, |
| 100 | nativeParent: Node, |
| 101 | specialElements: SchemaRegExpMap, |
| 102 | nsSanitizer: (el: Element) => void, |
| 103 | decodeComments: boolean |
| 104 | ) => { |
| 105 | const parentName = parent.name; |
| 106 | // Exclude the special elements where the content is RCDATA as their content needs to be parsed instead of being left as plain text |
| 107 | // See: https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments |
| 108 | const isSpecial = parentName in specialElements && parentName !== 'title' && parentName !== 'textarea' && parentName !== 'noscript'; |
| 109 | |
| 110 | const childNodes = nativeParent.childNodes; |
| 111 | for (let ni = 0, nl = childNodes.length; ni < nl; ni++) { |
| 112 | const nativeChild = childNodes[ni]; |
| 113 | const child = new AstNode(nativeChild.nodeName.toLowerCase(), nativeChild.nodeType); |
| 114 | |
| 115 | if (NodeType.isElement(nativeChild)) { |
| 116 | const attributes = nativeChild.attributes; |
| 117 | for (let ai = 0, al = attributes.length; ai < al; ai++) { |
| 118 | const attr = attributes[ai]; |
| 119 | child.attr(attr.name, attr.value); |
| 120 | } |
| 121 | |
| 122 | if (Namespace.isNonHtmlElementRootName(child.name)) { |
| 123 | nsSanitizer(nativeChild); |
| 124 | child.value = nativeChild.innerHTML; |
| 125 | } |
| 126 | } else if (NodeType.isText(nativeChild)) { |
| 127 | child.value = nativeChild.data; |
| 128 | if (isSpecial) { |
| 129 | child.raw = true; |
| 130 | } |
| 131 | } else if (NodeType.isComment(nativeChild)) { |
| 132 | child.value = decodeComments ? KeepHtmlComments.decodeData(nativeChild.data) : nativeChild.data; |
| 133 | } else if (NodeType.isCData(nativeChild) || NodeType.isPi(nativeChild)) { |
| 134 | child.value = nativeChild.data; |
| 135 | } |
| 136 | |
| 137 | if (NodeType.isTemplate(nativeChild)) { |
| 138 | const content = AstNode.create('#text'); |
| 139 | content.value = nativeChild.innerHTML; |
| 140 | content.raw = true; |
| 141 | child.append(content); |
| 142 | } else if (!Namespace.isNonHtmlElementRootName(child.name)) { |
| 143 | transferChildren(child, nativeChild, specialElements, nsSanitizer, decodeComments); |
| 144 | } |
| 145 | |
| 146 | parent.append(child); |
| 147 | } |
| 148 | }; |
| 149 | |
| 150 | const walkTree = (root: AstNode, preprocessors: WalkerCallback[], postprocessors: WalkerCallback[]) => { |
| 151 | const traverseOrder: AstNode[] = []; |