happy-dom 15.11.6 → 16.0.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 (489) hide show
  1. package/cjs/PropertySymbol.cjs +12 -9
  2. package/cjs/PropertySymbol.cjs.map +1 -1
  3. package/cjs/PropertySymbol.d.ts +4 -1
  4. package/cjs/PropertySymbol.d.ts.map +1 -1
  5. package/cjs/browser/utilities/BrowserFrameURL.cjs +1 -1
  6. package/cjs/browser/utilities/BrowserFrameURL.cjs.map +1 -1
  7. package/cjs/browser/utilities/BrowserFrameURL.d.ts +1 -1
  8. package/cjs/browser/utilities/BrowserFrameURL.d.ts.map +1 -1
  9. package/cjs/config/HTMLElementConfig.cjs +42 -16
  10. package/cjs/config/HTMLElementConfig.cjs.map +1 -1
  11. package/cjs/config/HTMLElementConfig.d.ts +7 -0
  12. package/cjs/config/HTMLElementConfig.d.ts.map +1 -1
  13. package/cjs/config/HTMLElementConfigContentModelEnum.cjs +3 -0
  14. package/cjs/config/HTMLElementConfigContentModelEnum.cjs.map +1 -1
  15. package/cjs/config/HTMLElementConfigContentModelEnum.d.ts +3 -0
  16. package/cjs/config/HTMLElementConfigContentModelEnum.d.ts.map +1 -1
  17. package/cjs/config/NamespaceURI.cjs +2 -0
  18. package/cjs/config/NamespaceURI.cjs.map +1 -1
  19. package/cjs/config/NamespaceURI.d.ts +2 -0
  20. package/cjs/config/NamespaceURI.d.ts.map +1 -1
  21. package/cjs/css/declaration/CSSStyleDeclaration.cjs +1 -1
  22. package/cjs/css/declaration/CSSStyleDeclaration.cjs.map +1 -1
  23. package/cjs/css/declaration/CSSStyleDeclaration.d.ts.map +1 -1
  24. package/cjs/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.cjs +2 -2
  25. package/cjs/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.cjs.map +1 -1
  26. package/cjs/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.d.ts.map +1 -1
  27. package/cjs/custom-element/CustomElementReactionStack.cjs +100 -0
  28. package/cjs/custom-element/CustomElementReactionStack.cjs.map +1 -0
  29. package/cjs/custom-element/CustomElementReactionStack.d.ts +27 -0
  30. package/cjs/custom-element/CustomElementReactionStack.d.ts.map +1 -0
  31. package/cjs/custom-element/CustomElementRegistry.cjs +32 -45
  32. package/cjs/custom-element/CustomElementRegistry.cjs.map +1 -1
  33. package/cjs/custom-element/CustomElementRegistry.d.ts +2 -6
  34. package/cjs/custom-element/CustomElementRegistry.d.ts.map +1 -1
  35. package/cjs/custom-element/CustomElementUtility.cjs +35 -0
  36. package/cjs/custom-element/CustomElementUtility.cjs.map +1 -0
  37. package/cjs/custom-element/CustomElementUtility.d.ts +14 -0
  38. package/cjs/custom-element/CustomElementUtility.d.ts.map +1 -0
  39. package/cjs/custom-element/ICustomElementDefinition.cjs +3 -0
  40. package/cjs/custom-element/ICustomElementDefinition.cjs.map +1 -0
  41. package/cjs/custom-element/ICustomElementDefinition.d.ts +12 -0
  42. package/cjs/custom-element/ICustomElementDefinition.d.ts.map +1 -0
  43. package/cjs/dom/DOMStringMap.cjs +8 -8
  44. package/cjs/dom/DOMStringMap.cjs.map +1 -1
  45. package/cjs/dom/DOMStringMap.d.ts.map +1 -1
  46. package/cjs/dom/DOMTokenList.cjs +1 -1
  47. package/cjs/dom/DOMTokenList.cjs.map +1 -1
  48. package/cjs/dom-parser/DOMParser.cjs +5 -67
  49. package/cjs/dom-parser/DOMParser.cjs.map +1 -1
  50. package/cjs/dom-parser/DOMParser.d.ts +0 -1
  51. package/cjs/dom-parser/DOMParser.d.ts.map +1 -1
  52. package/cjs/exception/DOMExceptionNameEnum.cjs +1 -0
  53. package/cjs/exception/DOMExceptionNameEnum.cjs.map +1 -1
  54. package/cjs/exception/DOMExceptionNameEnum.d.ts +2 -1
  55. package/cjs/exception/DOMExceptionNameEnum.d.ts.map +1 -1
  56. package/cjs/history/History.cjs +8 -8
  57. package/cjs/history/History.cjs.map +1 -1
  58. package/cjs/history/History.d.ts +2 -2
  59. package/cjs/history/History.d.ts.map +1 -1
  60. package/cjs/html-parser/HTMLParser.cjs +726 -0
  61. package/cjs/html-parser/HTMLParser.cjs.map +1 -0
  62. package/cjs/html-parser/HTMLParser.d.ts +91 -0
  63. package/cjs/html-parser/HTMLParser.d.ts.map +1 -0
  64. package/cjs/html-serializer/HTMLSerializer.cjs +152 -0
  65. package/cjs/html-serializer/HTMLSerializer.cjs.map +1 -0
  66. package/cjs/html-serializer/HTMLSerializer.d.ts +36 -0
  67. package/cjs/html-serializer/HTMLSerializer.d.ts.map +1 -0
  68. package/cjs/nodes/document/Document.cjs +105 -121
  69. package/cjs/nodes/document/Document.cjs.map +1 -1
  70. package/cjs/nodes/document/Document.d.ts +8 -0
  71. package/cjs/nodes/document/Document.d.ts.map +1 -1
  72. package/cjs/nodes/element/Element.cjs +35 -53
  73. package/cjs/nodes/element/Element.cjs.map +1 -1
  74. package/cjs/nodes/element/Element.d.ts +2 -12
  75. package/cjs/nodes/element/Element.d.ts.map +1 -1
  76. package/cjs/nodes/element/HTMLCollection.cjs +5 -9
  77. package/cjs/nodes/element/HTMLCollection.cjs.map +1 -1
  78. package/cjs/nodes/element/HTMLCollection.d.ts.map +1 -1
  79. package/cjs/nodes/element/NamedNodeMap.cjs +39 -52
  80. package/cjs/nodes/element/NamedNodeMap.cjs.map +1 -1
  81. package/cjs/nodes/element/NamedNodeMap.d.ts +1 -16
  82. package/cjs/nodes/element/NamedNodeMap.d.ts.map +1 -1
  83. package/cjs/nodes/element/NamedNodeMapProxyFactory.cjs +12 -14
  84. package/cjs/nodes/element/NamedNodeMapProxyFactory.cjs.map +1 -1
  85. package/cjs/nodes/element/NamedNodeMapProxyFactory.d.ts.map +1 -1
  86. package/cjs/nodes/html-button-element/HTMLButtonElement.cjs +1 -1
  87. package/cjs/nodes/html-button-element/HTMLButtonElement.cjs.map +1 -1
  88. package/cjs/nodes/html-button-element/HTMLButtonElement.d.ts.map +1 -1
  89. package/cjs/nodes/html-document/HTMLDocument.cjs +33 -2
  90. package/cjs/nodes/html-document/HTMLDocument.cjs.map +1 -1
  91. package/cjs/nodes/html-document/HTMLDocument.d.ts +10 -0
  92. package/cjs/nodes/html-document/HTMLDocument.d.ts.map +1 -1
  93. package/cjs/nodes/html-element/HTMLElement.cjs +52 -22
  94. package/cjs/nodes/html-element/HTMLElement.cjs.map +1 -1
  95. package/cjs/nodes/html-element/HTMLElement.d.ts +34 -0
  96. package/cjs/nodes/html-element/HTMLElement.d.ts.map +1 -1
  97. package/cjs/nodes/html-field-set-element/HTMLFieldSetElement.cjs +1 -1
  98. package/cjs/nodes/html-field-set-element/HTMLFieldSetElement.cjs.map +1 -1
  99. package/cjs/nodes/html-field-set-element/HTMLFieldSetElement.d.ts.map +1 -1
  100. package/cjs/nodes/html-form-element/HTMLFormElement.cjs +5 -8
  101. package/cjs/nodes/html-form-element/HTMLFormElement.cjs.map +1 -1
  102. package/cjs/nodes/html-form-element/HTMLFormElement.d.ts.map +1 -1
  103. package/cjs/nodes/html-iframe-element/HTMLIFrameElement.cjs +1 -1
  104. package/cjs/nodes/html-iframe-element/HTMLIFrameElement.cjs.map +1 -1
  105. package/cjs/nodes/html-input-element/HTMLInputElement.cjs +1 -1
  106. package/cjs/nodes/html-input-element/HTMLInputElement.cjs.map +1 -1
  107. package/cjs/nodes/html-input-element/HTMLInputElement.d.ts.map +1 -1
  108. package/cjs/nodes/html-media-element/TextTrackList.cjs +1 -1
  109. package/cjs/nodes/html-media-element/TextTrackList.cjs.map +1 -1
  110. package/cjs/nodes/html-object-element/HTMLObjectElement.cjs +1 -1
  111. package/cjs/nodes/html-object-element/HTMLObjectElement.cjs.map +1 -1
  112. package/cjs/nodes/html-object-element/HTMLObjectElement.d.ts.map +1 -1
  113. package/cjs/nodes/html-output-element/HTMLOutputElement.cjs +1 -1
  114. package/cjs/nodes/html-output-element/HTMLOutputElement.cjs.map +1 -1
  115. package/cjs/nodes/html-output-element/HTMLOutputElement.d.ts.map +1 -1
  116. package/cjs/nodes/html-script-element/HTMLScriptElement.cjs +3 -1
  117. package/cjs/nodes/html-script-element/HTMLScriptElement.cjs.map +1 -1
  118. package/cjs/nodes/html-script-element/HTMLScriptElement.d.ts.map +1 -1
  119. package/cjs/nodes/html-select-element/HTMLSelectElement.cjs +2 -2
  120. package/cjs/nodes/html-select-element/HTMLSelectElement.cjs.map +1 -1
  121. package/cjs/nodes/html-select-element/HTMLSelectElement.d.ts.map +1 -1
  122. package/cjs/nodes/html-table-element/HTMLTableElement.cjs +9 -1
  123. package/cjs/nodes/html-table-element/HTMLTableElement.cjs.map +1 -1
  124. package/cjs/nodes/html-table-element/HTMLTableElement.d.ts.map +1 -1
  125. package/cjs/nodes/html-table-row-element/HTMLTableRowElement.cjs +1 -1
  126. package/cjs/nodes/html-template-element/HTMLTemplateElement.cjs +15 -17
  127. package/cjs/nodes/html-template-element/HTMLTemplateElement.cjs.map +1 -1
  128. package/cjs/nodes/html-template-element/HTMLTemplateElement.d.ts +2 -2
  129. package/cjs/nodes/html-template-element/HTMLTemplateElement.d.ts.map +1 -1
  130. package/cjs/nodes/html-text-area-element/HTMLTextAreaElement.cjs +1 -1
  131. package/cjs/nodes/html-text-area-element/HTMLTextAreaElement.cjs.map +1 -1
  132. package/cjs/nodes/html-text-area-element/HTMLTextAreaElement.d.ts.map +1 -1
  133. package/cjs/nodes/node/Node.cjs +44 -48
  134. package/cjs/nodes/node/Node.cjs.map +1 -1
  135. package/cjs/nodes/node/Node.d.ts +2 -10
  136. package/cjs/nodes/node/Node.d.ts.map +1 -1
  137. package/cjs/nodes/node/NodeList.cjs +1 -1
  138. package/cjs/nodes/node/NodeList.cjs.map +1 -1
  139. package/cjs/nodes/node/NodeUtility.cjs +4 -3
  140. package/cjs/nodes/node/NodeUtility.cjs.map +1 -1
  141. package/cjs/nodes/node/NodeUtility.d.ts.map +1 -1
  142. package/cjs/nodes/parent-node/ParentNodeUtility.cjs +5 -2
  143. package/cjs/nodes/parent-node/ParentNodeUtility.cjs.map +1 -1
  144. package/cjs/nodes/parent-node/ParentNodeUtility.d.ts.map +1 -1
  145. package/cjs/nodes/shadow-root/ShadowRoot.cjs +8 -8
  146. package/cjs/nodes/shadow-root/ShadowRoot.cjs.map +1 -1
  147. package/cjs/nodes/shadow-root/ShadowRoot.d.ts.map +1 -1
  148. package/cjs/nodes/xml-document/XMLDocument.cjs +26 -0
  149. package/cjs/nodes/xml-document/XMLDocument.cjs.map +1 -1
  150. package/cjs/nodes/xml-document/XMLDocument.d.ts +2 -0
  151. package/cjs/nodes/xml-document/XMLDocument.d.ts.map +1 -1
  152. package/cjs/query-selector/SelectorItem.cjs +1 -2
  153. package/cjs/query-selector/SelectorItem.cjs.map +1 -1
  154. package/cjs/query-selector/SelectorItem.d.ts.map +1 -1
  155. package/cjs/range/Range.cjs +3 -3
  156. package/cjs/range/Range.cjs.map +1 -1
  157. package/cjs/range/Range.d.ts.map +1 -1
  158. package/cjs/storage/Storage.cjs +1 -1
  159. package/cjs/storage/Storage.cjs.map +1 -1
  160. package/cjs/svg/SVGLengthList.cjs +1 -1
  161. package/cjs/svg/SVGLengthList.cjs.map +1 -1
  162. package/cjs/svg/SVGNumberList.cjs +1 -1
  163. package/cjs/svg/SVGNumberList.cjs.map +1 -1
  164. package/cjs/svg/SVGPointList.cjs +1 -1
  165. package/cjs/svg/SVGPointList.cjs.map +1 -1
  166. package/cjs/svg/SVGStringList.cjs +1 -1
  167. package/cjs/svg/SVGStringList.cjs.map +1 -1
  168. package/cjs/svg/SVGTransformList.cjs +1 -1
  169. package/cjs/svg/SVGTransformList.cjs.map +1 -1
  170. package/cjs/tree-walker/NodeIterator.cjs +63 -6
  171. package/cjs/tree-walker/NodeIterator.cjs.map +1 -1
  172. package/cjs/tree-walker/NodeIterator.d.ts +18 -3
  173. package/cjs/tree-walker/NodeIterator.d.ts.map +1 -1
  174. package/cjs/tree-walker/TreeWalker.cjs +6 -6
  175. package/cjs/tree-walker/TreeWalker.cjs.map +1 -1
  176. package/cjs/tree-walker/TreeWalker.d.ts +2 -1
  177. package/cjs/tree-walker/TreeWalker.d.ts.map +1 -1
  178. package/cjs/utilities/ClassMethodBinder.cjs.map +1 -0
  179. package/cjs/utilities/ClassMethodBinder.d.ts.map +1 -0
  180. package/cjs/utilities/StringUtility.cjs.map +1 -0
  181. package/cjs/utilities/StringUtility.d.ts.map +1 -0
  182. package/cjs/utilities/XMLEncodeUtility.cjs +119 -0
  183. package/cjs/utilities/XMLEncodeUtility.cjs.map +1 -0
  184. package/cjs/utilities/XMLEncodeUtility.d.ts +48 -0
  185. package/cjs/utilities/XMLEncodeUtility.d.ts.map +1 -0
  186. package/cjs/window/BrowserWindow.cjs +9 -3
  187. package/cjs/window/BrowserWindow.cjs.map +1 -1
  188. package/cjs/window/BrowserWindow.d.ts +2 -0
  189. package/cjs/window/BrowserWindow.d.ts.map +1 -1
  190. package/cjs/window/WindowErrorUtility.cjs +1 -1
  191. package/cjs/window/WindowErrorUtility.cjs.map +1 -1
  192. package/cjs/xml-http-request/XMLHttpRequest.cjs +2 -1
  193. package/cjs/xml-http-request/XMLHttpRequest.cjs.map +1 -1
  194. package/cjs/xml-http-request/XMLHttpRequest.d.ts.map +1 -1
  195. package/cjs/xml-http-request/XMLHttpRequestResponseDataParser.cjs +1 -1
  196. package/cjs/xml-http-request/XMLHttpRequestResponseDataParser.cjs.map +1 -1
  197. package/cjs/xml-parser/XMLParser.cjs +531 -242
  198. package/cjs/xml-parser/XMLParser.cjs.map +1 -1
  199. package/cjs/xml-parser/XMLParser.d.ts +89 -19
  200. package/cjs/xml-parser/XMLParser.d.ts.map +1 -1
  201. package/cjs/xml-serializer/XMLSerializer.cjs +136 -40
  202. package/cjs/xml-serializer/XMLSerializer.cjs.map +1 -1
  203. package/cjs/xml-serializer/XMLSerializer.d.ts +6 -17
  204. package/cjs/xml-serializer/XMLSerializer.d.ts.map +1 -1
  205. package/lib/PropertySymbol.d.ts +4 -1
  206. package/lib/PropertySymbol.d.ts.map +1 -1
  207. package/lib/PropertySymbol.js +4 -1
  208. package/lib/PropertySymbol.js.map +1 -1
  209. package/lib/browser/utilities/BrowserFrameURL.d.ts +1 -1
  210. package/lib/browser/utilities/BrowserFrameURL.d.ts.map +1 -1
  211. package/lib/browser/utilities/BrowserFrameURL.js +1 -1
  212. package/lib/browser/utilities/BrowserFrameURL.js.map +1 -1
  213. package/lib/config/HTMLElementConfig.d.ts +7 -0
  214. package/lib/config/HTMLElementConfig.d.ts.map +1 -1
  215. package/lib/config/HTMLElementConfig.js +42 -16
  216. package/lib/config/HTMLElementConfig.js.map +1 -1
  217. package/lib/config/HTMLElementConfigContentModelEnum.d.ts +3 -0
  218. package/lib/config/HTMLElementConfigContentModelEnum.d.ts.map +1 -1
  219. package/lib/config/HTMLElementConfigContentModelEnum.js +3 -0
  220. package/lib/config/HTMLElementConfigContentModelEnum.js.map +1 -1
  221. package/lib/config/NamespaceURI.d.ts +2 -0
  222. package/lib/config/NamespaceURI.d.ts.map +1 -1
  223. package/lib/config/NamespaceURI.js +2 -0
  224. package/lib/config/NamespaceURI.js.map +1 -1
  225. package/lib/css/declaration/CSSStyleDeclaration.d.ts.map +1 -1
  226. package/lib/css/declaration/CSSStyleDeclaration.js +1 -1
  227. package/lib/css/declaration/CSSStyleDeclaration.js.map +1 -1
  228. package/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.d.ts.map +1 -1
  229. package/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.js +2 -2
  230. package/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.js.map +1 -1
  231. package/lib/custom-element/CustomElementReactionStack.d.ts +27 -0
  232. package/lib/custom-element/CustomElementReactionStack.d.ts.map +1 -0
  233. package/lib/custom-element/CustomElementReactionStack.js +71 -0
  234. package/lib/custom-element/CustomElementReactionStack.js.map +1 -0
  235. package/lib/custom-element/CustomElementRegistry.d.ts +2 -6
  236. package/lib/custom-element/CustomElementRegistry.d.ts.map +1 -1
  237. package/lib/custom-element/CustomElementRegistry.js +32 -45
  238. package/lib/custom-element/CustomElementRegistry.js.map +1 -1
  239. package/lib/custom-element/CustomElementUtility.d.ts +14 -0
  240. package/lib/custom-element/CustomElementUtility.d.ts.map +1 -0
  241. package/lib/custom-element/CustomElementUtility.js +32 -0
  242. package/lib/custom-element/CustomElementUtility.js.map +1 -0
  243. package/lib/custom-element/ICustomElementDefinition.d.ts +12 -0
  244. package/lib/custom-element/ICustomElementDefinition.d.ts.map +1 -0
  245. package/lib/custom-element/ICustomElementDefinition.js +2 -0
  246. package/lib/custom-element/ICustomElementDefinition.js.map +1 -0
  247. package/lib/dom/DOMStringMap.d.ts.map +1 -1
  248. package/lib/dom/DOMStringMap.js +8 -8
  249. package/lib/dom/DOMStringMap.js.map +1 -1
  250. package/lib/dom/DOMTokenList.js +1 -1
  251. package/lib/dom/DOMTokenList.js.map +1 -1
  252. package/lib/dom-parser/DOMParser.d.ts +0 -1
  253. package/lib/dom-parser/DOMParser.d.ts.map +1 -1
  254. package/lib/dom-parser/DOMParser.js +5 -67
  255. package/lib/dom-parser/DOMParser.js.map +1 -1
  256. package/lib/exception/DOMExceptionNameEnum.d.ts +2 -1
  257. package/lib/exception/DOMExceptionNameEnum.d.ts.map +1 -1
  258. package/lib/exception/DOMExceptionNameEnum.js +1 -0
  259. package/lib/exception/DOMExceptionNameEnum.js.map +1 -1
  260. package/lib/history/History.d.ts +2 -2
  261. package/lib/history/History.d.ts.map +1 -1
  262. package/lib/history/History.js +8 -8
  263. package/lib/history/History.js.map +1 -1
  264. package/lib/html-parser/HTMLParser.d.ts +91 -0
  265. package/lib/html-parser/HTMLParser.d.ts.map +1 -0
  266. package/lib/html-parser/HTMLParser.js +697 -0
  267. package/lib/html-parser/HTMLParser.js.map +1 -0
  268. package/lib/html-serializer/HTMLSerializer.d.ts +36 -0
  269. package/lib/html-serializer/HTMLSerializer.d.ts.map +1 -0
  270. package/lib/html-serializer/HTMLSerializer.js +123 -0
  271. package/lib/html-serializer/HTMLSerializer.js.map +1 -0
  272. package/lib/nodes/document/Document.d.ts +8 -0
  273. package/lib/nodes/document/Document.d.ts.map +1 -1
  274. package/lib/nodes/document/Document.js +106 -122
  275. package/lib/nodes/document/Document.js.map +1 -1
  276. package/lib/nodes/element/Element.d.ts +2 -12
  277. package/lib/nodes/element/Element.d.ts.map +1 -1
  278. package/lib/nodes/element/Element.js +35 -53
  279. package/lib/nodes/element/Element.js.map +1 -1
  280. package/lib/nodes/element/HTMLCollection.d.ts.map +1 -1
  281. package/lib/nodes/element/HTMLCollection.js +5 -9
  282. package/lib/nodes/element/HTMLCollection.js.map +1 -1
  283. package/lib/nodes/element/NamedNodeMap.d.ts +1 -16
  284. package/lib/nodes/element/NamedNodeMap.d.ts.map +1 -1
  285. package/lib/nodes/element/NamedNodeMap.js +39 -52
  286. package/lib/nodes/element/NamedNodeMap.js.map +1 -1
  287. package/lib/nodes/element/NamedNodeMapProxyFactory.d.ts.map +1 -1
  288. package/lib/nodes/element/NamedNodeMapProxyFactory.js +12 -14
  289. package/lib/nodes/element/NamedNodeMapProxyFactory.js.map +1 -1
  290. package/lib/nodes/html-button-element/HTMLButtonElement.d.ts.map +1 -1
  291. package/lib/nodes/html-button-element/HTMLButtonElement.js +1 -1
  292. package/lib/nodes/html-button-element/HTMLButtonElement.js.map +1 -1
  293. package/lib/nodes/html-document/HTMLDocument.d.ts +10 -0
  294. package/lib/nodes/html-document/HTMLDocument.d.ts.map +1 -1
  295. package/lib/nodes/html-document/HTMLDocument.js +33 -2
  296. package/lib/nodes/html-document/HTMLDocument.js.map +1 -1
  297. package/lib/nodes/html-element/HTMLElement.d.ts +34 -0
  298. package/lib/nodes/html-element/HTMLElement.d.ts.map +1 -1
  299. package/lib/nodes/html-element/HTMLElement.js +52 -22
  300. package/lib/nodes/html-element/HTMLElement.js.map +1 -1
  301. package/lib/nodes/html-field-set-element/HTMLFieldSetElement.d.ts.map +1 -1
  302. package/lib/nodes/html-field-set-element/HTMLFieldSetElement.js +1 -1
  303. package/lib/nodes/html-field-set-element/HTMLFieldSetElement.js.map +1 -1
  304. package/lib/nodes/html-form-element/HTMLFormElement.d.ts.map +1 -1
  305. package/lib/nodes/html-form-element/HTMLFormElement.js +5 -8
  306. package/lib/nodes/html-form-element/HTMLFormElement.js.map +1 -1
  307. package/lib/nodes/html-iframe-element/HTMLIFrameElement.js +1 -1
  308. package/lib/nodes/html-iframe-element/HTMLIFrameElement.js.map +1 -1
  309. package/lib/nodes/html-input-element/HTMLInputElement.d.ts.map +1 -1
  310. package/lib/nodes/html-input-element/HTMLInputElement.js +1 -1
  311. package/lib/nodes/html-input-element/HTMLInputElement.js.map +1 -1
  312. package/lib/nodes/html-media-element/TextTrackList.js +1 -1
  313. package/lib/nodes/html-media-element/TextTrackList.js.map +1 -1
  314. package/lib/nodes/html-object-element/HTMLObjectElement.d.ts.map +1 -1
  315. package/lib/nodes/html-object-element/HTMLObjectElement.js +1 -1
  316. package/lib/nodes/html-object-element/HTMLObjectElement.js.map +1 -1
  317. package/lib/nodes/html-output-element/HTMLOutputElement.d.ts.map +1 -1
  318. package/lib/nodes/html-output-element/HTMLOutputElement.js +1 -1
  319. package/lib/nodes/html-output-element/HTMLOutputElement.js.map +1 -1
  320. package/lib/nodes/html-script-element/HTMLScriptElement.d.ts.map +1 -1
  321. package/lib/nodes/html-script-element/HTMLScriptElement.js +3 -1
  322. package/lib/nodes/html-script-element/HTMLScriptElement.js.map +1 -1
  323. package/lib/nodes/html-select-element/HTMLSelectElement.d.ts.map +1 -1
  324. package/lib/nodes/html-select-element/HTMLSelectElement.js +2 -2
  325. package/lib/nodes/html-select-element/HTMLSelectElement.js.map +1 -1
  326. package/lib/nodes/html-table-element/HTMLTableElement.d.ts.map +1 -1
  327. package/lib/nodes/html-table-element/HTMLTableElement.js +9 -1
  328. package/lib/nodes/html-table-element/HTMLTableElement.js.map +1 -1
  329. package/lib/nodes/html-table-row-element/HTMLTableRowElement.js +1 -1
  330. package/lib/nodes/html-template-element/HTMLTemplateElement.d.ts +2 -2
  331. package/lib/nodes/html-template-element/HTMLTemplateElement.d.ts.map +1 -1
  332. package/lib/nodes/html-template-element/HTMLTemplateElement.js +15 -17
  333. package/lib/nodes/html-template-element/HTMLTemplateElement.js.map +1 -1
  334. package/lib/nodes/html-text-area-element/HTMLTextAreaElement.d.ts.map +1 -1
  335. package/lib/nodes/html-text-area-element/HTMLTextAreaElement.js +1 -1
  336. package/lib/nodes/html-text-area-element/HTMLTextAreaElement.js.map +1 -1
  337. package/lib/nodes/node/Node.d.ts +2 -10
  338. package/lib/nodes/node/Node.d.ts.map +1 -1
  339. package/lib/nodes/node/Node.js +44 -48
  340. package/lib/nodes/node/Node.js.map +1 -1
  341. package/lib/nodes/node/NodeList.js +1 -1
  342. package/lib/nodes/node/NodeList.js.map +1 -1
  343. package/lib/nodes/node/NodeUtility.d.ts.map +1 -1
  344. package/lib/nodes/node/NodeUtility.js +4 -3
  345. package/lib/nodes/node/NodeUtility.js.map +1 -1
  346. package/lib/nodes/parent-node/ParentNodeUtility.d.ts.map +1 -1
  347. package/lib/nodes/parent-node/ParentNodeUtility.js +5 -2
  348. package/lib/nodes/parent-node/ParentNodeUtility.js.map +1 -1
  349. package/lib/nodes/shadow-root/ShadowRoot.d.ts.map +1 -1
  350. package/lib/nodes/shadow-root/ShadowRoot.js +8 -8
  351. package/lib/nodes/shadow-root/ShadowRoot.js.map +1 -1
  352. package/lib/nodes/xml-document/XMLDocument.d.ts +2 -0
  353. package/lib/nodes/xml-document/XMLDocument.d.ts.map +1 -1
  354. package/lib/nodes/xml-document/XMLDocument.js +3 -0
  355. package/lib/nodes/xml-document/XMLDocument.js.map +1 -1
  356. package/lib/query-selector/SelectorItem.d.ts.map +1 -1
  357. package/lib/query-selector/SelectorItem.js +1 -2
  358. package/lib/query-selector/SelectorItem.js.map +1 -1
  359. package/lib/range/Range.d.ts.map +1 -1
  360. package/lib/range/Range.js +3 -3
  361. package/lib/range/Range.js.map +1 -1
  362. package/lib/storage/Storage.js +1 -1
  363. package/lib/storage/Storage.js.map +1 -1
  364. package/lib/svg/SVGLengthList.js +1 -1
  365. package/lib/svg/SVGLengthList.js.map +1 -1
  366. package/lib/svg/SVGNumberList.js +1 -1
  367. package/lib/svg/SVGNumberList.js.map +1 -1
  368. package/lib/svg/SVGPointList.js +1 -1
  369. package/lib/svg/SVGPointList.js.map +1 -1
  370. package/lib/svg/SVGStringList.js +1 -1
  371. package/lib/svg/SVGStringList.js.map +1 -1
  372. package/lib/svg/SVGTransformList.js +1 -1
  373. package/lib/svg/SVGTransformList.js.map +1 -1
  374. package/lib/tree-walker/NodeIterator.d.ts +18 -3
  375. package/lib/tree-walker/NodeIterator.d.ts.map +1 -1
  376. package/lib/tree-walker/NodeIterator.js +40 -6
  377. package/lib/tree-walker/NodeIterator.js.map +1 -1
  378. package/lib/tree-walker/TreeWalker.d.ts +2 -1
  379. package/lib/tree-walker/TreeWalker.d.ts.map +1 -1
  380. package/lib/tree-walker/TreeWalker.js +6 -6
  381. package/lib/tree-walker/TreeWalker.js.map +1 -1
  382. package/lib/utilities/ClassMethodBinder.d.ts.map +1 -0
  383. package/lib/utilities/ClassMethodBinder.js.map +1 -0
  384. package/lib/utilities/StringUtility.d.ts.map +1 -0
  385. package/lib/utilities/StringUtility.js.map +1 -0
  386. package/lib/utilities/XMLEncodeUtility.d.ts +48 -0
  387. package/lib/utilities/XMLEncodeUtility.d.ts.map +1 -0
  388. package/lib/utilities/XMLEncodeUtility.js +116 -0
  389. package/lib/utilities/XMLEncodeUtility.js.map +1 -0
  390. package/lib/window/BrowserWindow.d.ts +2 -0
  391. package/lib/window/BrowserWindow.d.ts.map +1 -1
  392. package/lib/window/BrowserWindow.js +9 -3
  393. package/lib/window/BrowserWindow.js.map +1 -1
  394. package/lib/window/WindowErrorUtility.js +1 -1
  395. package/lib/window/WindowErrorUtility.js.map +1 -1
  396. package/lib/xml-http-request/XMLHttpRequest.d.ts.map +1 -1
  397. package/lib/xml-http-request/XMLHttpRequest.js +2 -1
  398. package/lib/xml-http-request/XMLHttpRequest.js.map +1 -1
  399. package/lib/xml-http-request/XMLHttpRequestResponseDataParser.js +1 -1
  400. package/lib/xml-http-request/XMLHttpRequestResponseDataParser.js.map +1 -1
  401. package/lib/xml-parser/XMLParser.d.ts +89 -19
  402. package/lib/xml-parser/XMLParser.d.ts.map +1 -1
  403. package/lib/xml-parser/XMLParser.js +531 -242
  404. package/lib/xml-parser/XMLParser.js.map +1 -1
  405. package/lib/xml-serializer/XMLSerializer.d.ts +6 -17
  406. package/lib/xml-serializer/XMLSerializer.d.ts.map +1 -1
  407. package/lib/xml-serializer/XMLSerializer.js +136 -40
  408. package/lib/xml-serializer/XMLSerializer.js.map +1 -1
  409. package/package.json +1 -2
  410. package/src/PropertySymbol.ts +4 -1
  411. package/src/browser/utilities/BrowserFrameURL.ts +2 -2
  412. package/src/config/HTMLElementConfig.ts +53 -17
  413. package/src/config/HTMLElementConfigContentModelEnum.ts +3 -0
  414. package/src/config/NamespaceURI.ts +2 -0
  415. package/src/css/declaration/CSSStyleDeclaration.ts +1 -4
  416. package/src/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.ts +2 -4
  417. package/src/custom-element/CustomElementReactionStack.ts +81 -0
  418. package/src/custom-element/CustomElementRegistry.ts +35 -54
  419. package/src/custom-element/CustomElementUtility.ts +34 -0
  420. package/src/custom-element/ICustomElementDefinition.ts +16 -0
  421. package/src/dom/DOMStringMap.ts +12 -10
  422. package/src/dom/DOMTokenList.ts +1 -1
  423. package/src/dom-parser/DOMParser.ts +5 -75
  424. package/src/exception/DOMExceptionNameEnum.ts +2 -1
  425. package/src/history/History.ts +10 -10
  426. package/src/html-parser/HTMLParser.ts +864 -0
  427. package/src/html-serializer/HTMLSerializer.ts +162 -0
  428. package/src/nodes/document/Document.ts +118 -137
  429. package/src/nodes/element/Element.ts +48 -95
  430. package/src/nodes/element/HTMLCollection.ts +5 -30
  431. package/src/nodes/element/NamedNodeMap.ts +58 -72
  432. package/src/nodes/element/NamedNodeMapProxyFactory.ts +12 -15
  433. package/src/nodes/html-button-element/HTMLButtonElement.ts +1 -4
  434. package/src/nodes/html-document/HTMLDocument.ts +58 -2
  435. package/src/nodes/html-element/HTMLElement.ts +107 -25
  436. package/src/nodes/html-field-set-element/HTMLFieldSetElement.ts +1 -4
  437. package/src/nodes/html-form-element/HTMLFormElement.ts +5 -27
  438. package/src/nodes/html-iframe-element/HTMLIFrameElement.ts +1 -1
  439. package/src/nodes/html-input-element/HTMLInputElement.ts +1 -4
  440. package/src/nodes/html-media-element/TextTrackList.ts +1 -1
  441. package/src/nodes/html-object-element/HTMLObjectElement.ts +1 -4
  442. package/src/nodes/html-output-element/HTMLOutputElement.ts +1 -4
  443. package/src/nodes/html-script-element/HTMLScriptElement.ts +4 -1
  444. package/src/nodes/html-select-element/HTMLSelectElement.ts +2 -5
  445. package/src/nodes/html-table-element/HTMLTableElement.ts +8 -1
  446. package/src/nodes/html-table-row-element/HTMLTableRowElement.ts +1 -1
  447. package/src/nodes/html-template-element/HTMLTemplateElement.ts +23 -17
  448. package/src/nodes/html-text-area-element/HTMLTextAreaElement.ts +1 -4
  449. package/src/nodes/node/Node.ts +57 -70
  450. package/src/nodes/node/NodeList.ts +1 -1
  451. package/src/nodes/node/NodeUtility.ts +4 -3
  452. package/src/nodes/parent-node/ParentNodeUtility.ts +6 -6
  453. package/src/nodes/shadow-root/ShadowRoot.ts +8 -8
  454. package/src/nodes/xml-document/XMLDocument.ts +5 -1
  455. package/src/query-selector/SelectorItem.ts +1 -2
  456. package/src/range/Range.ts +3 -3
  457. package/src/storage/Storage.ts +1 -1
  458. package/src/svg/SVGLengthList.ts +1 -1
  459. package/src/svg/SVGNumberList.ts +1 -1
  460. package/src/svg/SVGPointList.ts +1 -1
  461. package/src/svg/SVGStringList.ts +1 -1
  462. package/src/svg/SVGTransformList.ts +1 -1
  463. package/src/tree-walker/NodeIterator.ts +44 -8
  464. package/src/tree-walker/TreeWalker.ts +6 -6
  465. package/src/utilities/XMLEncodeUtility.ts +127 -0
  466. package/src/window/BrowserWindow.ts +18 -5
  467. package/src/window/WindowErrorUtility.ts +1 -1
  468. package/src/xml-http-request/XMLHttpRequest.ts +3 -1
  469. package/src/xml-http-request/XMLHttpRequestResponseDataParser.ts +1 -1
  470. package/src/xml-parser/XMLParser.ts +627 -313
  471. package/src/xml-serializer/XMLSerializer.ts +204 -58
  472. package/cjs/ClassMethodBinder.cjs.map +0 -1
  473. package/cjs/ClassMethodBinder.d.ts.map +0 -1
  474. package/cjs/StringUtility.cjs.map +0 -1
  475. package/cjs/StringUtility.d.ts.map +0 -1
  476. package/lib/ClassMethodBinder.d.ts.map +0 -1
  477. package/lib/ClassMethodBinder.js.map +0 -1
  478. package/lib/StringUtility.d.ts.map +0 -1
  479. package/lib/StringUtility.js.map +0 -1
  480. /package/cjs/{ClassMethodBinder.cjs → utilities/ClassMethodBinder.cjs} +0 -0
  481. /package/cjs/{ClassMethodBinder.d.ts → utilities/ClassMethodBinder.d.ts} +0 -0
  482. /package/cjs/{StringUtility.cjs → utilities/StringUtility.cjs} +0 -0
  483. /package/cjs/{StringUtility.d.ts → utilities/StringUtility.d.ts} +0 -0
  484. /package/lib/{ClassMethodBinder.d.ts → utilities/ClassMethodBinder.d.ts} +0 -0
  485. /package/lib/{ClassMethodBinder.js → utilities/ClassMethodBinder.js} +0 -0
  486. /package/lib/{StringUtility.d.ts → utilities/StringUtility.d.ts} +0 -0
  487. /package/lib/{StringUtility.js → utilities/StringUtility.js} +0 -0
  488. /package/src/{ClassMethodBinder.ts → utilities/ClassMethodBinder.ts} +0 -0
  489. /package/src/{StringUtility.ts → utilities/StringUtility.ts} +0 -0
@@ -1,17 +1,10 @@
1
- import Document from '../nodes/document/Document.js';
2
1
  import * as PropertySymbol from '../PropertySymbol.js';
3
2
  import NamespaceURI from '../config/NamespaceURI.js';
4
- import HTMLScriptElement from '../nodes/html-script-element/HTMLScriptElement.js';
5
3
  import Element from '../nodes/element/Element.js';
6
- import HTMLLinkElement from '../nodes/html-link-element/HTMLLinkElement.js';
7
- import DocumentType from '../nodes/document-type/DocumentType.js';
8
4
  import Node from '../nodes/node/Node.js';
9
- import DocumentFragment from '../nodes/document-fragment/DocumentFragment.js';
10
- import HTMLElementConfig from '../config/HTMLElementConfig.js';
11
- import * as Entities from 'entities';
12
- import HTMLElementConfigContentModelEnum from '../config/HTMLElementConfigContentModelEnum.js';
13
- import SVGElementConfig from '../config/SVGElementConfig.js';
14
- import StringUtility from '../StringUtility.js';
5
+ import BrowserWindow from '../window/BrowserWindow.js';
6
+ import XMLDocument from '../nodes/xml-document/XMLDocument.js';
7
+ import XMLEncodeUtility from '../utilities/XMLEncodeUtility.js';
15
8
 
16
9
  /**
17
10
  * Markup RegExp.
@@ -25,30 +18,31 @@ import StringUtility from '../StringUtility.js';
25
18
  * Group 7: End of self closing start tag (e.g. "/>" in "<img/>").
26
19
  * Group 8: End of start tag (e.g. ">" in "<div>").
27
20
  */
28
- const MARKUP_REGEXP =
29
- /<([^\s/!>?]+)|<\/([^\s/!>?]+)\s*>|<!--([^-]+)-->|<!--([^>]+)>|<!([^>]*)>|<\?([^>]+)>|(\/>)|(>)/gm;
21
+ const MARKUP_REGEXP = /<([^\s/!>?]+)|<\/([^\s/!>?]+)\s*>|(<!--)|(-->)|(<!)|(<\?)|(\/>)|(>)/gm;
30
22
 
31
23
  /**
32
24
  * Attribute RegExp.
33
25
  *
34
26
  * Group 1: Attribute name when the attribute has a value using double apostrophe (e.g. "name" in "<div name="value">").
35
27
  * Group 2: Attribute value when the attribute has a value using double apostrophe (e.g. "value" in "<div name="value">").
36
- * Group 3: Attribute name when the attribute has a value using double apostrophe (e.g. "name" in "<div name="value">").
37
- * Group 4: Attribute value when the attribute has a value using double apostrophe (e.g. "value" in "<div name="value">").
38
- * Group 5: Attribute end apostrophe when the attribute has a value using double apostrophe (e.g. '"' in "<div name="value">").
39
- * Group 6: Attribute name when the attribute has a value using single apostrophe (e.g. "name" in "<div name='value'>").
40
- * Group 7: Attribute value when the attribute has a value using single apostrophe (e.g. "value" in "<div name='value'>").
41
- * Group 8: Attribute end apostrophe when the attribute has a value using single apostrophe (e.g. "'" in "<div name='value'>").
42
- * Group 9: Attribute name when the attribute has no value (e.g. "disabled" in "<div disabled>").
28
+ * Group 3: Attribute end apostrophe when the attribute has a value using double apostrophe (e.g. '"' in "<div name="value">").
29
+ * Group 4: Attribute name when the attribute has a value using single apostrophe (e.g. "name" in "<div name='value'>").
30
+ * Group 5: Attribute value when the attribute has a value using single apostrophe (e.g. "value" in "<div name='value'>").
31
+ * Group 6: Attribute end apostrophe when the attribute has a value using single apostrophe (e.g. "'" in "<div name='value'>").
32
+ * Group 7: Attribute name when the attribute has no value (e.g. "disabled" in "<div disabled>").
43
33
  */
44
34
  const ATTRIBUTE_REGEXP =
45
- /\s*([a-zA-Z0-9-_:.$@?\\]+) *= *([a-zA-Z0-9-_:.$@?{}/]+)|\s*([a-zA-Z0-9-_:.$@?\\]+) *= *"([^"]*)("{0,1})|\s*([a-zA-Z0-9-_:.$@?\\]+) *= *'([^']*)('{0,1})|\s*([a-zA-Z0-9-_:.$@?\\]+)/gm;
35
+ /\s*([a-zA-Z0-9-_:]+)\s*=\s*"([^"]*)("{0,1})|\s*([a-zA-Z0-9-_:]+)\s*=\s*'([^']*)('{0,1})/gm;
46
36
 
47
- enum MarkupReadStateEnum {
48
- startOrEndTag = 'startOrEndTag',
49
- insideStartTag = 'insideStartTag',
50
- plainTextContent = 'plainTextContent'
51
- }
37
+ /**
38
+ * Attribute without value RegExp.
39
+ */
40
+ const ATTRIBUTE_WITHOUT_VALUE_REGEXP = /^\s*([a-zA-Z0-9-_:]+)$/;
41
+
42
+ /**
43
+ * XML processing instruction version RegExp.
44
+ */
45
+ const XML_PROCESSING_INSTRUCTION_VERSION_REGEXP = /version="[^"]+"/;
52
46
 
53
47
  /**
54
48
  * Document type attribute RegExp.
@@ -57,333 +51,653 @@ enum MarkupReadStateEnum {
57
51
  */
58
52
  const DOCUMENT_TYPE_ATTRIBUTE_REGEXP = /"([^"]+)"/gm;
59
53
 
54
+ /**
55
+ * Space RegExp.
56
+ */
57
+ const SPACE_REGEXP = /\s+/;
58
+
59
+ /**
60
+ * New line RegExp.
61
+ */
62
+ const NEW_LINE_REGEXP = /\n/g;
63
+
64
+ /**
65
+ * Markup read state (which state the parser is in).
66
+ */
67
+ enum MarkupReadStateEnum {
68
+ any = 'any',
69
+ startTag = 'startTag',
70
+ comment = 'comment',
71
+ documentType = 'documentType',
72
+ processingInstruction = 'processingInstruction',
73
+ error = 'error'
74
+ }
75
+
76
+ /**
77
+ * Document type.
78
+ */
79
+ interface IDocumentType {
80
+ name: string;
81
+ publicId: string;
82
+ systemId: string;
83
+ }
84
+
85
+ const NAMESPACE_URIS = Object.values(NamespaceURI);
86
+
60
87
  /**
61
88
  * XML parser.
62
- *
63
- * @see https://html.spec.whatwg.org/multipage/indices.html
64
89
  */
65
90
  export default class XMLParser {
91
+ private window: BrowserWindow;
92
+ private rootNode: XMLDocument | null = null;
93
+ private nodeStack: Node[] = [];
94
+ private tagNameStack: string[] = [];
95
+ private defaultNamespaceStack: string[] | null = null;
96
+ private namespacePrefixStack: Array<Map<string, string>> | null = null;
97
+ private startTagIndex = 0;
98
+ private markupRegExp: RegExp | null = null;
99
+ private lastIndex = 0;
100
+ private errorIndex = 0;
101
+ private nextElement: Element | null = null;
102
+ private nextTagName: string | null = null;
103
+ private currentNode: Node | null = null;
104
+ private readState: MarkupReadStateEnum = MarkupReadStateEnum.any;
105
+ private errorMessage: string | null = null;
106
+
66
107
  /**
67
- * Parses XML/HTML and returns a root element.
108
+ * Constructor.
68
109
  *
69
- * @param document Document.
70
- * @param xml XML/HTML string.
110
+ * @param window Window.
71
111
  * @param [options] Options.
72
- * @param [options.rootNode] Node to append elements to. Otherwise a new DocumentFragment is created.
73
- * @param [options.evaluateScripts = false] Set to "true" to enable script execution.
74
- * @returns Root node.
112
+ * @param [options.mode] Mode. Defaults to "htmlFragment".
113
+ * @param [options.evaluateScripts] Set to "true" to enable script execution
75
114
  */
76
- public static parse(
77
- document: Document,
78
- xml: string,
79
- options?: { rootNode?: Element | DocumentFragment | Document; evaluateScripts?: boolean }
80
- ): Element | DocumentFragment | Document {
81
- const root = options && options.rootNode ? options.rootNode : document.createDocumentFragment();
82
- const nodeStack: Node[] = [root];
83
- const localNameStack: string[] = [null];
84
- const markupRegexp = new RegExp(MARKUP_REGEXP, 'gm');
85
- const { evaluateScripts = false } = options || {};
86
- let newNode: Node | null = null;
87
- let currentNode: Node | null = root;
115
+ constructor(window: BrowserWindow) {
116
+ this.window = window;
117
+ }
118
+ /**
119
+ * Parses XML and returns an XML document containing nodes found.
120
+ *
121
+ * @param xml XML string.
122
+ * @returns XML document.
123
+ */
124
+ public parse(xml: string): XMLDocument {
125
+ this.rootNode = new this.window.XMLDocument();
126
+ this.nodeStack = [this.rootNode];
127
+ this.tagNameStack = [null];
128
+ this.currentNode = this.rootNode;
129
+ this.readState = <MarkupReadStateEnum>MarkupReadStateEnum.any;
130
+ this.defaultNamespaceStack = [null];
131
+ this.namespacePrefixStack = [null];
132
+ this.startTagIndex = 0;
133
+ this.errorIndex = 0;
134
+ this.errorMessage = null;
135
+ this.markupRegExp = new RegExp(MARKUP_REGEXP, 'gm');
136
+ this.lastIndex = 0;
88
137
  let match: RegExpExecArray;
89
- let readState: MarkupReadStateEnum = MarkupReadStateEnum.startOrEndTag;
90
- let startTagIndex = 0;
91
- let lastIndex = 0;
92
-
93
- if (xml !== null && xml !== undefined) {
94
- xml = String(xml);
95
-
96
- while ((match = markupRegexp.exec(xml))) {
97
- switch (readState) {
98
- case MarkupReadStateEnum.startOrEndTag:
99
- if (
100
- match.index !== lastIndex &&
101
- (match[1] || match[2] || match[3] || match[4] || match[5] !== undefined || match[6])
102
- ) {
103
- // Plain text between tags.
104
- currentNode[PropertySymbol.appendChild](
105
- document.createTextNode(Entities.decodeHTML(xml.substring(lastIndex, match.index))),
106
- true
107
- );
138
+
139
+ this.rootNode[PropertySymbol.defaultView] = this.window;
140
+
141
+ xml = String(xml);
142
+
143
+ while ((match = this.markupRegExp.exec(xml))) {
144
+ switch (this.readState) {
145
+ case MarkupReadStateEnum.any:
146
+ if (
147
+ match.index !== this.lastIndex &&
148
+ (match[1] || match[2] || match[3] || match[4] || match[5] !== undefined || match[6])
149
+ ) {
150
+ // Plain text between tags.
151
+ this.parsePlainText(xml.substring(this.lastIndex, match.index));
152
+ }
153
+
154
+ if (match[1]) {
155
+ // Start tag.
156
+ this.parseStartTag(match[1]);
157
+ } else if (match[2]) {
158
+ // End tag.
159
+ if (!this.parseEndTag(match[2])) {
160
+ this.errorMessage = `Opening and ending tag mismatch: ${
161
+ this.tagNameStack[this.tagNameStack.length - 1]
162
+ } line ${xml.substring(0, this.startTagIndex).split('\n').length} and ${match[2]}\n`;
163
+ this.errorIndex = this.markupRegExp.lastIndex;
164
+ this.readState = MarkupReadStateEnum.error;
165
+ this.removeOverflowingTextNodes();
108
166
  }
167
+ } else if (match[3]) {
168
+ // Comment.
169
+ this.startTagIndex = this.markupRegExp.lastIndex;
170
+ this.readState = MarkupReadStateEnum.comment;
171
+ } else if (match[5] !== undefined) {
172
+ // Document type
173
+ this.startTagIndex = this.markupRegExp.lastIndex;
174
+ this.readState = MarkupReadStateEnum.documentType;
175
+ } else if (match[6]) {
176
+ // Processing instruction.
177
+ this.startTagIndex = this.markupRegExp.lastIndex;
178
+ this.readState = MarkupReadStateEnum.processingInstruction;
179
+ } else {
180
+ // Plain text between tags, including the matched tag as it is not a valid start or end tag.
181
+ this.parsePlainText(xml.substring(this.lastIndex, this.markupRegExp.lastIndex));
182
+ }
183
+
184
+ break;
185
+ case MarkupReadStateEnum.startTag:
186
+ // End of start tag
187
+
188
+ // match[7] is matching "/>" (e.g. "<img/>").
189
+ // match[8] is matching ">" (e.g. "<div>").
190
+ if (match[7] || match[8]) {
191
+ const attributeString = xml.substring(
192
+ this.startTagIndex,
193
+ match[2] ? this.markupRegExp.lastIndex - 1 : match.index
194
+ );
195
+ const isSelfClosed = !!match[7];
196
+
197
+ this.parseEndOfStartTag(attributeString, isSelfClosed);
198
+ } else {
199
+ this.errorMessage =
200
+ match[2] && this.lastIndex !== this.startTagIndex
201
+ ? `Unescaped '&lt;' not allowed in attributes values\n`
202
+ : 'error parsing attribute name\n';
203
+ this.errorIndex = match.index;
204
+ this.readState = MarkupReadStateEnum.error;
205
+ this.removeOverflowingTextNodes();
206
+ }
207
+ break;
208
+ case MarkupReadStateEnum.comment:
209
+ // Comment end tag.
210
+
211
+ if (match[4]) {
212
+ this.parseComment(xml.substring(this.startTagIndex, match.index));
213
+ }
214
+ break;
215
+ case MarkupReadStateEnum.documentType:
216
+ // Document type end tag.
217
+
218
+ if (match[7] || match[8]) {
219
+ this.parseDocumentType(xml.substring(this.startTagIndex, match.index));
220
+ }
221
+ break;
222
+ case MarkupReadStateEnum.processingInstruction:
223
+ // Processing instruction end tag.
224
+
225
+ if (match[7] || match[8]) {
226
+ this.parseProcessingInstruction(xml.substring(this.startTagIndex, match.index));
227
+ }
228
+ break;
229
+ case MarkupReadStateEnum.error:
230
+ this.parseError(xml.slice(0, this.errorIndex), this.errorMessage);
231
+ return this.rootNode;
232
+ }
109
233
 
110
- if (match[1]) {
111
- // Start tag.
112
- const name = StringUtility.asciiLowerCase(match[1]);
113
-
114
- // NamespaceURI is inherited from the parent element.
115
- // NamespaceURI should be SVG for SVGSVGElement.
116
- const namespaceURI =
117
- name === 'svg'
118
- ? NamespaceURI.svg
119
- : (<Element>currentNode)[PropertySymbol.namespaceURI] || NamespaceURI.html;
120
-
121
- // SVG elements are resolved to their local name during parsing.
122
- // This should probably be handled in an XML document.
123
- const qualifiedName =
124
- namespaceURI === NamespaceURI.svg && SVGElementConfig[name]
125
- ? SVGElementConfig[name].localName
126
- : name;
127
-
128
- // Create a new element.
129
- newNode = document.createElementNS(namespaceURI, qualifiedName);
130
-
131
- readState = MarkupReadStateEnum.insideStartTag;
132
- startTagIndex = markupRegexp.lastIndex;
133
- } else if (match[2]) {
134
- // End tag.
135
-
136
- // We close all tags up until the first tag that matches the end tag.
137
- const localName = StringUtility.asciiLowerCase(match[2]);
138
- const index = localNameStack.lastIndexOf(localName);
139
- if (index !== -1) {
140
- nodeStack.splice(index, nodeStack.length - index);
141
- localNameStack.splice(index, localNameStack.length - index);
142
- currentNode = nodeStack[nodeStack.length - 1] || root;
143
- }
144
- } else if (
145
- match[3] ||
146
- match[4] ||
147
- (match[6] &&
148
- (<Element>currentNode)[PropertySymbol.namespaceURI] === NamespaceURI.html)
149
- ) {
150
- // Comment.
151
-
152
- let comment: string;
153
-
154
- if (match[3]) {
155
- comment = match[3];
156
- } else if (match[4]) {
157
- comment = match[4].endsWith('--') ? match[4].slice(0, -2) : match[4];
158
- } else {
159
- comment = '?' + match[6];
160
- }
234
+ this.lastIndex = this.markupRegExp.lastIndex;
235
+ }
161
236
 
162
- currentNode[PropertySymbol.appendChild](
163
- document.createComment(Entities.decodeHTML(comment)),
164
- true
165
- );
166
- } else if (match[5] !== undefined) {
167
- // Exclamation mark comment.
168
- // Document type node or comment.
169
- const exclamationComment = Entities.decodeHTML(match[5]);
170
- currentNode[PropertySymbol.appendChild](
171
- this.getDocumentTypeNode(document, exclamationComment) ||
172
- document.createComment(exclamationComment),
173
- true
174
- );
175
- } else if (match[6]) {
176
- // Processing instruction (not supported by HTML).
177
- // TODO: Add support for processing instructions.
178
- } else {
179
- // Plain text between tags, including the match as it is not a valid start or end tag.
180
-
181
- currentNode[PropertySymbol.appendChild](
182
- document.createTextNode(
183
- Entities.decodeHTML(xml.substring(lastIndex, markupRegexp.lastIndex))
184
- ),
185
- true
186
- );
187
- }
237
+ if (this.readState === MarkupReadStateEnum.error) {
238
+ this.parseError(xml.slice(0, this.errorIndex), this.errorMessage);
239
+ return this.rootNode;
240
+ }
188
241
 
189
- break;
190
- case MarkupReadStateEnum.insideStartTag:
191
- // End of start tag
192
- if (match[7] || match[8]) {
193
- // Attribute name and value.
194
-
195
- const attributeString = xml.substring(startTagIndex, match.index);
196
- let hasAttributeStringEnded = true;
197
-
198
- if (!!attributeString) {
199
- const attributeRegexp = new RegExp(ATTRIBUTE_REGEXP, 'gm');
200
- let attributeMatch: RegExpExecArray;
201
-
202
- while ((attributeMatch = attributeRegexp.exec(attributeString))) {
203
- if (
204
- (attributeMatch[1] && attributeMatch[2]) ||
205
- (attributeMatch[3] && attributeMatch[5] === '"') ||
206
- (attributeMatch[6] && attributeMatch[8] === "'") ||
207
- attributeMatch[9]
208
- ) {
209
- // Valid attribute name and value.
210
- const name =
211
- attributeMatch[1] ||
212
- attributeMatch[3] ||
213
- attributeMatch[6] ||
214
- attributeMatch[9] ||
215
- '';
216
- const rawValue =
217
- attributeMatch[2] || attributeMatch[4] || attributeMatch[7] || '';
218
- const value = rawValue ? Entities.decodeHTMLAttribute(rawValue) : '';
219
-
220
- if ((<Element>newNode)[PropertySymbol.namespaceURI] === NamespaceURI.svg) {
221
- // In XML and SVG namespaces, the attribute "xmlns" should be set to the "http://www.w3.org/2000/xmlns/" namespace.
222
- const attributeItem = document.createAttributeNS(
223
- name === 'xmlns' ? NamespaceURI.xmlns : null,
224
- name
225
- );
226
- attributeItem[PropertySymbol.value] = value;
227
- (<Element>newNode)[PropertySymbol.attributes][PropertySymbol.setNamedItem](
228
- attributeItem
229
- );
230
- } else {
231
- const attributeItem = document.createAttribute(name);
232
- attributeItem[PropertySymbol.value] = value;
233
- (<Element>newNode)[PropertySymbol.attributes][PropertySymbol.setNamedItem](
234
- attributeItem
235
- );
236
- }
237
-
238
- startTagIndex += attributeMatch[0].length;
239
- } else if (
240
- !attributeMatch[1] &&
241
- ((attributeMatch[3] && !attributeMatch[5]) ||
242
- (attributeMatch[6] && !attributeMatch[8]))
243
- ) {
244
- // End attribute apostrophe is missing (e.g. "attr='value" or 'attr="value').
245
- hasAttributeStringEnded = false;
246
- break;
247
- }
248
- }
249
- }
242
+ if (this.readState === MarkupReadStateEnum.comment) {
243
+ this.parseError(xml, 'Comment not terminated\n');
244
+ this.removeOverflowingTextNodes();
245
+ return this.rootNode;
246
+ }
250
247
 
251
- // We need to check if the attribute string is read completely.
252
- // The attribute string can potentially contain "/>" or ">".
253
- if (hasAttributeStringEnded) {
254
- const config = HTMLElementConfig[(<Element>newNode)[PropertySymbol.localName]];
255
- const localName = StringUtility.asciiLowerCase(
256
- (<Element>newNode)[PropertySymbol.localName]
257
- );
248
+ // Missing start tag (e.g. when parsing just a string like "Test").
249
+ if (this.rootNode[PropertySymbol.elementArray].length === 0) {
250
+ this.parseError('', `Start tag expected, '&lt;' not found`);
251
+ return this.rootNode;
252
+ }
258
253
 
259
- // Some elements are not allowed to be nested (e.g. "<a><a></a></a>" is not allowed.).
260
- // Therefore we need to auto-close the tag, so that it become valid (e.g. "<a></a><a></a>").
261
- if (
262
- config?.contentModel ===
263
- HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants &&
264
- localNameStack[localNameStack.length - 1] === localName
265
- ) {
266
- nodeStack.pop();
267
- localNameStack.pop();
268
- currentNode = nodeStack[nodeStack.length - 1] || root;
269
- } else if (
270
- config?.contentModel === HTMLElementConfigContentModelEnum.noSelfDescendants &&
271
- localNameStack.includes(localName)
272
- ) {
273
- while (currentNode !== root) {
274
- if ((<Element>currentNode)[PropertySymbol.localName] === localName) {
275
- nodeStack.pop();
276
- localNameStack.pop();
277
- currentNode = nodeStack[nodeStack.length - 1] || root;
278
- break;
279
- }
280
- nodeStack.pop();
281
- localNameStack.pop();
282
- currentNode = nodeStack[nodeStack.length - 1] || root;
283
- }
284
- }
254
+ // Plain text after tags.
255
+ if (this.lastIndex !== xml.length && this.currentNode) {
256
+ this.parsePlainText(xml.substring(this.lastIndex));
257
+ }
285
258
 
286
- // Appends the new node to its parent and sets is as current node.
287
- currentNode[PropertySymbol.appendChild](newNode, true);
288
- currentNode = newNode;
289
- nodeStack.push(currentNode);
290
- localNameStack.push(localName);
291
- newNode = null;
292
-
293
- // Checks if the tag is a self closing tag (ends with "/>") or void element.
294
- // When it is a self closing tag or void element it should be closed immediately.
295
- // Self closing tags are not allowed in the HTML namespace, but the parser should still allow it for void elements.
296
- // Self closing tags is supported in the SVG namespace.
297
- if (
298
- config?.contentModel === HTMLElementConfigContentModelEnum.noDescendants ||
299
- // SVG tag is self closing (<svg/>).
300
- (match[7] &&
301
- (<Element>currentNode)[PropertySymbol.namespaceURI] === NamespaceURI.svg)
302
- ) {
303
- nodeStack.pop();
304
- localNameStack.pop();
305
- currentNode = nodeStack[nodeStack.length - 1] || root;
306
- readState = MarkupReadStateEnum.startOrEndTag;
307
- } else {
308
- readState =
309
- config?.contentModel === HTMLElementConfigContentModelEnum.rawText
310
- ? MarkupReadStateEnum.plainTextContent
311
- : MarkupReadStateEnum.startOrEndTag;
312
- }
259
+ // Missing end tag.
260
+ if (this.nodeStack.length !== 1) {
261
+ this.parseError(
262
+ xml,
263
+ this.nextElement
264
+ ? 'attributes construct error\n'
265
+ : 'Premature end of data in tag article line 1\n'
266
+ );
267
+ return this.rootNode;
268
+ }
269
+
270
+ return this.rootNode;
271
+ }
272
+
273
+ /**
274
+ * Parses plain text.
275
+ *
276
+ * @param text Text.
277
+ */
278
+ private parsePlainText(text: string): void {
279
+ if (this.currentNode === this.rootNode) {
280
+ const xmlText = text.replace(SPACE_REGEXP, '');
281
+ if (xmlText) {
282
+ this.errorMessage = 'Extra content at the end of the document\n';
283
+ this.errorIndex = this.lastIndex;
284
+ this.readState = MarkupReadStateEnum.error;
285
+ }
286
+ } else if (text.includes('&nbsp;')) {
287
+ this.errorMessage = `Entity 'nbsp' not defined\n`;
288
+ this.errorIndex = this.lastIndex + text.indexOf('&nbsp;') + 6;
289
+ this.readState = MarkupReadStateEnum.error;
290
+ } else {
291
+ this.currentNode[PropertySymbol.appendChild](
292
+ this.rootNode.createTextNode(XMLEncodeUtility.decodeXMLEntities(text)),
293
+ true
294
+ );
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Parses processing instruction.
300
+ *
301
+ * @param text Text.
302
+ */
303
+ private parseProcessingInstruction(text: string): void {
304
+ const parts = text.split(SPACE_REGEXP);
305
+ const endsWithQuestionMark = text[text.length - 1] === '?';
306
+
307
+ if (parts[0] === 'xml') {
308
+ if (
309
+ this.currentNode !== this.rootNode ||
310
+ this.rootNode[PropertySymbol.nodeArray].length !== 0 ||
311
+ parts.length === 1
312
+ ) {
313
+ this.errorMessage = 'XML declaration allowed only at the start of the document\n';
314
+ this.errorIndex = this.markupRegExp.lastIndex - text.length + 2;
315
+ this.readState = MarkupReadStateEnum.error;
316
+ this.removeOverflowingTextNodes();
317
+ } else if (!XML_PROCESSING_INSTRUCTION_VERSION_REGEXP.test(parts[1])) {
318
+ this.errorMessage = 'Malformed declaration expecting version\n';
319
+ this.errorIndex = this.markupRegExp.lastIndex - text.length + 3;
320
+ this.readState = MarkupReadStateEnum.error;
321
+ } else if (!endsWithQuestionMark) {
322
+ this.errorMessage = 'Blank needed here\n';
323
+ this.errorIndex = this.markupRegExp.lastIndex - 1;
324
+ this.readState = MarkupReadStateEnum.error;
325
+ } else {
326
+ // When the processing instruction has "xml" as target, we should not add it as a child node.
327
+ // Instead we will store the state on the root node, so that it is added when serializing the document with XMLSerializer.
328
+ // TODO: We need to handle validation of encoding.
329
+ const name = parts[0];
330
+ // We need to remove the ending "?".
331
+ const content = parts.slice(1).join(' ').slice(0, -1);
332
+ this.rootNode[PropertySymbol.xmlProcessingInstruction] =
333
+ this.rootNode.createProcessingInstruction(name, content);
334
+ this.readState = MarkupReadStateEnum.any;
335
+ }
336
+ } else {
337
+ if (parts.length === 1 && !endsWithQuestionMark) {
338
+ this.errorMessage = 'ParsePI: PI processing-instruction space expected\n';
339
+ this.errorIndex = this.markupRegExp.lastIndex - 1;
340
+ this.readState = MarkupReadStateEnum.error;
341
+ } else if (parts.length > 1 && !endsWithQuestionMark) {
342
+ this.errorMessage = 'ParsePI: PI processing-instruction never end ...\n';
343
+ this.errorIndex = this.markupRegExp.lastIndex - 1;
344
+ this.readState = MarkupReadStateEnum.error;
345
+ } else {
346
+ const name = parts[0];
347
+ // We need to remove the ending "?".
348
+ const content = parts.slice(1).join(' ').slice(0, -1);
349
+ this.currentNode[PropertySymbol.appendChild](
350
+ this.rootNode.createProcessingInstruction(name, content),
351
+ true
352
+ );
353
+ this.readState = MarkupReadStateEnum.any;
354
+ }
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Parses comment.
360
+ *
361
+ * @param comment Comment.
362
+ */
363
+ private parseComment(comment: string): void {
364
+ // Comments are not allowed in the root when parsing XML.
365
+ if (this.currentNode !== this.rootNode) {
366
+ this.currentNode[PropertySymbol.appendChild](
367
+ this.rootNode.createComment(XMLEncodeUtility.decodeXMLEntities(comment)),
368
+ true
369
+ );
370
+ }
371
+ this.readState = MarkupReadStateEnum.any;
372
+ }
313
373
 
314
- startTagIndex = markupRegexp.lastIndex;
374
+ /**
375
+ * Parses document type.
376
+ *
377
+ * @param text Text.
378
+ */
379
+ private parseDocumentType(text: string): void {
380
+ if (
381
+ this.currentNode === this.rootNode &&
382
+ this.rootNode[PropertySymbol.nodeArray].length === 0
383
+ ) {
384
+ const documentType = this.getDocumentType(XMLEncodeUtility.decodeXMLEntities(text));
385
+
386
+ if (documentType?.name) {
387
+ this.rootNode[PropertySymbol.appendChild](
388
+ this.window.document.implementation.createDocumentType(
389
+ documentType.name,
390
+ documentType.publicId,
391
+ documentType.systemId
392
+ ),
393
+ true
394
+ );
395
+ this.readState = MarkupReadStateEnum.any;
396
+ } else if (documentType) {
397
+ this.errorMessage = 'xmlParseDocTypeDecl : no DOCTYPE name\n';
398
+ this.errorIndex = this.markupRegExp.lastIndex - text.length - 2;
399
+ this.readState = MarkupReadStateEnum.error;
400
+ } else {
401
+ this.errorMessage = 'StartTag: invalid element name\n';
402
+ this.errorIndex = this.markupRegExp.lastIndex - text.length - 2;
403
+ this.readState = MarkupReadStateEnum.error;
404
+ }
405
+ } else if (
406
+ this.currentNode === this.rootNode &&
407
+ this.rootNode[PropertySymbol.elementArray].length === 1
408
+ ) {
409
+ this.errorMessage = 'Extra content at the end of the document\n';
410
+ this.errorIndex = this.markupRegExp.lastIndex - text.length - 2;
411
+ this.readState = MarkupReadStateEnum.error;
412
+ } else {
413
+ this.errorMessage = 'StartTag: invalid element name\n';
414
+ this.errorIndex = this.markupRegExp.lastIndex - text.length - 2;
415
+ this.readState = MarkupReadStateEnum.error;
416
+ }
417
+ }
418
+
419
+ /**
420
+ * Parses start tag.
421
+ *
422
+ * @param tagName Tag name.
423
+ */
424
+ private parseStartTag(tagName: string): void {
425
+ const parts = tagName.split(':');
426
+
427
+ if (parts.length > 1) {
428
+ this.nextElement = this.rootNode.createElementNS(
429
+ this.namespacePrefixStack[this.namespacePrefixStack.length - 1]?.get(parts[0]) || null,
430
+ tagName
431
+ );
432
+ } else {
433
+ this.nextElement = this.rootNode.createElementNS(
434
+ this.defaultNamespaceStack[this.defaultNamespaceStack.length - 1] || null,
435
+ tagName
436
+ );
437
+ }
438
+
439
+ this.namespacePrefixStack.push(
440
+ new Map(this.namespacePrefixStack[this.namespacePrefixStack.length - 1])
441
+ );
442
+
443
+ this.nextTagName = tagName;
444
+
445
+ this.startTagIndex = this.markupRegExp.lastIndex;
446
+ this.readState = MarkupReadStateEnum.startTag;
447
+ }
448
+
449
+ /**
450
+ * Parses end of start tag.
451
+ *
452
+ * @param attributeString Attribute string.
453
+ * @param isSelfClosed Is self closed.
454
+ */
455
+ private parseEndOfStartTag(attributeString: string, isSelfClosed: boolean): void {
456
+ const namespacePrefix = this.namespacePrefixStack[this.namespacePrefixStack.length - 1];
457
+
458
+ if (attributeString) {
459
+ const attributeRegexp = new RegExp(ATTRIBUTE_REGEXP, 'gm');
460
+ let attributeMatch: RegExpExecArray;
461
+ let lastIndex = 0;
462
+
463
+ while ((attributeMatch = attributeRegexp.exec(attributeString))) {
464
+ const textBetweenAttributes = attributeString
465
+ .substring(lastIndex, attributeMatch.index)
466
+ .replace(SPACE_REGEXP, '');
467
+
468
+ // If there is text between attributes, the text did not match a valid attribute.
469
+ if (textBetweenAttributes.length) {
470
+ const match = textBetweenAttributes.match(ATTRIBUTE_WITHOUT_VALUE_REGEXP);
471
+ this.errorMessage = match
472
+ ? `Specification mandates value for attribute ${match[1]}\n`
473
+ : 'attributes construct error\n';
474
+ this.errorIndex = this.startTagIndex;
475
+ this.readState = MarkupReadStateEnum.error;
476
+ this.removeOverflowingTextNodes();
477
+ return;
478
+ }
479
+
480
+ if (
481
+ (attributeMatch[1] && attributeMatch[3] === '"') ||
482
+ (attributeMatch[4] && attributeMatch[6] === "'")
483
+ ) {
484
+ // Valid attribute name and value.
485
+ const name = attributeMatch[1] ?? attributeMatch[4];
486
+ const rawValue = attributeMatch[2] ?? attributeMatch[5];
487
+
488
+ // In XML, new line characters should be replaced with a space.
489
+ const value = rawValue
490
+ ? XMLEncodeUtility.decodeAttributeValue(rawValue.replace(NEW_LINE_REGEXP, ' '))
491
+ : '';
492
+ const attributes = this.nextElement[PropertySymbol.attributes];
493
+ const nameParts = name.split(':');
494
+
495
+ if (
496
+ nameParts.length > 2 ||
497
+ (nameParts.length === 2 && (!nameParts[0] || !nameParts[1]))
498
+ ) {
499
+ this.errorMessage = `Failed to parse QName '${name}'\n`;
500
+ this.errorIndex =
501
+ this.startTagIndex + attributeMatch.index + attributeMatch[0].split('=')[0].length;
502
+ this.readState = MarkupReadStateEnum.error;
503
+ return;
504
+ }
505
+
506
+ // In XML, attributes prefixed with "xmlns:" or named "xmlns" should be set to the "http://www.w3.org/2000/xmlns/" namespace.
507
+ const namespaceURI = nameParts[0] === 'xmlns' ? NamespaceURI.xmlns : null;
508
+
509
+ if (!attributes.getNamedItemNS(namespaceURI, name)) {
510
+ const attributeItem = this.rootNode.createAttributeNS(namespaceURI, name);
511
+ attributeItem[PropertySymbol.value] = value;
512
+ attributes[PropertySymbol.setNamedItem](attributeItem);
513
+
514
+ // Attributes prefixed with "xmlns:" should be added to the namespace prefix map, so that the prefix can be added as namespaceURI to elements using the prefix.
515
+ if (attributeItem[PropertySymbol.prefix] === 'xmlns') {
516
+ namespacePrefix.set(attributeItem[PropertySymbol.localName], value);
517
+
518
+ // If the prefix matches the current element, we should set the namespace URI of the element to the value of the attribute.
519
+ // We don't need to upgrade the element, as there are no defined element types using a prefix.
520
+ if (
521
+ this.nextElement[PropertySymbol.prefix] === attributeItem[PropertySymbol.localName]
522
+ ) {
523
+ this.nextElement[PropertySymbol.namespaceURI] = value;
315
524
  }
316
525
  }
317
-
318
- break;
319
- case MarkupReadStateEnum.plainTextContent:
320
- const localName = currentNode[PropertySymbol.localName];
321
-
322
- if (localName && match[2] && StringUtility.asciiLowerCase(match[2]) === localName) {
323
- // End of plain text tag.
324
-
325
- // Scripts are not allowed to be executed when they are parsed using innerHTML, outerHTML, replaceWith() etc.
326
- // However, they are allowed to be executed when document.write() is used.
327
- // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement
328
- if (localName === 'script') {
329
- (<HTMLScriptElement>currentNode)[PropertySymbol.evaluateScript] = evaluateScripts;
330
- } else if (localName === 'link') {
331
- // An assumption that the same rule should be applied for the HTMLLinkElement is made here.
332
- (<HTMLLinkElement>currentNode)[PropertySymbol.evaluateCSS] = evaluateScripts;
526
+ // If the attribute is "xmlns", we should upgrade the element to an element created using the namespace URI.
527
+ else if (name === 'xmlns' && !this.nextElement[PropertySymbol.prefix]) {
528
+ // We only need to create a new instance if it is a known namespace URI.
529
+ if (NAMESPACE_URIS.includes(value)) {
530
+ this.nextElement = this.rootNode.createElementNS(
531
+ value,
532
+ this.nextElement[PropertySymbol.tagName]
533
+ );
534
+ this.nextElement[PropertySymbol.attributes] = attributes;
535
+ attributes[PropertySymbol.ownerElement] = this.nextElement;
536
+ for (const attr of attributes[PropertySymbol.namespaceItems].values()) {
537
+ attr[PropertySymbol.ownerElement] = this.nextElement;
538
+ }
539
+ } else {
540
+ this.nextElement[PropertySymbol.namespaceURI] = value;
333
541
  }
334
-
335
- // Plain text elements such as <script> and <style> should only contain text.
336
- currentNode[PropertySymbol.appendChild](
337
- document.createTextNode(
338
- Entities.decodeHTML(xml.substring(startTagIndex, match.index))
339
- ),
340
- true
341
- );
342
-
343
- nodeStack.pop();
344
- localNameStack.pop();
345
- currentNode = nodeStack[nodeStack.length - 1] || root;
346
- readState = MarkupReadStateEnum.startOrEndTag;
347
542
  }
348
-
349
- break;
543
+ } else {
544
+ this.errorMessage = `Attribute ${name} redefined\n`;
545
+ this.errorIndex = this.startTagIndex;
546
+ this.readState = MarkupReadStateEnum.error;
547
+ }
548
+
549
+ this.startTagIndex += attributeMatch[0].length;
550
+ } else if (
551
+ (attributeMatch[1] && attributeMatch[3] !== '"') ||
552
+ (attributeMatch[4] && attributeMatch[6] !== "'")
553
+ ) {
554
+ // End attribute apostrophe is missing (e.g. "attr='value" or 'attr="value').
555
+ // We should continue to the next end of start tag match.
556
+ return;
350
557
  }
351
558
 
352
- lastIndex = markupRegexp.lastIndex;
559
+ lastIndex = attributeRegexp.lastIndex;
353
560
  }
354
561
 
355
- // We expected the "newNode" to be null if the start tag was closed correctly.
356
- // We should append the last node to the current node to correct it.
357
- if (newNode && currentNode) {
358
- currentNode[PropertySymbol.appendChild](newNode, true);
562
+ const attributeStringEnd = attributeString.substring(lastIndex).replace(SPACE_REGEXP, '');
563
+
564
+ if (attributeStringEnd.length) {
565
+ const match = attributeStringEnd.match(ATTRIBUTE_WITHOUT_VALUE_REGEXP);
566
+ if (match) {
567
+ this.errorMessage = `Specification mandates value for attribute ${match[1]}\n`;
568
+ this.errorIndex = this.markupRegExp.lastIndex - 2;
569
+ } else {
570
+ this.errorMessage = 'attributes construct error\n';
571
+ this.errorIndex = this.startTagIndex;
572
+ }
573
+ this.readState = MarkupReadStateEnum.error;
574
+ this.removeOverflowingTextNodes();
575
+ return;
359
576
  }
577
+ }
360
578
 
361
- if (lastIndex !== xml.length) {
362
- // Plain text after tags.
579
+ // Prefixed elements need to have a namespace URI defined by a prefixed "xmlns:" attribute either by a parent or in the current element.
580
+ if (this.nextElement[PropertySymbol.prefix] && !this.nextElement[PropertySymbol.namespaceURI]) {
581
+ this.errorMessage = `Namespace prefix ${
582
+ this.nextElement[PropertySymbol.prefix]
583
+ } on name is not defined\n`;
584
+ this.errorIndex = this.lastIndex;
585
+ this.readState = MarkupReadStateEnum.error;
586
+ return;
587
+ }
363
588
 
364
- currentNode[PropertySymbol.appendChild](
365
- document.createTextNode(Entities.decodeHTML(xml.substring(lastIndex))),
366
- true
589
+ // Only one document element is allowed in the document.
590
+ if (
591
+ this.currentNode === this.rootNode &&
592
+ this.rootNode[PropertySymbol.elementArray].length !== 0
593
+ ) {
594
+ this.errorMessage = 'Extra content at the end of the document\n';
595
+ this.errorIndex = this.lastIndex - this.nextElement[PropertySymbol.tagName].length - 1;
596
+ this.readState = MarkupReadStateEnum.error;
597
+ return;
598
+ }
599
+
600
+ this.currentNode[PropertySymbol.appendChild](this.nextElement, true);
601
+
602
+ // Sets the new element as the current node.
603
+ // XML nodes can be self closed using "/>"
604
+ if (!isSelfClosed) {
605
+ this.currentNode = this.nextElement;
606
+ this.nodeStack.push(this.currentNode);
607
+ this.tagNameStack.push(this.nextTagName);
608
+
609
+ if (
610
+ this.currentNode[PropertySymbol.namespaceURI] &&
611
+ !this.currentNode[PropertySymbol.prefix]
612
+ ) {
613
+ this.defaultNamespaceStack.push(this.currentNode[PropertySymbol.namespaceURI]);
614
+ } else {
615
+ this.defaultNamespaceStack.push(
616
+ this.defaultNamespaceStack[this.defaultNamespaceStack.length - 1]
367
617
  );
368
618
  }
369
619
  }
370
620
 
371
- return root;
621
+ this.nextElement = null;
622
+ this.nextTagName = null;
623
+ this.readState = MarkupReadStateEnum.any;
624
+ this.startTagIndex = this.markupRegExp.lastIndex;
372
625
  }
373
626
 
374
627
  /**
375
- * Returns document type node.
628
+ * Parses end tag.
629
+ *
630
+ * @param tagName Tag name.
631
+ * @returns True if the end tag was parsed, false otherwise.
632
+ */
633
+ private parseEndTag(tagName: string): boolean {
634
+ if (this.tagNameStack[this.tagNameStack.length - 1] === tagName) {
635
+ this.nodeStack.pop();
636
+ this.tagNameStack.pop();
637
+ this.namespacePrefixStack.pop();
638
+ this.defaultNamespaceStack.pop();
639
+ this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode;
640
+ return true;
641
+ }
642
+ return false;
643
+ }
644
+
645
+ /**
646
+ * Parses XML document error.
647
+ *
648
+ * @param readXML XML that has been read.
649
+ * @param errorMessage Error message.
650
+ */
651
+ private parseError(readXML: string, errorMessage: string): void {
652
+ let errorRoot: Element = (<XMLDocument>this.rootNode).documentElement;
653
+
654
+ if (!errorRoot) {
655
+ const documentElement = this.rootNode.createElementNS(NamespaceURI.html, 'html');
656
+ const body = this.rootNode.createElementNS(NamespaceURI.html, 'body');
657
+ documentElement.appendChild(body);
658
+ errorRoot = body;
659
+ this.rootNode[PropertySymbol.appendChild](documentElement, true);
660
+ }
661
+
662
+ const rows = readXML.split('\n');
663
+ const column = rows[rows.length - 1].length + 1;
664
+ const error = `error on line ${rows.length} at column ${column}: ${errorMessage}`;
665
+ const errorElement = this.rootNode.createElementNS(NamespaceURI.html, 'parsererror');
666
+
667
+ errorElement.setAttribute(
668
+ 'style',
669
+ 'display: block; white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black'
670
+ );
671
+ errorElement.innerHTML = `<h3>This page contains the following errors:</h3><div style="font-family:monospace;font-size:12px">${error}</div><h3>Below is a rendering of the page up to the first error.</h3>`;
672
+
673
+ errorRoot.insertBefore(errorElement, errorRoot.firstChild);
674
+ }
675
+
676
+ /**
677
+ * Removes overflowing text nodes in the current node.
678
+ *
679
+ * This needs to be done for some errors.
680
+ */
681
+ private removeOverflowingTextNodes(): void {
682
+ if (this.currentNode && this.currentNode !== this.rootNode) {
683
+ while (this.currentNode.lastChild?.[PropertySymbol.nodeType] === Node.TEXT_NODE) {
684
+ this.currentNode.removeChild(this.currentNode.lastChild);
685
+ }
686
+ }
687
+ }
688
+
689
+ /**
690
+ * Returns document type.
376
691
  *
377
- * @param document Document.
378
692
  * @param value Value.
379
- * @returns Document type node.
693
+ * @returns Document type.
380
694
  */
381
- private static getDocumentTypeNode(document: Document, value: string): DocumentType {
695
+ private getDocumentType(value: string): IDocumentType {
382
696
  if (!value.toUpperCase().startsWith('DOCTYPE')) {
383
697
  return null;
384
698
  }
385
699
 
386
- const docTypeSplit = value.split(' ');
700
+ const docTypeSplit = value.split(SPACE_REGEXP);
387
701
 
388
702
  if (docTypeSplit.length <= 1) {
389
703
  return null;
@@ -402,10 +716,10 @@ export default class XMLParser {
402
716
  const publicId = isPublic ? attributes[0] || '' : '';
403
717
  const systemId = isPublic ? attributes[1] || '' : attributes[0] || '';
404
718
 
405
- return document.implementation.createDocumentType(
406
- docTypeSplit[1].toLowerCase(),
719
+ return {
720
+ name: docTypeSplit[1].toLowerCase(),
407
721
  publicId,
408
722
  systemId
409
- );
723
+ };
410
724
  }
411
725
  }