@remote-dom/polyfill 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +51 -3
  3. package/build/cjs/Attr.cjs +33 -4
  4. package/build/cjs/CharacterData.cjs +10 -0
  5. package/build/cjs/ChildNode.cjs +79 -13
  6. package/build/cjs/Comment.cjs +1 -1
  7. package/build/cjs/CustomElementRegistry.cjs +27 -2
  8. package/build/cjs/CustomEvent.cjs +2 -2
  9. package/build/cjs/Document.cjs +56 -32
  10. package/build/cjs/DocumentFragment.cjs +6 -2
  11. package/build/cjs/Element.cjs +68 -8
  12. package/build/cjs/Event.cjs +29 -27
  13. package/build/cjs/EventTarget.cjs +128 -58
  14. package/build/cjs/HTMLTemplateElement.cjs +1 -0
  15. package/build/cjs/MutationObserver.cjs +167 -1
  16. package/build/cjs/NamedNodeMap.cjs +82 -45
  17. package/build/cjs/Node.cjs +47 -11
  18. package/build/cjs/NodeList.cjs +9 -1
  19. package/build/cjs/ParentNode.cjs +319 -77
  20. package/build/cjs/SVGElement.cjs +1 -1
  21. package/build/cjs/Text.cjs +1 -1
  22. package/build/cjs/Window.cjs +131 -38
  23. package/build/cjs/attribute-reactions.cjs +20 -0
  24. package/build/cjs/constants.cjs +48 -24
  25. package/build/cjs/custom-element-reactions.cjs +52 -0
  26. package/build/cjs/dom-exception.cjs +15 -0
  27. package/build/cjs/hook-effects.cjs +51 -0
  28. package/build/cjs/names.cjs +61 -0
  29. package/build/cjs/selectors.cjs +213 -122
  30. package/build/cjs/serialization.cjs +168 -65
  31. package/build/cjs/shared.cjs +177 -28
  32. package/build/esm/Attr.mjs +34 -5
  33. package/build/esm/CharacterData.mjs +10 -0
  34. package/build/esm/ChildNode.mjs +76 -15
  35. package/build/esm/Comment.mjs +2 -2
  36. package/build/esm/CustomElementRegistry.mjs +27 -2
  37. package/build/esm/CustomEvent.mjs +2 -2
  38. package/build/esm/Document.mjs +60 -35
  39. package/build/esm/DocumentFragment.mjs +7 -3
  40. package/build/esm/Element.mjs +69 -9
  41. package/build/esm/Event.mjs +27 -27
  42. package/build/esm/EventTarget.mjs +130 -60
  43. package/build/esm/HTMLTemplateElement.mjs +2 -1
  44. package/build/esm/MutationObserver.mjs +166 -2
  45. package/build/esm/NamedNodeMap.mjs +83 -46
  46. package/build/esm/Node.mjs +48 -12
  47. package/build/esm/NodeList.mjs +9 -1
  48. package/build/esm/ParentNode.mjs +322 -81
  49. package/build/esm/SVGElement.mjs +2 -2
  50. package/build/esm/Text.mjs +2 -2
  51. package/build/esm/Window.mjs +132 -39
  52. package/build/esm/attribute-reactions.mjs +16 -0
  53. package/build/esm/constants.mjs +28 -23
  54. package/build/esm/custom-element-reactions.mjs +47 -0
  55. package/build/esm/dom-exception.mjs +11 -0
  56. package/build/esm/hook-effects.mjs +46 -0
  57. package/build/esm/names.mjs +54 -0
  58. package/build/esm/selectors.mjs +202 -124
  59. package/build/esm/serialization.mjs +169 -66
  60. package/build/esm/shared.mjs +173 -30
  61. package/build/esnext/Attr.esnext +45 -5
  62. package/build/esnext/CharacterData.esnext +10 -0
  63. package/build/esnext/ChildNode.esnext +84 -15
  64. package/build/esnext/Comment.esnext +2 -2
  65. package/build/esnext/CustomElementRegistry.esnext +42 -0
  66. package/build/esnext/CustomEvent.esnext +2 -2
  67. package/build/esnext/Document.esnext +69 -32
  68. package/build/esnext/DocumentFragment.esnext +6 -2
  69. package/build/esnext/Element.esnext +78 -9
  70. package/build/esnext/Event.esnext +36 -37
  71. package/build/esnext/EventTarget.esnext +133 -61
  72. package/build/esnext/HTMLTemplateElement.esnext +3 -1
  73. package/build/esnext/MutationObserver.esnext +163 -2
  74. package/build/esnext/NamedNodeMap.esnext +110 -42
  75. package/build/esnext/Node.esnext +50 -12
  76. package/build/esnext/NodeList.esnext +1 -1
  77. package/build/esnext/ParentNode.esnext +352 -79
  78. package/build/esnext/SVGElement.esnext +2 -2
  79. package/build/esnext/Text.esnext +2 -2
  80. package/build/esnext/Window.esnext +120 -16
  81. package/build/esnext/attribute-reactions.esnext +21 -0
  82. package/build/esnext/constants.esnext +34 -21
  83. package/build/esnext/custom-element-reactions.esnext +49 -0
  84. package/build/esnext/dom-exception.esnext +11 -0
  85. package/build/esnext/hook-effects.esnext +46 -0
  86. package/build/esnext/names.esnext +61 -0
  87. package/build/esnext/selectors.esnext +202 -100
  88. package/build/esnext/serialization.esnext +171 -48
  89. package/build/esnext/shared.esnext +181 -34
  90. package/build/tsconfig.tsbuildinfo +1 -1
  91. package/build/typescript/Attr.d.ts +6 -4
  92. package/build/typescript/Attr.d.ts.map +1 -1
  93. package/build/typescript/CharacterData.d.ts.map +1 -1
  94. package/build/typescript/ChildNode.d.ts +5 -0
  95. package/build/typescript/ChildNode.d.ts.map +1 -1
  96. package/build/typescript/ClipboardEvent.d.ts.map +1 -1
  97. package/build/typescript/Comment.d.ts +2 -2
  98. package/build/typescript/Comment.d.ts.map +1 -1
  99. package/build/typescript/CustomElementRegistry.d.ts +1 -0
  100. package/build/typescript/CustomElementRegistry.d.ts.map +1 -1
  101. package/build/typescript/CustomEvent.d.ts.map +1 -1
  102. package/build/typescript/Document.d.ts +10 -5
  103. package/build/typescript/Document.d.ts.map +1 -1
  104. package/build/typescript/DocumentFragment.d.ts +2 -1
  105. package/build/typescript/DocumentFragment.d.ts.map +1 -1
  106. package/build/typescript/Element.d.ts +16 -7
  107. package/build/typescript/Element.d.ts.map +1 -1
  108. package/build/typescript/ErrorEvent.d.ts.map +1 -1
  109. package/build/typescript/Event.d.ts +9 -10
  110. package/build/typescript/Event.d.ts.map +1 -1
  111. package/build/typescript/EventTarget.d.ts +20 -3
  112. package/build/typescript/EventTarget.d.ts.map +1 -1
  113. package/build/typescript/FocusEvent.d.ts.map +1 -1
  114. package/build/typescript/HTMLTemplateElement.d.ts.map +1 -1
  115. package/build/typescript/MutationObserver.d.ts +42 -0
  116. package/build/typescript/MutationObserver.d.ts.map +1 -1
  117. package/build/typescript/NamedNodeMap.d.ts +5 -3
  118. package/build/typescript/NamedNodeMap.d.ts.map +1 -1
  119. package/build/typescript/Node.d.ts +4 -3
  120. package/build/typescript/Node.d.ts.map +1 -1
  121. package/build/typescript/NodeList.d.ts +3 -2
  122. package/build/typescript/NodeList.d.ts.map +1 -1
  123. package/build/typescript/ParentNode.d.ts +29 -10
  124. package/build/typescript/ParentNode.d.ts.map +1 -1
  125. package/build/typescript/PromiseRejectionEvent.d.ts.map +1 -1
  126. package/build/typescript/SVGElement.d.ts +1 -1
  127. package/build/typescript/SVGElement.d.ts.map +1 -1
  128. package/build/typescript/Text.d.ts +1 -1
  129. package/build/typescript/Text.d.ts.map +1 -1
  130. package/build/typescript/ToggleEvent.d.ts.map +1 -1
  131. package/build/typescript/Window.d.ts +5 -1
  132. package/build/typescript/Window.d.ts.map +1 -1
  133. package/build/typescript/attribute-reactions.d.ts +4 -0
  134. package/build/typescript/attribute-reactions.d.ts.map +1 -0
  135. package/build/typescript/constants.d.ts +27 -18
  136. package/build/typescript/constants.d.ts.map +1 -1
  137. package/build/typescript/custom-element-reactions.d.ts +6 -0
  138. package/build/typescript/custom-element-reactions.d.ts.map +1 -0
  139. package/build/typescript/dom-exception.d.ts +2 -0
  140. package/build/typescript/dom-exception.d.ts.map +1 -0
  141. package/build/typescript/extensions.d.ts +4 -0
  142. package/build/typescript/extensions.d.ts.map +1 -0
  143. package/build/typescript/hook-effects.d.ts +6 -0
  144. package/build/typescript/hook-effects.d.ts.map +1 -0
  145. package/build/typescript/hooks.d.ts +3 -3
  146. package/build/typescript/hooks.d.ts.map +1 -1
  147. package/build/typescript/index.d.ts +1 -0
  148. package/build/typescript/index.d.ts.map +1 -1
  149. package/build/typescript/names.d.ts +11 -0
  150. package/build/typescript/names.d.ts.map +1 -0
  151. package/build/typescript/selectors.d.ts +21 -22
  152. package/build/typescript/selectors.d.ts.map +1 -1
  153. package/build/typescript/serialization.d.ts.map +1 -1
  154. package/build/typescript/shared.d.ts +10 -0
  155. package/build/typescript/shared.d.ts.map +1 -1
  156. package/build/typescript/tests/ChildNode.test.d.ts +2 -0
  157. package/build/typescript/tests/ChildNode.test.d.ts.map +1 -0
  158. package/build/typescript/tests/MutationObserver.test.d.ts +2 -0
  159. package/build/typescript/tests/MutationObserver.test.d.ts.map +1 -0
  160. package/build/typescript/tests/adopt-inserted-subtrees.test.d.ts +2 -0
  161. package/build/typescript/tests/adopt-inserted-subtrees.test.d.ts.map +1 -0
  162. package/build/typescript/tests/attr-mutation.test.d.ts +2 -0
  163. package/build/typescript/tests/attr-mutation.test.d.ts.map +1 -0
  164. package/build/typescript/tests/child-node-before-after.test.d.ts +2 -0
  165. package/build/typescript/tests/child-node-before-after.test.d.ts.map +1 -0
  166. package/build/typescript/tests/child-node-replace-with.test.d.ts +2 -0
  167. package/build/typescript/tests/child-node-replace-with.test.d.ts.map +1 -0
  168. package/build/typescript/tests/clone-import-namespaces.test.d.ts +2 -0
  169. package/build/typescript/tests/clone-import-namespaces.test.d.ts.map +1 -0
  170. package/build/typescript/tests/constants.test.d.ts +2 -0
  171. package/build/typescript/tests/constants.test.d.ts.map +1 -0
  172. package/build/typescript/tests/create-element-namespaces.test.d.ts +2 -0
  173. package/build/typescript/tests/create-element-namespaces.test.d.ts.map +1 -0
  174. package/build/typescript/tests/create-text-node.test.d.ts +2 -0
  175. package/build/typescript/tests/create-text-node.test.d.ts.map +1 -0
  176. package/build/typescript/tests/custom-element-reactions.test.d.ts +2 -0
  177. package/build/typescript/tests/custom-element-reactions.test.d.ts.map +1 -0
  178. package/build/typescript/tests/custom-element-registry.test.d.ts +2 -0
  179. package/build/typescript/tests/custom-element-registry.test.d.ts.map +1 -0
  180. package/build/typescript/tests/custom-event.test.d.ts +2 -0
  181. package/build/typescript/tests/custom-event.test.d.ts.map +1 -0
  182. package/build/typescript/tests/document-clone-import-contract.test.d.ts +2 -0
  183. package/build/typescript/tests/document-clone-import-contract.test.d.ts.map +1 -0
  184. package/build/typescript/tests/document.test.d.ts +2 -0
  185. package/build/typescript/tests/document.test.d.ts.map +1 -0
  186. package/build/typescript/tests/dom-mutation-selector-errors.test.d.ts +2 -0
  187. package/build/typescript/tests/dom-mutation-selector-errors.test.d.ts.map +1 -0
  188. package/build/typescript/tests/event-dispatch.test.d.ts +2 -0
  189. package/build/typescript/tests/event-dispatch.test.d.ts.map +1 -0
  190. package/build/typescript/tests/event-target.test.d.ts +2 -0
  191. package/build/typescript/tests/event-target.test.d.ts.map +1 -0
  192. package/build/typescript/tests/event.test.d.ts +2 -0
  193. package/build/typescript/tests/event.test.d.ts.map +1 -0
  194. package/build/typescript/tests/extensions.test.d.ts +2 -0
  195. package/build/typescript/tests/extensions.test.d.ts.map +1 -0
  196. package/build/typescript/tests/get-elements-by-tag-name.test.d.ts +2 -0
  197. package/build/typescript/tests/get-elements-by-tag-name.test.d.ts.map +1 -0
  198. package/build/typescript/tests/getElementsByClassName.test.d.ts +2 -0
  199. package/build/typescript/tests/getElementsByClassName.test.d.ts.map +1 -0
  200. package/build/typescript/tests/hooks.test.d.ts +2 -0
  201. package/build/typescript/tests/hooks.test.d.ts.map +1 -0
  202. package/build/typescript/tests/inner-html-parsing.test.d.ts +2 -0
  203. package/build/typescript/tests/inner-html-parsing.test.d.ts.map +1 -0
  204. package/build/typescript/tests/is-default-namespace.test.d.ts +2 -0
  205. package/build/typescript/tests/is-default-namespace.test.d.ts.map +1 -0
  206. package/build/typescript/tests/name-and-namespace-normalization.test.d.ts +2 -0
  207. package/build/typescript/tests/name-and-namespace-normalization.test.d.ts.map +1 -0
  208. package/build/typescript/tests/named-node-map.test.d.ts +2 -0
  209. package/build/typescript/tests/named-node-map.test.d.ts.map +1 -0
  210. package/build/typescript/tests/namespaced-attribute-reactions.test.d.ts +2 -0
  211. package/build/typescript/tests/namespaced-attribute-reactions.test.d.ts.map +1 -0
  212. package/build/typescript/tests/node.test.d.ts +2 -0
  213. package/build/typescript/tests/node.test.d.ts.map +1 -0
  214. package/build/typescript/tests/parent-node-mutation-return-values.test.d.ts +2 -0
  215. package/build/typescript/tests/parent-node-mutation-return-values.test.d.ts.map +1 -0
  216. package/build/typescript/tests/parent-node-mutation-validation.test.d.ts +2 -0
  217. package/build/typescript/tests/parent-node-mutation-validation.test.d.ts.map +1 -0
  218. package/build/typescript/tests/parent-node.test.d.ts +2 -0
  219. package/build/typescript/tests/parent-node.test.d.ts.map +1 -0
  220. package/build/typescript/tests/serialization-template.test.d.ts +2 -0
  221. package/build/typescript/tests/serialization-template.test.d.ts.map +1 -0
  222. package/build/typescript/tests/slot-attribute.test.d.ts +2 -0
  223. package/build/typescript/tests/slot-attribute.test.d.ts.map +1 -0
  224. package/build/typescript/tests/text-content.test.d.ts +2 -0
  225. package/build/typescript/tests/text-content.test.d.ts.map +1 -0
  226. package/build/typescript/tests/toggle-attribute.test.d.ts +2 -0
  227. package/build/typescript/tests/toggle-attribute.test.d.ts.map +1 -0
  228. package/build/typescript/tests/wide-tree-traversal.test.d.ts +2 -0
  229. package/build/typescript/tests/wide-tree-traversal.test.d.ts.map +1 -0
  230. package/build/typescript/tests/window-set-global.test.d.ts +2 -0
  231. package/build/typescript/tests/window-set-global.test.d.ts.map +1 -0
  232. package/package.json +1 -1
  233. package/source/Attr.ts +60 -8
  234. package/source/CharacterData.ts +13 -0
  235. package/source/ChildNode.ts +107 -14
  236. package/source/Comment.ts +2 -2
  237. package/source/CustomElementRegistry.ts +56 -0
  238. package/source/CustomEvent.ts +2 -2
  239. package/source/Document.ts +104 -38
  240. package/source/DocumentFragment.ts +12 -2
  241. package/source/Element.ts +129 -14
  242. package/source/Event.ts +34 -32
  243. package/source/EventTarget.ts +203 -79
  244. package/source/HTMLTemplateElement.ts +2 -1
  245. package/source/MutationObserver.ts +279 -1
  246. package/source/NamedNodeMap.ts +141 -60
  247. package/source/Node.ts +70 -14
  248. package/source/NodeList.ts +13 -3
  249. package/source/ParentNode.ts +500 -88
  250. package/source/SVGElement.ts +2 -2
  251. package/source/Text.ts +2 -2
  252. package/source/Window.ts +156 -17
  253. package/source/attribute-reactions.ts +32 -0
  254. package/source/constants.ts +40 -17
  255. package/source/custom-element-reactions.ts +64 -0
  256. package/source/dom-exception.ts +14 -0
  257. package/source/extensions.ts +4 -0
  258. package/source/hook-effects.ts +56 -0
  259. package/source/hooks.ts +11 -3
  260. package/source/index.ts +1 -0
  261. package/source/names.ts +94 -0
  262. package/source/selectors.ts +301 -138
  263. package/source/serialization.ts +224 -66
  264. package/source/shared.ts +269 -40
  265. package/source/tests/ChildNode.test.ts +178 -0
  266. package/source/tests/MutationObserver.test.ts +303 -0
  267. package/source/tests/adopt-inserted-subtrees.test.ts +584 -0
  268. package/source/tests/attr-mutation.test.ts +112 -0
  269. package/source/tests/child-node-before-after.test.ts +421 -0
  270. package/source/tests/child-node-replace-with.test.ts +251 -0
  271. package/source/tests/clone-import-namespaces.test.ts +365 -0
  272. package/source/tests/constants.test.ts +46 -0
  273. package/source/tests/create-element-namespaces.test.ts +142 -0
  274. package/source/tests/create-text-node.test.ts +38 -0
  275. package/source/tests/custom-element-reactions.test.ts +600 -0
  276. package/source/tests/custom-element-registry.test.ts +137 -0
  277. package/source/tests/custom-event.test.ts +26 -0
  278. package/source/tests/document-clone-import-contract.test.ts +77 -0
  279. package/source/tests/document.test.ts +122 -0
  280. package/source/tests/dom-mutation-selector-errors.test.ts +484 -0
  281. package/source/tests/event-dispatch.test.ts +270 -0
  282. package/source/tests/event-target.test.ts +208 -0
  283. package/source/tests/event.test.ts +98 -0
  284. package/source/tests/extensions.test.ts +159 -0
  285. package/source/tests/get-elements-by-tag-name.test.ts +79 -0
  286. package/source/tests/getElementsByClassName.test.ts +109 -0
  287. package/source/tests/hooks.test.ts +43 -0
  288. package/source/tests/inner-html-parsing.test.ts +461 -0
  289. package/source/tests/is-default-namespace.test.ts +111 -0
  290. package/source/tests/name-and-namespace-normalization.test.ts +319 -0
  291. package/source/tests/named-node-map.test.ts +122 -0
  292. package/source/tests/namespaced-attribute-reactions.test.ts +141 -0
  293. package/source/tests/node.test.ts +56 -0
  294. package/source/tests/parent-node-mutation-return-values.test.ts +63 -0
  295. package/source/tests/parent-node-mutation-validation.test.ts +362 -0
  296. package/source/tests/parent-node.test.ts +169 -0
  297. package/source/tests/selectors.test.ts +533 -22
  298. package/source/tests/serialization-template.test.ts +232 -0
  299. package/source/tests/slot-attribute.test.ts +133 -0
  300. package/source/tests/text-content.test.ts +440 -0
  301. package/source/tests/toggle-attribute.test.ts +113 -0
  302. package/source/tests/wide-tree-traversal.test.ts +699 -0
  303. package/source/tests/window-set-global.test.ts +321 -0
  304. package/tsconfig.json +1 -1
@@ -1,9 +1,53 @@
1
- import { CHILD, NEXT, PARENT, PREV } from './constants.esnext';
1
+ import { CHILD, asciiLowercase, NEXT, splitOnASCIIWhitespace, HTML_NAMESPACE, PARENT, PREV } from './constants.esnext';
2
2
  import { isElementNode } from './shared.esnext';
3
+ import { NodeList } from './NodeList.esnext';
4
+ import { createDOMException } from './dom-exception.esnext';
3
5
 
4
- const ELEMENT_SELECTOR_TEST = /[a-z]/;
6
+ const COMBINATOR_DESCENDANT = 0;
7
+ const COMBINATOR_CHILD = 1;
8
+ const COMBINATOR_SIBLING = 2;
9
+ const COMBINATOR_ADJACENT = 3;
10
+ const COMBINATOR_INNER = 4;
11
+ const MATCHER_UNKNOWN = 0;
12
+ const MATCHER_ELEMENT = 1;
13
+ const MATCHER_ID = 2;
14
+ const MATCHER_CLASS = 3;
15
+ const MATCHER_ATTRIBUTE = 4;
16
+ const MATCHER_PSEUDO = 5;
17
+ const MATCHER_FUNCTION = 6;
18
+ const MATCHER_SCOPE = 7;
19
+ const SUPPORTED_IDENTIFIER_TEST = /^(?:--|-?[A-Za-z_\u0080-\u{10FFFF}])[A-Za-z0-9_\u0080-\u{10FFFF}-]*$/u;
20
+ function readFunctionArgument(selector, start) {
21
+ let depth = 1;
22
+ let quote = null;
23
+ for (let index = start; index < selector.length; index++) {
24
+ const character = selector[index];
25
+ if (quote) {
26
+ if (character === "\\") {
27
+ index++;
28
+ } else if (character === quote) {
29
+ quote = null;
30
+ }
31
+ continue;
32
+ }
33
+ if (character === '"' || character === "'") {
34
+ quote = character;
35
+ } else if (character === "(") {
36
+ depth++;
37
+ } else if (character === ")" && --depth === 0) {
38
+ return [selector.slice(start, index), index + 1];
39
+ }
40
+ }
41
+ return [selector.slice(start), selector.length];
42
+ }
43
+ function throwSelectorSyntaxError(selector) {
44
+ throw createDOMException(
45
+ `Invalid or unsupported selector: "${selector}"`,
46
+ "SyntaxError"
47
+ );
48
+ }
5
49
  function querySelector(within, selector) {
6
- const parts = parseSelector(selector);
50
+ const parts = typeof selector === "string" ? parseSelector(selector) : [{ combinator: COMBINATOR_INNER, matchers: selector }];
7
51
  let result = null;
8
52
  const child = within[CHILD];
9
53
  if (child && parts[0].matchers.length) {
@@ -15,8 +59,8 @@ function querySelector(within, selector) {
15
59
  return result;
16
60
  }
17
61
  function querySelectorAll(within, selector) {
18
- const parts = parseSelector(selector);
19
- const results = [];
62
+ const parts = typeof selector === "string" ? parseSelector(selector) : [{ combinator: COMBINATOR_INNER, matchers: selector }];
63
+ const results = new NodeList();
20
64
  const child = within[CHILD];
21
65
  if (child && parts[0].matchers.length) {
22
66
  walkNodesForSelector(child, parts, (node) => {
@@ -25,163 +69,221 @@ function querySelectorAll(within, selector) {
25
69
  }
26
70
  return results;
27
71
  }
28
- function parseSelector(selector) {
29
- let part = { combinator: 4 /* Inner */, matchers: [] };
72
+ function parseSelector(selector, insideHas = false, allowLeadingCombinator = false) {
73
+ let part = { combinator: COMBINATOR_INNER, matchers: [] };
30
74
  const parts = [part];
31
- const tokenizer = /\s*?([>\s+~]?)\s*?(?:(?:\[\s*([^\]=]+)(?:=(['"])(.*?)\3)?\s*\])|([#.]?)([^\s#.[>:+~]+)|:(\w+)(?:\((.*?)\))?)/gi;
75
+ const tokenizer = /[\t\n\f\r ]*?([>\t\n\f\r +~]?)[\t\n\f\r ]*?(?:(?:\[[\t\n\f\r ]*([^\]=\t\n\f\r ]+)[\t\n\f\r ]*(?:=[\t\n\f\r ]*(?:(['"])(.*?)\3|([^\]\t\n\f\r ]+)))?[\t\n\f\r ]*(?:\]|$))|([#.]?)([^\t\n\f\r #.[>:+~()]+)|:(\w+)(\()?)/gi;
76
+ const normalizedSelector = selector.replace(
77
+ /^[\t\n\f\r ]+|[\t\n\f\r ]+$/g,
78
+ ""
79
+ );
80
+ if (normalizedSelector === "") throwSelectorSyntaxError(selector);
81
+ let consumed = 0;
32
82
  let token;
33
- while (token = tokenizer.exec(selector)) {
83
+ while (token = tokenizer.exec(normalizedSelector)) {
84
+ if (token.index !== consumed) throwSelectorSyntaxError(selector);
34
85
  if (token[1]) {
35
- if (token[1] === ">") part.combinator = 1 /* Child */;
36
- else if (token[1] === "+") part.combinator = 3 /* Adjacent */;
37
- else if (token[1] === "~") part.combinator = 2 /* Sibling */;
38
- else part.combinator = 0 /* Descendant */;
39
- part = { combinator: 4 /* Inner */, matchers: [] };
86
+ if (part.matchers.length === 0 && !(allowLeadingCombinator && parts.length === 1)) {
87
+ throwSelectorSyntaxError(selector);
88
+ }
89
+ if (token[1] === ">") part.combinator = COMBINATOR_CHILD;
90
+ else if (token[1] === "+") part.combinator = COMBINATOR_ADJACENT;
91
+ else if (token[1] === "~") part.combinator = COMBINATOR_SIBLING;
92
+ else part.combinator = COMBINATOR_DESCENDANT;
93
+ part = { combinator: COMBINATOR_INNER, matchers: [] };
40
94
  parts.push(part);
41
95
  }
42
- let type = 0 /* Unknown */;
96
+ const name = token[8] ? asciiLowercase(token[8]) : token[2] || token[7];
97
+ const isTypeSelector = token[7] != null && !token[6];
98
+ if (isTypeSelector && part.matchers.length > 0) {
99
+ throwSelectorSyntaxError(selector);
100
+ }
101
+ let type;
102
+ let value = token[4] ?? token[5] ?? token[7];
43
103
  if (token[2]) {
44
- type = 4 /* Attribute */;
45
- } else if (token[5]) {
46
- type = token[5] === "#" ? 2 /* Id */ : 3 /* Class */;
47
- } else if (token[7]) {
48
- type = token[8] == null ? 5 /* Pseudo */ : 6 /* Function */;
104
+ if (!SUPPORTED_IDENTIFIER_TEST.test(name)) {
105
+ throwSelectorSyntaxError(selector);
106
+ }
107
+ const unquotedValue = token[5];
108
+ const openingQuote = unquotedValue?.[0];
109
+ if (token[3] == null && (openingQuote === '"' || openingQuote === "'")) {
110
+ const valueOffset = token[0].lastIndexOf(unquotedValue);
111
+ value = normalizedSelector.slice(token.index + valueOffset + 1);
112
+ tokenizer.lastIndex = normalizedSelector.length;
113
+ } else if (unquotedValue != null && !SUPPORTED_IDENTIFIER_TEST.test(unquotedValue)) {
114
+ throwSelectorSyntaxError(selector);
115
+ }
116
+ type = MATCHER_ATTRIBUTE;
49
117
  } else if (token[6]) {
50
- if (token[6] === "*") {
51
- type = 0 /* Unknown */;
52
- } else if (ELEMENT_SELECTOR_TEST.test(token[6])) {
53
- type = 1 /* Element */;
118
+ if (!SUPPORTED_IDENTIFIER_TEST.test(name)) {
119
+ throwSelectorSyntaxError(selector);
54
120
  }
121
+ type = token[6] === "#" ? MATCHER_ID : MATCHER_CLASS;
122
+ } else if (token[8]) {
123
+ type = token[9] == null ? MATCHER_PSEUDO : MATCHER_FUNCTION;
124
+ } else if (token[7] === "*") {
125
+ type = MATCHER_UNKNOWN;
126
+ } else if (token[7] && SUPPORTED_IDENTIFIER_TEST.test(token[7])) {
127
+ type = MATCHER_ELEMENT;
128
+ } else {
129
+ throwSelectorSyntaxError(selector);
55
130
  }
56
- part.matchers.push({
57
- type,
58
- name: token[2] || token[6] || token[7],
59
- value: token[4] ?? token[6] ?? token[8]
60
- });
131
+ if (token[9]) {
132
+ [value, tokenizer.lastIndex] = readFunctionArgument(
133
+ normalizedSelector,
134
+ tokenizer.lastIndex
135
+ );
136
+ if (name !== "has" && name !== "not") {
137
+ throwSelectorSyntaxError(selector);
138
+ }
139
+ if (name === "has" && insideHas) throwSelectorSyntaxError(selector);
140
+ parseSelector(value, insideHas || name === "has", name === "has");
141
+ } else if (type === MATCHER_PSEUDO) {
142
+ throwSelectorSyntaxError(selector);
143
+ }
144
+ part.matchers.push({ type, name, value });
145
+ consumed = tokenizer.lastIndex;
146
+ }
147
+ if (consumed !== normalizedSelector.length || part.matchers.length === 0) {
148
+ throwSelectorSyntaxError(selector);
61
149
  }
62
150
  return parts;
63
151
  }
64
152
  function matchesSelector(element, selector) {
65
153
  const parsed = parseSelector(selector);
66
- let part;
67
- while (part = parsed.pop()) {
68
- if (!matchesSelectorPart(element, part)) return false;
69
- }
70
- return true;
154
+ return parsed[0]?.matchers.length ? matchesSelectorRecursive(element, parsed) : false;
71
155
  }
72
- function walkNodesForSelector(node, parts, callback) {
73
- if (isElementNode(node)) {
74
- if (matchesSelectorRecursive(node, parts)) {
75
- if (callback(node) === false) return false;
76
- }
77
- const child = node[CHILD];
78
- if (child && walkNodesForSelector(child, parts, callback) === false) {
156
+ function matchesRelativeSelector(scope, selector) {
157
+ const parts = parseSelector(selector, true, true);
158
+ const first = parts[0];
159
+ if (parts.length === 1 && first.matchers.length === 0) return false;
160
+ let leadingCombinator = COMBINATOR_DESCENDANT;
161
+ const scopeMatcher = { type: MATCHER_SCOPE, name: ":scope" };
162
+ if (first.matchers.length === 0) {
163
+ leadingCombinator = first.combinator;
164
+ first.matchers.push(scopeMatcher);
165
+ } else {
166
+ parts.unshift({
167
+ combinator: COMBINATOR_DESCENDANT,
168
+ matchers: [scopeMatcher]
169
+ });
170
+ }
171
+ if (parts.some(({ matchers }) => matchers.length === 0)) return false;
172
+ const root = leadingCombinator === COMBINATOR_ADJACENT || leadingCombinator === COMBINATOR_SIBLING ? scope[NEXT] : scope[CHILD];
173
+ if (!root) return false;
174
+ let matched = false;
175
+ walkNodesForSelector(
176
+ root,
177
+ parts,
178
+ () => {
179
+ matched = true;
79
180
  return false;
181
+ },
182
+ scope
183
+ );
184
+ return matched;
185
+ }
186
+ function walkNodesForSelector(node, parts, callback, scope) {
187
+ const pendingSiblings = [];
188
+ let current = node;
189
+ while (current) {
190
+ if (isElementNode(current)) {
191
+ if (matchesSelectorRecursive(current, parts, scope)) {
192
+ if (callback(current) === false) return false;
193
+ }
194
+ const child = current[CHILD];
195
+ if (child) {
196
+ const sibling = current[NEXT];
197
+ if (sibling) pendingSiblings.push(sibling);
198
+ current = child;
199
+ continue;
200
+ }
80
201
  }
81
- }
82
- const next = node[NEXT];
83
- if (next && walkNodesForSelector(next, parts, callback) === false) {
84
- return false;
202
+ current = current[NEXT] ?? pendingSiblings.pop() ?? null;
85
203
  }
86
204
  return true;
87
205
  }
88
- function matchesSelectorRecursive(element, parts) {
206
+ function matchesSelectorRecursive(element, parts, scope) {
89
207
  const { combinator, matchers } = parts[parts.length - 1];
90
- if (combinator === 4 /* Inner */) {
91
- if (!matchesSelectorMatcher(element, matchers)) return false;
208
+ if (combinator === COMBINATOR_INNER) {
209
+ if (!matchesSelectorMatcher(element, matchers, scope)) return false;
92
210
  const pp = parts.slice(0, -1);
93
- return pp.length === 0 || matchesSelectorRecursive(element, pp);
211
+ return pp.length === 0 || matchesSelectorRecursive(element, pp, scope);
94
212
  }
95
- const link = combinator === 1 /* Child */ || combinator === 0 /* Descendant */ ? PARENT : PREV;
213
+ const link = combinator === COMBINATOR_CHILD || combinator === COMBINATOR_DESCENDANT ? PARENT : PREV;
96
214
  let ref = element[link];
97
215
  if (!ref) return false;
98
- if (combinator === 0 /* Descendant */ || combinator === 2 /* Sibling */) {
216
+ if (combinator === COMBINATOR_DESCENDANT || combinator === COMBINATOR_SIBLING) {
99
217
  while (ref) {
100
- if (isElementNode(ref) && matchesSelectorMatcher(ref, matchers)) {
218
+ if (isElementNode(ref) && matchesSelectorMatcher(ref, matchers, scope)) {
101
219
  const pp = parts.slice(0, -1);
102
220
  if (pp.length === 0) return true;
103
- if (matchesSelectorRecursive(element, pp)) return true;
221
+ if (matchesSelectorRecursive(ref, pp, scope)) return true;
104
222
  }
105
223
  ref = ref[link];
106
224
  }
107
225
  return false;
108
226
  } else {
109
- if (combinator === 3 /* Adjacent */ && !isElementNode(ref)) {
227
+ if (combinator === COMBINATOR_ADJACENT && !isElementNode(ref)) {
110
228
  while (ref && !isElementNode(ref)) {
111
229
  ref = ref[link];
112
230
  }
113
231
  if (!ref) return false;
114
232
  }
115
- if (!isElementNode(ref) || !matchesSelectorMatcher(ref, matchers)) {
233
+ if (!isElementNode(ref) || !matchesSelectorMatcher(ref, matchers, scope)) {
116
234
  return false;
117
235
  }
118
236
  const pp = parts.slice(0, -1);
119
- return pp.length === 0 || matchesSelectorRecursive(element, pp);
237
+ return pp.length === 0 || matchesSelectorRecursive(ref, pp, scope);
120
238
  }
121
239
  }
122
- function matchesSelectorPart(element, { combinator, matchers }) {
123
- if (combinator === 4 /* Inner */) {
124
- return matchesSelectorMatcher(element, matchers);
125
- }
126
- const link = combinator === 1 /* Child */ || combinator === 0 /* Descendant */ ? PARENT : PREV;
127
- let ref = element[link];
128
- if (!ref) return false;
129
- if (combinator === 3 /* Adjacent */ && !isElementNode(ref)) {
130
- while (ref && !isElementNode(ref)) {
131
- ref = ref[link];
132
- }
133
- if (!ref) return false;
134
- }
135
- if (!isElementNode(ref) || !matchesSelectorMatcher(ref, matchers)) {
136
- return false;
137
- }
138
- if (combinator === 0 /* Descendant */ || combinator === 2 /* Sibling */) {
139
- while (ref = ref[link]) {
140
- if (isElementNode(ref) && matchesSelectorMatcher(ref, matchers))
141
- return true;
142
- }
143
- }
144
- return true;
240
+ function getSelectorAttribute(element, name) {
241
+ return element.getAttributeNS(
242
+ null,
243
+ element.namespaceURI === HTML_NAMESPACE ? asciiLowercase(name) : name
244
+ );
145
245
  }
146
- function matchesSelectorMatcher(element, matcher) {
246
+ function matchesSelectorMatcher(element, matcher, scope) {
147
247
  if (!element) return false;
148
248
  if (Array.isArray(matcher)) {
149
249
  for (const single of matcher) {
150
- if (matchesSelectorMatcher(element, single) === false) return false;
250
+ if (matchesSelectorMatcher(element, single, scope) === false) {
251
+ return false;
252
+ }
151
253
  }
152
254
  return true;
153
255
  }
154
256
  const { type, name, value } = matcher;
155
257
  switch (type) {
156
- case 0 /* Unknown */:
258
+ case MATCHER_UNKNOWN:
157
259
  return name === "*";
158
260
  // Universal selector
159
- case 1 /* Element */:
160
- return element.localName === name;
161
- case 2 /* Id */:
162
- return element.getAttribute("id") === name;
163
- case 3 /* Class */:
164
- const classAttr = element.getAttribute("class");
261
+ case MATCHER_ELEMENT:
262
+ return element.namespaceURI === HTML_NAMESPACE ? element.localName === asciiLowercase(name) : element.localName === name;
263
+ case MATCHER_ID:
264
+ return getSelectorAttribute(element, "id") === name;
265
+ case MATCHER_CLASS:
266
+ const classAttr = getSelectorAttribute(element, "class");
165
267
  if (!classAttr) return false;
166
- return classAttr.split(/\s+/).includes(name);
167
- case 4 /* Attribute */:
168
- return value == null ? element.hasAttribute(name) : element.getAttribute(name) === value;
169
- case 5 /* Pseudo */:
170
- switch (name) {
171
- default:
172
- throw Error(`Pseudo :${name} not implemented`);
173
- }
174
- case 6 /* Function */:
268
+ return splitOnASCIIWhitespace(classAttr).includes(name);
269
+ case MATCHER_ATTRIBUTE:
270
+ const attribute = getSelectorAttribute(element, name);
271
+ return value == null ? attribute != null : attribute === value;
272
+ case MATCHER_SCOPE:
273
+ return element === scope;
274
+ case MATCHER_PSEUDO:
275
+ throwSelectorSyntaxError(`:${name}`);
276
+ case MATCHER_FUNCTION:
175
277
  switch (name) {
176
278
  case "has":
177
- return matchesSelector(element, value || "");
279
+ return matchesRelativeSelector(element, value || "");
178
280
  case "not":
179
281
  return !matchesSelector(element, value || "");
180
282
  default:
181
- throw Error(`Function :${name}(${value}) not implemented`);
283
+ throwSelectorSyntaxError(`:${name}(${value})`);
182
284
  }
183
285
  }
184
286
  return false;
185
287
  }
186
288
 
187
- export { parseSelector, querySelector, querySelectorAll };
289
+ export { COMBINATOR_ADJACENT, COMBINATOR_CHILD, COMBINATOR_DESCENDANT, COMBINATOR_INNER, COMBINATOR_SIBLING, MATCHER_ATTRIBUTE, MATCHER_CLASS, MATCHER_ELEMENT, MATCHER_FUNCTION, MATCHER_ID, MATCHER_PSEUDO, MATCHER_SCOPE, MATCHER_UNKNOWN, parseSelector, querySelector, querySelectorAll };
@@ -1,76 +1,199 @@
1
- import { CHILD, NEXT, NodeType, DATA, NAME, ATTRIBUTES, VALUE } from './constants.esnext';
1
+ import { CHILD, asciiLowercase, NS, SVG_NAMESPACE, HTML_NAMESPACE, CREATE_ELEMENT, NAME, NEXT, NODE_TYPE_COMMENT, DATA, NODE_TYPE_TEXT, NODE_TYPE_ELEMENT, ATTRIBUTES, VALUE, CONTENT } from './constants.esnext';
2
2
 
3
- const elementTokenizer = /(?:<([a-z][a-z0-9-:]*)((?:[\s]+[^<>'"=\s]+(?:=(['"])[^]*?\3|=[^>'"\s]*|))*)[\s]*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|<!--(.*?)-->|([^&<>]+))/gi;
4
- const attributeTokenizer = /\s([^<>'"=\n\s]+)(?:=(["'])([\s\S]*?)\2|=([^>'"\n\s]*)|)/g;
3
+ const CHARACTER_REFERENCES = {
4
+ amp: "&",
5
+ AMP: "&",
6
+ apos: "'",
7
+ gt: ">",
8
+ GT: ">",
9
+ lt: "<",
10
+ LT: "<",
11
+ quot: '"',
12
+ QUOT: '"'
13
+ };
14
+ const VOID_ELEMENTS = /* @__PURE__ */ new Set([
15
+ "area",
16
+ "base",
17
+ "br",
18
+ "col",
19
+ "embed",
20
+ "hr",
21
+ "img",
22
+ "input",
23
+ "link",
24
+ "meta",
25
+ "param",
26
+ "source",
27
+ "track",
28
+ "wbr"
29
+ ]);
30
+ const ELEMENT_TOKENIZER = /(?:<([a-z][a-z0-9-:]*)((?:[\s]+[^<>'"=/\s]+(?:=(['"])[^]*?\3|=[^>'"\s]*|))*)[\s]*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|<!--(.*?)-->|([^<>]+))/gi;
31
+ const ATTRIBUTE_TOKENIZER = /\s([^<>'"=/\n\s]+)(?:=(["'])([\s\S]*?)\2|=([^>'"\n\s]*)|)/g;
32
+ const SVG_HTML_BREAKOUTS = "|b|big|blockquote|body|br|center|code|dd|div|dl|dt|em|embed|h1|h2|h3|h4|h5|h6|head|hr|i|img|li|listing|menu|meta|nobr|ol|p|pre|ruby|s|small|span|strong|strike|sub|sup|table|tt|u|ul|var|";
33
+ const SVG_HTML_FONT_ATTRIBUTE = /^(?:color|face|size)$/i;
34
+ function decodeCharacterReferences(value) {
35
+ return value.replace(
36
+ /&(?:(amp|AMP|apos|gt|GT|lt|LT|quot|QUOT)|#(\d+)|#[xX]([\da-fA-F]+));/g,
37
+ (reference, name, decimal, hexadecimal) => {
38
+ if (name) return CHARACTER_REFERENCES[name];
39
+ const codePoint = Number.parseInt(
40
+ decimal ?? hexadecimal,
41
+ decimal ? 10 : 16
42
+ );
43
+ try {
44
+ return String.fromCodePoint(codePoint);
45
+ } catch {
46
+ return reference;
47
+ }
48
+ }
49
+ );
50
+ }
51
+ function isVoidElement(element) {
52
+ return element.namespaceURI === HTML_NAMESPACE && VOID_ELEMENTS.has(element.localName);
53
+ }
54
+ function isHtmlIntegrationPoint(element) {
55
+ const name = element.localName;
56
+ return element[NS] === SVG_NAMESPACE && (name === "foreignObject" || name === "desc" || name === "title");
57
+ }
58
+ function isSvgHtmlBreakout(tag, attributes) {
59
+ if (SVG_HTML_BREAKOUTS.includes(`|${tag}|`)) return true;
60
+ if (tag !== "font") return false;
61
+ for (const attribute of attributes.matchAll(ATTRIBUTE_TOKENIZER)) {
62
+ if (SVG_HTML_FONT_ATTRIBUTE.test(attribute[1])) return true;
63
+ }
64
+ return false;
65
+ }
5
66
  function parseHtml(html, contextNode) {
6
67
  const document = contextNode.ownerDocument;
7
68
  const root = document.createDocumentFragment();
8
- const stack = [root];
69
+ const stack = [];
9
70
  let parent = root;
10
- let token;
11
- elementTokenizer.lastIndex = 0;
12
- while (token = elementTokenizer.exec(html)) {
71
+ for (const token of html.matchAll(ELEMENT_TOKENIZER)) {
13
72
  const tag = token[1];
14
73
  if (tag) {
15
- const node = document.createElement(tag);
16
74
  const attrs = token[2];
17
- attributeTokenizer.lastIndex = 0;
18
- let t;
19
- while (t = attributeTokenizer.exec(attrs)) {
20
- node.setAttribute(t[1], t[3] || t[4] || "");
75
+ const normalizedTag = asciiLowercase(tag);
76
+ const openElement = stack[stack.length - 1]?.element ?? contextNode;
77
+ let namespace = openElement[NS] === SVG_NAMESPACE ? SVG_NAMESPACE : HTML_NAMESPACE;
78
+ if (normalizedTag === "svg") {
79
+ namespace = SVG_NAMESPACE;
80
+ } else if (namespace === SVG_NAMESPACE) {
81
+ if (isHtmlIntegrationPoint(openElement)) {
82
+ namespace = HTML_NAMESPACE;
83
+ } else if (isSvgHtmlBreakout(normalizedTag, attrs)) {
84
+ while (stack.length > 0) {
85
+ const frame = stack[stack.length - 1];
86
+ if (frame.element[NS] !== SVG_NAMESPACE || isHtmlIntegrationPoint(frame.element)) {
87
+ break;
88
+ }
89
+ stack.pop();
90
+ parent = frame.target;
91
+ }
92
+ namespace = HTML_NAMESPACE;
93
+ }
94
+ }
95
+ const name = namespace === HTML_NAMESPACE ? normalizedTag : tag;
96
+ const node = document[CREATE_ELEMENT](name, namespace, null, name);
97
+ for (const attribute of attrs.matchAll(ATTRIBUTE_TOKENIZER)) {
98
+ node.setAttribute(
99
+ attribute[1],
100
+ decodeCharacterReferences(attribute[3] || attribute[4] || "")
101
+ );
21
102
  }
22
103
  parent.append(node);
23
- stack.push(parent);
24
- parent = node;
104
+ if (isVoidElement(node) || namespace !== HTML_NAMESPACE && token[4]) {
105
+ continue;
106
+ }
107
+ stack.push({ element: node, target: parent });
108
+ parent = namespace === HTML_NAMESPACE && normalizedTag === "template" ? node.content : node;
25
109
  } else if (token[5]) {
26
- parent = stack.pop() || root;
110
+ const closingTag = asciiLowercase(token[5]);
111
+ for (let index = stack.length - 1; index >= 0; index--) {
112
+ const frame = stack[index];
113
+ const frameName = asciiLowercase(frame.element[NAME]);
114
+ if (frameName === closingTag) {
115
+ parent = frame.target;
116
+ stack.length = index;
117
+ break;
118
+ }
119
+ if (frame.element[NS] === HTML_NAMESPACE && frameName === "template") {
120
+ break;
121
+ }
122
+ }
27
123
  } else if (token[6]) {
28
124
  parent.append(document.createComment(token[6]));
29
125
  } else {
30
- parent.append(token[7]);
126
+ parent.append(decodeCharacterReferences(token[7]));
31
127
  }
32
128
  }
33
129
  return root;
34
130
  }
35
131
  function serializeChildren(parentNode) {
36
- let out = "";
37
- let child = parentNode[CHILD];
38
- while (child) {
39
- out += serializeNode(child);
40
- child = child[NEXT];
41
- }
42
- return out;
132
+ return serialize([{ type: "content", child: parentNode[CHILD] }]);
43
133
  }
44
134
  function serializeNode(node) {
45
- switch (node.nodeType) {
46
- case NodeType.ELEMENT_NODE: {
47
- const el = node;
48
- let out = `<${el[NAME]}`;
49
- let attr = el[ATTRIBUTES]?.[CHILD];
50
- while (attr) {
51
- out += ` ${attr[NAME]}`;
52
- let value = attr[VALUE];
53
- if (value !== "") {
54
- value = String(value).replace(/&/g, "&amp;").replace(/"/g, "&quot;");
55
- out += `="${value}"`;
135
+ return serialize([{ type: "opening", node }]);
136
+ }
137
+ function serialize(workItems) {
138
+ const chunks = [];
139
+ let workItem;
140
+ while (workItem = workItems.pop()) {
141
+ switch (workItem.type) {
142
+ case "opening": {
143
+ const node = workItem.node;
144
+ switch (node.nodeType) {
145
+ case NODE_TYPE_ELEMENT: {
146
+ const el = node;
147
+ chunks.push(`<${el[NAME]}`);
148
+ let attr = el[ATTRIBUTES]?.[CHILD];
149
+ while (attr) {
150
+ chunks.push(` ${attr[NAME]}`);
151
+ let value = attr[VALUE];
152
+ if (value !== "") {
153
+ value = String(value).replace(/&/g, "&amp;").replace(/"/g, "&quot;");
154
+ chunks.push(`="${value}"`);
155
+ }
156
+ attr = attr[NEXT];
157
+ }
158
+ chunks.push(">");
159
+ if (isVoidElement(el)) break;
160
+ const content = el.namespaceURI === HTML_NAMESPACE && el.localName === "template" ? el[CONTENT] : el;
161
+ workItems.push({ type: "closing", name: el[NAME] });
162
+ workItems.push({
163
+ type: "content",
164
+ child: content?.[CHILD] ?? null
165
+ });
166
+ break;
167
+ }
168
+ case NODE_TYPE_TEXT: {
169
+ const text = node;
170
+ chunks.push(
171
+ text[DATA].replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
172
+ );
173
+ break;
174
+ }
175
+ case NODE_TYPE_COMMENT: {
176
+ const text = node;
177
+ chunks.push(`<!--${text[DATA]}-->`);
178
+ break;
179
+ }
56
180
  }
57
- attr = attr[NEXT];
181
+ break;
58
182
  }
59
- out += ">";
60
- out += serializeChildren(el);
61
- out += `</${el[NAME]}>`;
62
- return out;
63
- }
64
- case NodeType.TEXT_NODE: {
65
- const text = node;
66
- return text[DATA].replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
67
- }
68
- case NodeType.COMMENT_NODE: {
69
- const text = node;
70
- return `<!--${text[DATA]}-->`;
183
+ case "content": {
184
+ const child = workItem.child;
185
+ if (child) {
186
+ workItems.push({ type: "content", child: child[NEXT] });
187
+ workItems.push({ type: "opening", node: child });
188
+ }
189
+ break;
190
+ }
191
+ case "closing":
192
+ chunks.push(`</${workItem.name}>`);
193
+ break;
71
194
  }
72
195
  }
73
- return "";
196
+ return chunks.join("");
74
197
  }
75
198
 
76
199
  export { parseHtml, serializeChildren, serializeNode };