happy-dom 15.11.7 → 16.0.1
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.
- package/cjs/PropertySymbol.cjs +12 -9
- package/cjs/PropertySymbol.cjs.map +1 -1
- package/cjs/PropertySymbol.d.ts +4 -1
- package/cjs/PropertySymbol.d.ts.map +1 -1
- package/cjs/config/HTMLElementConfig.cjs +42 -16
- package/cjs/config/HTMLElementConfig.cjs.map +1 -1
- package/cjs/config/HTMLElementConfig.d.ts +7 -0
- package/cjs/config/HTMLElementConfig.d.ts.map +1 -1
- package/cjs/config/HTMLElementConfigContentModelEnum.cjs +3 -0
- package/cjs/config/HTMLElementConfigContentModelEnum.cjs.map +1 -1
- package/cjs/config/HTMLElementConfigContentModelEnum.d.ts +3 -0
- package/cjs/config/HTMLElementConfigContentModelEnum.d.ts.map +1 -1
- package/cjs/config/NamespaceURI.cjs +2 -0
- package/cjs/config/NamespaceURI.cjs.map +1 -1
- package/cjs/config/NamespaceURI.d.ts +2 -0
- package/cjs/config/NamespaceURI.d.ts.map +1 -1
- package/cjs/css/declaration/CSSStyleDeclaration.cjs +1 -1
- package/cjs/css/declaration/CSSStyleDeclaration.cjs.map +1 -1
- package/cjs/css/declaration/CSSStyleDeclaration.d.ts.map +1 -1
- package/cjs/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.cjs +2 -2
- package/cjs/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.cjs.map +1 -1
- package/cjs/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.d.ts.map +1 -1
- package/cjs/css/rules/CSSStyleRule.cjs +1 -1
- package/cjs/css/rules/CSSStyleRule.cjs.map +1 -1
- package/cjs/css/rules/CSSStyleRule.d.ts +1 -1
- package/cjs/css/rules/CSSStyleRule.d.ts.map +1 -1
- package/cjs/custom-element/CustomElementReactionStack.cjs +104 -0
- package/cjs/custom-element/CustomElementReactionStack.cjs.map +1 -0
- package/cjs/custom-element/CustomElementReactionStack.d.ts +27 -0
- package/cjs/custom-element/CustomElementReactionStack.d.ts.map +1 -0
- package/cjs/custom-element/CustomElementRegistry.cjs +32 -45
- package/cjs/custom-element/CustomElementRegistry.cjs.map +1 -1
- package/cjs/custom-element/CustomElementRegistry.d.ts +2 -6
- package/cjs/custom-element/CustomElementRegistry.d.ts.map +1 -1
- package/cjs/custom-element/CustomElementUtility.cjs +35 -0
- package/cjs/custom-element/CustomElementUtility.cjs.map +1 -0
- package/cjs/custom-element/CustomElementUtility.d.ts +14 -0
- package/cjs/custom-element/CustomElementUtility.d.ts.map +1 -0
- package/cjs/custom-element/ICustomElementDefinition.cjs +3 -0
- package/cjs/custom-element/ICustomElementDefinition.cjs.map +1 -0
- package/cjs/custom-element/ICustomElementDefinition.d.ts +12 -0
- package/cjs/custom-element/ICustomElementDefinition.d.ts.map +1 -0
- package/cjs/dom/DOMStringMap.cjs +8 -8
- package/cjs/dom/DOMStringMap.cjs.map +1 -1
- package/cjs/dom/DOMStringMap.d.ts.map +1 -1
- package/cjs/dom/DOMTokenList.cjs +1 -1
- package/cjs/dom/DOMTokenList.cjs.map +1 -1
- package/cjs/dom-parser/DOMParser.cjs +5 -67
- package/cjs/dom-parser/DOMParser.cjs.map +1 -1
- package/cjs/dom-parser/DOMParser.d.ts +0 -1
- package/cjs/dom-parser/DOMParser.d.ts.map +1 -1
- package/cjs/exception/DOMExceptionNameEnum.cjs +1 -0
- package/cjs/exception/DOMExceptionNameEnum.cjs.map +1 -1
- package/cjs/exception/DOMExceptionNameEnum.d.ts +2 -1
- package/cjs/exception/DOMExceptionNameEnum.d.ts.map +1 -1
- package/cjs/history/History.cjs +6 -6
- package/cjs/history/History.cjs.map +1 -1
- package/cjs/html-parser/HTMLParser.cjs +726 -0
- package/cjs/html-parser/HTMLParser.cjs.map +1 -0
- package/cjs/html-parser/HTMLParser.d.ts +91 -0
- package/cjs/html-parser/HTMLParser.d.ts.map +1 -0
- package/cjs/html-serializer/HTMLSerializer.cjs +152 -0
- package/cjs/html-serializer/HTMLSerializer.cjs.map +1 -0
- package/cjs/html-serializer/HTMLSerializer.d.ts +36 -0
- package/cjs/html-serializer/HTMLSerializer.d.ts.map +1 -0
- package/cjs/nodes/document/Document.cjs +104 -120
- package/cjs/nodes/document/Document.cjs.map +1 -1
- package/cjs/nodes/document/Document.d.ts +8 -0
- package/cjs/nodes/document/Document.d.ts.map +1 -1
- package/cjs/nodes/element/Element.cjs +35 -53
- package/cjs/nodes/element/Element.cjs.map +1 -1
- package/cjs/nodes/element/Element.d.ts +2 -12
- package/cjs/nodes/element/Element.d.ts.map +1 -1
- package/cjs/nodes/element/HTMLCollection.cjs +5 -9
- package/cjs/nodes/element/HTMLCollection.cjs.map +1 -1
- package/cjs/nodes/element/HTMLCollection.d.ts.map +1 -1
- package/cjs/nodes/element/NamedNodeMap.cjs +39 -52
- package/cjs/nodes/element/NamedNodeMap.cjs.map +1 -1
- package/cjs/nodes/element/NamedNodeMap.d.ts +1 -16
- package/cjs/nodes/element/NamedNodeMap.d.ts.map +1 -1
- package/cjs/nodes/element/NamedNodeMapProxyFactory.cjs +12 -14
- package/cjs/nodes/element/NamedNodeMapProxyFactory.cjs.map +1 -1
- package/cjs/nodes/element/NamedNodeMapProxyFactory.d.ts.map +1 -1
- package/cjs/nodes/html-button-element/HTMLButtonElement.cjs +1 -1
- package/cjs/nodes/html-button-element/HTMLButtonElement.cjs.map +1 -1
- package/cjs/nodes/html-button-element/HTMLButtonElement.d.ts.map +1 -1
- package/cjs/nodes/html-document/HTMLDocument.cjs +33 -2
- package/cjs/nodes/html-document/HTMLDocument.cjs.map +1 -1
- package/cjs/nodes/html-document/HTMLDocument.d.ts +10 -0
- package/cjs/nodes/html-document/HTMLDocument.d.ts.map +1 -1
- package/cjs/nodes/html-element/HTMLElement.cjs +58 -22
- package/cjs/nodes/html-element/HTMLElement.cjs.map +1 -1
- package/cjs/nodes/html-element/HTMLElement.d.ts +34 -0
- package/cjs/nodes/html-element/HTMLElement.d.ts.map +1 -1
- package/cjs/nodes/html-field-set-element/HTMLFieldSetElement.cjs +1 -1
- package/cjs/nodes/html-field-set-element/HTMLFieldSetElement.cjs.map +1 -1
- package/cjs/nodes/html-field-set-element/HTMLFieldSetElement.d.ts.map +1 -1
- package/cjs/nodes/html-form-element/HTMLFormElement.cjs +5 -8
- package/cjs/nodes/html-form-element/HTMLFormElement.cjs.map +1 -1
- package/cjs/nodes/html-form-element/HTMLFormElement.d.ts.map +1 -1
- package/cjs/nodes/html-iframe-element/HTMLIFrameElement.cjs +1 -1
- package/cjs/nodes/html-iframe-element/HTMLIFrameElement.cjs.map +1 -1
- package/cjs/nodes/html-input-element/HTMLInputElement.cjs +1 -1
- package/cjs/nodes/html-input-element/HTMLInputElement.cjs.map +1 -1
- package/cjs/nodes/html-input-element/HTMLInputElement.d.ts.map +1 -1
- package/cjs/nodes/html-media-element/TextTrackList.cjs +1 -1
- package/cjs/nodes/html-media-element/TextTrackList.cjs.map +1 -1
- package/cjs/nodes/html-object-element/HTMLObjectElement.cjs +1 -1
- package/cjs/nodes/html-object-element/HTMLObjectElement.cjs.map +1 -1
- package/cjs/nodes/html-object-element/HTMLObjectElement.d.ts.map +1 -1
- package/cjs/nodes/html-output-element/HTMLOutputElement.cjs +1 -1
- package/cjs/nodes/html-output-element/HTMLOutputElement.cjs.map +1 -1
- package/cjs/nodes/html-output-element/HTMLOutputElement.d.ts.map +1 -1
- package/cjs/nodes/html-script-element/HTMLScriptElement.cjs +3 -1
- package/cjs/nodes/html-script-element/HTMLScriptElement.cjs.map +1 -1
- package/cjs/nodes/html-script-element/HTMLScriptElement.d.ts.map +1 -1
- package/cjs/nodes/html-select-element/HTMLSelectElement.cjs +2 -2
- package/cjs/nodes/html-select-element/HTMLSelectElement.cjs.map +1 -1
- package/cjs/nodes/html-select-element/HTMLSelectElement.d.ts.map +1 -1
- package/cjs/nodes/html-table-element/HTMLTableElement.cjs +9 -1
- package/cjs/nodes/html-table-element/HTMLTableElement.cjs.map +1 -1
- package/cjs/nodes/html-table-element/HTMLTableElement.d.ts.map +1 -1
- package/cjs/nodes/html-table-row-element/HTMLTableRowElement.cjs +1 -1
- package/cjs/nodes/html-template-element/HTMLTemplateElement.cjs +15 -17
- package/cjs/nodes/html-template-element/HTMLTemplateElement.cjs.map +1 -1
- package/cjs/nodes/html-template-element/HTMLTemplateElement.d.ts +2 -2
- package/cjs/nodes/html-template-element/HTMLTemplateElement.d.ts.map +1 -1
- package/cjs/nodes/html-text-area-element/HTMLTextAreaElement.cjs +1 -1
- package/cjs/nodes/html-text-area-element/HTMLTextAreaElement.cjs.map +1 -1
- package/cjs/nodes/html-text-area-element/HTMLTextAreaElement.d.ts.map +1 -1
- package/cjs/nodes/node/Node.cjs +44 -48
- package/cjs/nodes/node/Node.cjs.map +1 -1
- package/cjs/nodes/node/Node.d.ts +2 -10
- package/cjs/nodes/node/Node.d.ts.map +1 -1
- package/cjs/nodes/node/NodeList.cjs +1 -1
- package/cjs/nodes/node/NodeList.cjs.map +1 -1
- package/cjs/nodes/node/NodeUtility.cjs +4 -3
- package/cjs/nodes/node/NodeUtility.cjs.map +1 -1
- package/cjs/nodes/node/NodeUtility.d.ts.map +1 -1
- package/cjs/nodes/parent-node/ParentNodeUtility.cjs +5 -2
- package/cjs/nodes/parent-node/ParentNodeUtility.cjs.map +1 -1
- package/cjs/nodes/parent-node/ParentNodeUtility.d.ts.map +1 -1
- package/cjs/nodes/shadow-root/ShadowRoot.cjs +8 -8
- package/cjs/nodes/shadow-root/ShadowRoot.cjs.map +1 -1
- package/cjs/nodes/shadow-root/ShadowRoot.d.ts.map +1 -1
- package/cjs/nodes/xml-document/XMLDocument.cjs +26 -0
- package/cjs/nodes/xml-document/XMLDocument.cjs.map +1 -1
- package/cjs/nodes/xml-document/XMLDocument.d.ts +2 -0
- package/cjs/nodes/xml-document/XMLDocument.d.ts.map +1 -1
- package/cjs/query-selector/SelectorItem.cjs +1 -2
- package/cjs/query-selector/SelectorItem.cjs.map +1 -1
- package/cjs/query-selector/SelectorItem.d.ts.map +1 -1
- package/cjs/range/Range.cjs +3 -3
- package/cjs/range/Range.cjs.map +1 -1
- package/cjs/range/Range.d.ts.map +1 -1
- package/cjs/storage/Storage.cjs +1 -1
- package/cjs/storage/Storage.cjs.map +1 -1
- package/cjs/svg/SVGLengthList.cjs +1 -1
- package/cjs/svg/SVGLengthList.cjs.map +1 -1
- package/cjs/svg/SVGNumberList.cjs +1 -1
- package/cjs/svg/SVGNumberList.cjs.map +1 -1
- package/cjs/svg/SVGPointList.cjs +1 -1
- package/cjs/svg/SVGPointList.cjs.map +1 -1
- package/cjs/svg/SVGStringList.cjs +1 -1
- package/cjs/svg/SVGStringList.cjs.map +1 -1
- package/cjs/svg/SVGTransformList.cjs +1 -1
- package/cjs/svg/SVGTransformList.cjs.map +1 -1
- package/cjs/tree-walker/NodeIterator.cjs +63 -6
- package/cjs/tree-walker/NodeIterator.cjs.map +1 -1
- package/cjs/tree-walker/NodeIterator.d.ts +18 -3
- package/cjs/tree-walker/NodeIterator.d.ts.map +1 -1
- package/cjs/tree-walker/TreeWalker.cjs +6 -6
- package/cjs/tree-walker/TreeWalker.cjs.map +1 -1
- package/cjs/tree-walker/TreeWalker.d.ts +2 -1
- package/cjs/tree-walker/TreeWalker.d.ts.map +1 -1
- package/cjs/utilities/ClassMethodBinder.cjs.map +1 -0
- package/cjs/utilities/ClassMethodBinder.d.ts.map +1 -0
- package/cjs/utilities/StringUtility.cjs.map +1 -0
- package/cjs/utilities/StringUtility.d.ts.map +1 -0
- package/cjs/utilities/XMLEncodeUtility.cjs +119 -0
- package/cjs/utilities/XMLEncodeUtility.cjs.map +1 -0
- package/cjs/utilities/XMLEncodeUtility.d.ts +48 -0
- package/cjs/utilities/XMLEncodeUtility.d.ts.map +1 -0
- package/cjs/window/BrowserWindow.cjs +5 -3
- package/cjs/window/BrowserWindow.cjs.map +1 -1
- package/cjs/window/BrowserWindow.d.ts +2 -0
- package/cjs/window/BrowserWindow.d.ts.map +1 -1
- package/cjs/window/WindowErrorUtility.cjs +1 -1
- package/cjs/window/WindowErrorUtility.cjs.map +1 -1
- package/cjs/xml-http-request/XMLHttpRequest.cjs +2 -1
- package/cjs/xml-http-request/XMLHttpRequest.cjs.map +1 -1
- package/cjs/xml-http-request/XMLHttpRequest.d.ts.map +1 -1
- package/cjs/xml-http-request/XMLHttpRequestResponseDataParser.cjs +1 -1
- package/cjs/xml-http-request/XMLHttpRequestResponseDataParser.cjs.map +1 -1
- package/cjs/xml-parser/XMLParser.cjs +531 -242
- package/cjs/xml-parser/XMLParser.cjs.map +1 -1
- package/cjs/xml-parser/XMLParser.d.ts +89 -19
- package/cjs/xml-parser/XMLParser.d.ts.map +1 -1
- package/cjs/xml-serializer/XMLSerializer.cjs +136 -40
- package/cjs/xml-serializer/XMLSerializer.cjs.map +1 -1
- package/cjs/xml-serializer/XMLSerializer.d.ts +6 -17
- package/cjs/xml-serializer/XMLSerializer.d.ts.map +1 -1
- package/lib/PropertySymbol.d.ts +4 -1
- package/lib/PropertySymbol.d.ts.map +1 -1
- package/lib/PropertySymbol.js +4 -1
- package/lib/PropertySymbol.js.map +1 -1
- package/lib/config/HTMLElementConfig.d.ts +7 -0
- package/lib/config/HTMLElementConfig.d.ts.map +1 -1
- package/lib/config/HTMLElementConfig.js +42 -16
- package/lib/config/HTMLElementConfig.js.map +1 -1
- package/lib/config/HTMLElementConfigContentModelEnum.d.ts +3 -0
- package/lib/config/HTMLElementConfigContentModelEnum.d.ts.map +1 -1
- package/lib/config/HTMLElementConfigContentModelEnum.js +3 -0
- package/lib/config/HTMLElementConfigContentModelEnum.js.map +1 -1
- package/lib/config/NamespaceURI.d.ts +2 -0
- package/lib/config/NamespaceURI.d.ts.map +1 -1
- package/lib/config/NamespaceURI.js +2 -0
- package/lib/config/NamespaceURI.js.map +1 -1
- package/lib/css/declaration/CSSStyleDeclaration.d.ts.map +1 -1
- package/lib/css/declaration/CSSStyleDeclaration.js +1 -1
- package/lib/css/declaration/CSSStyleDeclaration.js.map +1 -1
- package/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.d.ts.map +1 -1
- package/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.js +2 -2
- package/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.js.map +1 -1
- package/lib/css/rules/CSSStyleRule.d.ts +1 -1
- package/lib/css/rules/CSSStyleRule.d.ts.map +1 -1
- package/lib/css/rules/CSSStyleRule.js +1 -1
- package/lib/css/rules/CSSStyleRule.js.map +1 -1
- package/lib/custom-element/CustomElementReactionStack.d.ts +27 -0
- package/lib/custom-element/CustomElementReactionStack.d.ts.map +1 -0
- package/lib/custom-element/CustomElementReactionStack.js +75 -0
- package/lib/custom-element/CustomElementReactionStack.js.map +1 -0
- package/lib/custom-element/CustomElementRegistry.d.ts +2 -6
- package/lib/custom-element/CustomElementRegistry.d.ts.map +1 -1
- package/lib/custom-element/CustomElementRegistry.js +32 -45
- package/lib/custom-element/CustomElementRegistry.js.map +1 -1
- package/lib/custom-element/CustomElementUtility.d.ts +14 -0
- package/lib/custom-element/CustomElementUtility.d.ts.map +1 -0
- package/lib/custom-element/CustomElementUtility.js +32 -0
- package/lib/custom-element/CustomElementUtility.js.map +1 -0
- package/lib/custom-element/ICustomElementDefinition.d.ts +12 -0
- package/lib/custom-element/ICustomElementDefinition.d.ts.map +1 -0
- package/lib/custom-element/ICustomElementDefinition.js +2 -0
- package/lib/custom-element/ICustomElementDefinition.js.map +1 -0
- package/lib/dom/DOMStringMap.d.ts.map +1 -1
- package/lib/dom/DOMStringMap.js +8 -8
- package/lib/dom/DOMStringMap.js.map +1 -1
- package/lib/dom/DOMTokenList.js +1 -1
- package/lib/dom/DOMTokenList.js.map +1 -1
- package/lib/dom-parser/DOMParser.d.ts +0 -1
- package/lib/dom-parser/DOMParser.d.ts.map +1 -1
- package/lib/dom-parser/DOMParser.js +5 -67
- package/lib/dom-parser/DOMParser.js.map +1 -1
- package/lib/exception/DOMExceptionNameEnum.d.ts +2 -1
- package/lib/exception/DOMExceptionNameEnum.d.ts.map +1 -1
- package/lib/exception/DOMExceptionNameEnum.js +1 -0
- package/lib/exception/DOMExceptionNameEnum.js.map +1 -1
- package/lib/history/History.js +6 -6
- package/lib/history/History.js.map +1 -1
- package/lib/html-parser/HTMLParser.d.ts +91 -0
- package/lib/html-parser/HTMLParser.d.ts.map +1 -0
- package/lib/html-parser/HTMLParser.js +697 -0
- package/lib/html-parser/HTMLParser.js.map +1 -0
- package/lib/html-serializer/HTMLSerializer.d.ts +36 -0
- package/lib/html-serializer/HTMLSerializer.d.ts.map +1 -0
- package/lib/html-serializer/HTMLSerializer.js +123 -0
- package/lib/html-serializer/HTMLSerializer.js.map +1 -0
- package/lib/nodes/document/Document.d.ts +8 -0
- package/lib/nodes/document/Document.d.ts.map +1 -1
- package/lib/nodes/document/Document.js +105 -121
- package/lib/nodes/document/Document.js.map +1 -1
- package/lib/nodes/element/Element.d.ts +2 -12
- package/lib/nodes/element/Element.d.ts.map +1 -1
- package/lib/nodes/element/Element.js +35 -53
- package/lib/nodes/element/Element.js.map +1 -1
- package/lib/nodes/element/HTMLCollection.d.ts.map +1 -1
- package/lib/nodes/element/HTMLCollection.js +5 -9
- package/lib/nodes/element/HTMLCollection.js.map +1 -1
- package/lib/nodes/element/NamedNodeMap.d.ts +1 -16
- package/lib/nodes/element/NamedNodeMap.d.ts.map +1 -1
- package/lib/nodes/element/NamedNodeMap.js +39 -52
- package/lib/nodes/element/NamedNodeMap.js.map +1 -1
- package/lib/nodes/element/NamedNodeMapProxyFactory.d.ts.map +1 -1
- package/lib/nodes/element/NamedNodeMapProxyFactory.js +12 -14
- package/lib/nodes/element/NamedNodeMapProxyFactory.js.map +1 -1
- package/lib/nodes/html-button-element/HTMLButtonElement.d.ts.map +1 -1
- package/lib/nodes/html-button-element/HTMLButtonElement.js +1 -1
- package/lib/nodes/html-button-element/HTMLButtonElement.js.map +1 -1
- package/lib/nodes/html-document/HTMLDocument.d.ts +10 -0
- package/lib/nodes/html-document/HTMLDocument.d.ts.map +1 -1
- package/lib/nodes/html-document/HTMLDocument.js +33 -2
- package/lib/nodes/html-document/HTMLDocument.js.map +1 -1
- package/lib/nodes/html-element/HTMLElement.d.ts +34 -0
- package/lib/nodes/html-element/HTMLElement.d.ts.map +1 -1
- package/lib/nodes/html-element/HTMLElement.js +58 -22
- package/lib/nodes/html-element/HTMLElement.js.map +1 -1
- package/lib/nodes/html-field-set-element/HTMLFieldSetElement.d.ts.map +1 -1
- package/lib/nodes/html-field-set-element/HTMLFieldSetElement.js +1 -1
- package/lib/nodes/html-field-set-element/HTMLFieldSetElement.js.map +1 -1
- package/lib/nodes/html-form-element/HTMLFormElement.d.ts.map +1 -1
- package/lib/nodes/html-form-element/HTMLFormElement.js +5 -8
- package/lib/nodes/html-form-element/HTMLFormElement.js.map +1 -1
- package/lib/nodes/html-iframe-element/HTMLIFrameElement.js +1 -1
- package/lib/nodes/html-iframe-element/HTMLIFrameElement.js.map +1 -1
- package/lib/nodes/html-input-element/HTMLInputElement.d.ts.map +1 -1
- package/lib/nodes/html-input-element/HTMLInputElement.js +1 -1
- package/lib/nodes/html-input-element/HTMLInputElement.js.map +1 -1
- package/lib/nodes/html-media-element/TextTrackList.js +1 -1
- package/lib/nodes/html-media-element/TextTrackList.js.map +1 -1
- package/lib/nodes/html-object-element/HTMLObjectElement.d.ts.map +1 -1
- package/lib/nodes/html-object-element/HTMLObjectElement.js +1 -1
- package/lib/nodes/html-object-element/HTMLObjectElement.js.map +1 -1
- package/lib/nodes/html-output-element/HTMLOutputElement.d.ts.map +1 -1
- package/lib/nodes/html-output-element/HTMLOutputElement.js +1 -1
- package/lib/nodes/html-output-element/HTMLOutputElement.js.map +1 -1
- package/lib/nodes/html-script-element/HTMLScriptElement.d.ts.map +1 -1
- package/lib/nodes/html-script-element/HTMLScriptElement.js +3 -1
- package/lib/nodes/html-script-element/HTMLScriptElement.js.map +1 -1
- package/lib/nodes/html-select-element/HTMLSelectElement.d.ts.map +1 -1
- package/lib/nodes/html-select-element/HTMLSelectElement.js +2 -2
- package/lib/nodes/html-select-element/HTMLSelectElement.js.map +1 -1
- package/lib/nodes/html-table-element/HTMLTableElement.d.ts.map +1 -1
- package/lib/nodes/html-table-element/HTMLTableElement.js +9 -1
- package/lib/nodes/html-table-element/HTMLTableElement.js.map +1 -1
- package/lib/nodes/html-table-row-element/HTMLTableRowElement.js +1 -1
- package/lib/nodes/html-template-element/HTMLTemplateElement.d.ts +2 -2
- package/lib/nodes/html-template-element/HTMLTemplateElement.d.ts.map +1 -1
- package/lib/nodes/html-template-element/HTMLTemplateElement.js +15 -17
- package/lib/nodes/html-template-element/HTMLTemplateElement.js.map +1 -1
- package/lib/nodes/html-text-area-element/HTMLTextAreaElement.d.ts.map +1 -1
- package/lib/nodes/html-text-area-element/HTMLTextAreaElement.js +1 -1
- package/lib/nodes/html-text-area-element/HTMLTextAreaElement.js.map +1 -1
- package/lib/nodes/node/Node.d.ts +2 -10
- package/lib/nodes/node/Node.d.ts.map +1 -1
- package/lib/nodes/node/Node.js +44 -48
- package/lib/nodes/node/Node.js.map +1 -1
- package/lib/nodes/node/NodeList.js +1 -1
- package/lib/nodes/node/NodeList.js.map +1 -1
- package/lib/nodes/node/NodeUtility.d.ts.map +1 -1
- package/lib/nodes/node/NodeUtility.js +4 -3
- package/lib/nodes/node/NodeUtility.js.map +1 -1
- package/lib/nodes/parent-node/ParentNodeUtility.d.ts.map +1 -1
- package/lib/nodes/parent-node/ParentNodeUtility.js +5 -2
- package/lib/nodes/parent-node/ParentNodeUtility.js.map +1 -1
- package/lib/nodes/shadow-root/ShadowRoot.d.ts.map +1 -1
- package/lib/nodes/shadow-root/ShadowRoot.js +8 -8
- package/lib/nodes/shadow-root/ShadowRoot.js.map +1 -1
- package/lib/nodes/xml-document/XMLDocument.d.ts +2 -0
- package/lib/nodes/xml-document/XMLDocument.d.ts.map +1 -1
- package/lib/nodes/xml-document/XMLDocument.js +3 -0
- package/lib/nodes/xml-document/XMLDocument.js.map +1 -1
- package/lib/query-selector/SelectorItem.d.ts.map +1 -1
- package/lib/query-selector/SelectorItem.js +1 -2
- package/lib/query-selector/SelectorItem.js.map +1 -1
- package/lib/range/Range.d.ts.map +1 -1
- package/lib/range/Range.js +3 -3
- package/lib/range/Range.js.map +1 -1
- package/lib/storage/Storage.js +1 -1
- package/lib/storage/Storage.js.map +1 -1
- package/lib/svg/SVGLengthList.js +1 -1
- package/lib/svg/SVGLengthList.js.map +1 -1
- package/lib/svg/SVGNumberList.js +1 -1
- package/lib/svg/SVGNumberList.js.map +1 -1
- package/lib/svg/SVGPointList.js +1 -1
- package/lib/svg/SVGPointList.js.map +1 -1
- package/lib/svg/SVGStringList.js +1 -1
- package/lib/svg/SVGStringList.js.map +1 -1
- package/lib/svg/SVGTransformList.js +1 -1
- package/lib/svg/SVGTransformList.js.map +1 -1
- package/lib/tree-walker/NodeIterator.d.ts +18 -3
- package/lib/tree-walker/NodeIterator.d.ts.map +1 -1
- package/lib/tree-walker/NodeIterator.js +40 -6
- package/lib/tree-walker/NodeIterator.js.map +1 -1
- package/lib/tree-walker/TreeWalker.d.ts +2 -1
- package/lib/tree-walker/TreeWalker.d.ts.map +1 -1
- package/lib/tree-walker/TreeWalker.js +6 -6
- package/lib/tree-walker/TreeWalker.js.map +1 -1
- package/lib/utilities/ClassMethodBinder.d.ts.map +1 -0
- package/lib/utilities/ClassMethodBinder.js.map +1 -0
- package/lib/utilities/StringUtility.d.ts.map +1 -0
- package/lib/utilities/StringUtility.js.map +1 -0
- package/lib/utilities/XMLEncodeUtility.d.ts +48 -0
- package/lib/utilities/XMLEncodeUtility.d.ts.map +1 -0
- package/lib/utilities/XMLEncodeUtility.js +116 -0
- package/lib/utilities/XMLEncodeUtility.js.map +1 -0
- package/lib/window/BrowserWindow.d.ts +2 -0
- package/lib/window/BrowserWindow.d.ts.map +1 -1
- package/lib/window/BrowserWindow.js +5 -3
- package/lib/window/BrowserWindow.js.map +1 -1
- package/lib/window/WindowErrorUtility.js +1 -1
- package/lib/window/WindowErrorUtility.js.map +1 -1
- package/lib/xml-http-request/XMLHttpRequest.d.ts.map +1 -1
- package/lib/xml-http-request/XMLHttpRequest.js +2 -1
- package/lib/xml-http-request/XMLHttpRequest.js.map +1 -1
- package/lib/xml-http-request/XMLHttpRequestResponseDataParser.js +1 -1
- package/lib/xml-http-request/XMLHttpRequestResponseDataParser.js.map +1 -1
- package/lib/xml-parser/XMLParser.d.ts +89 -19
- package/lib/xml-parser/XMLParser.d.ts.map +1 -1
- package/lib/xml-parser/XMLParser.js +531 -242
- package/lib/xml-parser/XMLParser.js.map +1 -1
- package/lib/xml-serializer/XMLSerializer.d.ts +6 -17
- package/lib/xml-serializer/XMLSerializer.d.ts.map +1 -1
- package/lib/xml-serializer/XMLSerializer.js +136 -40
- package/lib/xml-serializer/XMLSerializer.js.map +1 -1
- package/package.json +1 -2
- package/src/PropertySymbol.ts +4 -1
- package/src/config/HTMLElementConfig.ts +53 -17
- package/src/config/HTMLElementConfigContentModelEnum.ts +3 -0
- package/src/config/NamespaceURI.ts +2 -0
- package/src/css/declaration/CSSStyleDeclaration.ts +1 -4
- package/src/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.ts +2 -4
- package/src/css/rules/CSSStyleRule.ts +1 -1
- package/src/custom-element/CustomElementReactionStack.ts +86 -0
- package/src/custom-element/CustomElementRegistry.ts +35 -54
- package/src/custom-element/CustomElementUtility.ts +34 -0
- package/src/custom-element/ICustomElementDefinition.ts +16 -0
- package/src/dom/DOMStringMap.ts +12 -10
- package/src/dom/DOMTokenList.ts +1 -1
- package/src/dom-parser/DOMParser.ts +5 -75
- package/src/exception/DOMExceptionNameEnum.ts +2 -1
- package/src/history/History.ts +6 -6
- package/src/html-parser/HTMLParser.ts +864 -0
- package/src/html-serializer/HTMLSerializer.ts +162 -0
- package/src/nodes/document/Document.ts +117 -136
- package/src/nodes/element/Element.ts +48 -95
- package/src/nodes/element/HTMLCollection.ts +5 -30
- package/src/nodes/element/NamedNodeMap.ts +58 -72
- package/src/nodes/element/NamedNodeMapProxyFactory.ts +12 -15
- package/src/nodes/html-button-element/HTMLButtonElement.ts +1 -4
- package/src/nodes/html-document/HTMLDocument.ts +58 -2
- package/src/nodes/html-element/HTMLElement.ts +117 -25
- package/src/nodes/html-field-set-element/HTMLFieldSetElement.ts +1 -4
- package/src/nodes/html-form-element/HTMLFormElement.ts +5 -27
- package/src/nodes/html-iframe-element/HTMLIFrameElement.ts +1 -1
- package/src/nodes/html-input-element/HTMLInputElement.ts +1 -4
- package/src/nodes/html-media-element/TextTrackList.ts +1 -1
- package/src/nodes/html-object-element/HTMLObjectElement.ts +1 -4
- package/src/nodes/html-output-element/HTMLOutputElement.ts +1 -4
- package/src/nodes/html-script-element/HTMLScriptElement.ts +4 -1
- package/src/nodes/html-select-element/HTMLSelectElement.ts +2 -5
- package/src/nodes/html-table-element/HTMLTableElement.ts +8 -1
- package/src/nodes/html-table-row-element/HTMLTableRowElement.ts +1 -1
- package/src/nodes/html-template-element/HTMLTemplateElement.ts +23 -17
- package/src/nodes/html-text-area-element/HTMLTextAreaElement.ts +1 -4
- package/src/nodes/node/Node.ts +57 -70
- package/src/nodes/node/NodeList.ts +1 -1
- package/src/nodes/node/NodeUtility.ts +4 -3
- package/src/nodes/parent-node/ParentNodeUtility.ts +6 -6
- package/src/nodes/shadow-root/ShadowRoot.ts +8 -8
- package/src/nodes/xml-document/XMLDocument.ts +5 -1
- package/src/query-selector/SelectorItem.ts +1 -2
- package/src/range/Range.ts +3 -3
- package/src/storage/Storage.ts +1 -1
- package/src/svg/SVGLengthList.ts +1 -1
- package/src/svg/SVGNumberList.ts +1 -1
- package/src/svg/SVGPointList.ts +1 -1
- package/src/svg/SVGStringList.ts +1 -1
- package/src/svg/SVGTransformList.ts +1 -1
- package/src/tree-walker/NodeIterator.ts +44 -8
- package/src/tree-walker/TreeWalker.ts +6 -6
- package/src/utilities/XMLEncodeUtility.ts +127 -0
- package/src/window/BrowserWindow.ts +7 -5
- package/src/window/WindowErrorUtility.ts +1 -1
- package/src/xml-http-request/XMLHttpRequest.ts +3 -1
- package/src/xml-http-request/XMLHttpRequestResponseDataParser.ts +1 -1
- package/src/xml-parser/XMLParser.ts +627 -313
- package/src/xml-serializer/XMLSerializer.ts +204 -58
- package/cjs/ClassMethodBinder.cjs.map +0 -1
- package/cjs/ClassMethodBinder.d.ts.map +0 -1
- package/cjs/StringUtility.cjs.map +0 -1
- package/cjs/StringUtility.d.ts.map +0 -1
- package/lib/ClassMethodBinder.d.ts.map +0 -1
- package/lib/ClassMethodBinder.js.map +0 -1
- package/lib/StringUtility.d.ts.map +0 -1
- package/lib/StringUtility.js.map +0 -1
- /package/cjs/{ClassMethodBinder.cjs → utilities/ClassMethodBinder.cjs} +0 -0
- /package/cjs/{ClassMethodBinder.d.ts → utilities/ClassMethodBinder.d.ts} +0 -0
- /package/cjs/{StringUtility.cjs → utilities/StringUtility.cjs} +0 -0
- /package/cjs/{StringUtility.d.ts → utilities/StringUtility.d.ts} +0 -0
- /package/lib/{ClassMethodBinder.d.ts → utilities/ClassMethodBinder.d.ts} +0 -0
- /package/lib/{ClassMethodBinder.js → utilities/ClassMethodBinder.js} +0 -0
- /package/lib/{StringUtility.d.ts → utilities/StringUtility.d.ts} +0 -0
- /package/lib/{StringUtility.js → utilities/StringUtility.js} +0 -0
- /package/src/{ClassMethodBinder.ts → utilities/ClassMethodBinder.ts} +0 -0
- /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
|
10
|
-
import
|
11
|
-
import
|
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
|
37
|
-
* Group 4: Attribute
|
38
|
-
* Group 5: Attribute
|
39
|
-
* Group 6: Attribute
|
40
|
-
* Group 7: Attribute
|
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-_
|
35
|
+
/\s*([a-zA-Z0-9-_:]+)\s*=\s*"([^"]*)("{0,1})|\s*([a-zA-Z0-9-_:]+)\s*=\s*'([^']*)('{0,1})/gm;
|
46
36
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
*
|
108
|
+
* Constructor.
|
68
109
|
*
|
69
|
-
* @param
|
70
|
-
* @param xml XML/HTML string.
|
110
|
+
* @param window Window.
|
71
111
|
* @param [options] Options.
|
72
|
-
* @param [options.
|
73
|
-
* @param [options.evaluateScripts
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
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 '<' 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
|
-
|
111
|
-
|
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
|
-
|
163
|
-
|
164
|
-
|
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
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
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
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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, '<' not found`);
|
251
|
+
return this.rootNode;
|
252
|
+
}
|
258
253
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
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
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
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(' ')) {
|
287
|
+
this.errorMessage = `Entity 'nbsp' not defined\n`;
|
288
|
+
this.errorIndex = this.lastIndex + text.indexOf(' ') + 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
|
-
|
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
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
} else
|
331
|
-
|
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
|
-
|
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 =
|
559
|
+
lastIndex = attributeRegexp.lastIndex;
|
353
560
|
}
|
354
561
|
|
355
|
-
|
356
|
-
|
357
|
-
if (
|
358
|
-
|
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
|
-
|
362
|
-
|
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
|
-
|
365
|
-
|
366
|
-
|
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
|
-
|
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
|
-
*
|
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
|
693
|
+
* @returns Document type.
|
380
694
|
*/
|
381
|
-
private
|
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
|
406
|
-
docTypeSplit[1].toLowerCase(),
|
719
|
+
return {
|
720
|
+
name: docTypeSplit[1].toLowerCase(),
|
407
721
|
publicId,
|
408
722
|
systemId
|
409
|
-
|
723
|
+
};
|
410
724
|
}
|
411
725
|
}
|