Comparing version 2.0.1 to 2.0.2
@@ -7,2 +7,107 @@ # Changelog | ||
## [0.8.7](https://github.com/xmldom/xmldom/compare/0.8.6...0.8.7) | ||
### Fixed | ||
- properly parse closing where the last attribute has no value [`#485`](https://github.com/xmldom/xmldom/pull/485) / [`#486`](https://github.com/xmldom/xmldom/issues/486) | ||
Thank you, [@bulandent](https://github.com/bulandent), for your contributions | ||
## [0.7.10](https://github.com/xmldom/xmldom/compare/0.7.9...0.7.10) | ||
### Fixed | ||
- properly parse closing where the last attribute has no value [`#485`](https://github.com/xmldom/xmldom/pull/485) / [`#486`](https://github.com/xmldom/xmldom/issues/486) | ||
Thank you, [@bulandent](https://github.com/bulandent), for your contributions | ||
## [0.8.6](https://github.com/xmldom/xmldom/compare/0.8.5...0.8.6) | ||
### Fixed | ||
- Properly check nodes before replacement [`#457`](https://github.com/xmldom/xmldom/pull/457) / [`#455`](https://github.com/xmldom/xmldom/issues/455) / [`#456`](https://github.com/xmldom/xmldom/issues/456) | ||
Thank you, [@edemaine](https://github.com/edemaine), [@pedro-l9](https://github.com/pedro-l9), for your contributions | ||
## [0.8.5](https://github.com/xmldom/xmldom/compare/0.8.4...0.8.5) | ||
### Fixed | ||
- fix: Restore ES5 compatibility [`#452`](https://github.com/xmldom/xmldom/pull/452) / [`#453`](https://github.com/xmldom/xmldom/issues/453) | ||
Thank you, [@fengxinming](https://github.com/fengxinming), for your contributions | ||
## [0.8.4](https://github.com/xmldom/xmldom/compare/0.8.3...0.8.4) | ||
### Fixed | ||
- Security: Prevent inserting DOM nodes when they are not well-formed [`CVE-2022-39353`](https://github.com/xmldom/xmldom/security/advisories/GHSA-crh6-fp67-6883) | ||
In case such a DOM would be created, the part that is not well-formed will be transformed into text nodes, in which xml specific characters like `<` and `>` are encoded accordingly. | ||
In the upcoming version 0.9.0 those text nodes will no longer be added and an error will be thrown instead. | ||
This change can break your code, if you relied on this behavior, e.g. multiple root elements in the past. We consider it more important to align with the specs that we want to be aligned with, considering the potential security issues that might derive from people not being aware of the difference in behavior. | ||
Related Spec: <https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity> | ||
Thank you, [@frumioj](https://github.com/frumioj), [@cjbarth](https://github.com/cjbarth), [@markgollnick](https://github.com/markgollnick) for your contributions | ||
## [0.8.3](https://github.com/xmldom/xmldom/compare/0.8.3...0.8.2) | ||
### Fixed | ||
- Avoid iterating over prototype properties [`#437`](https://github.com/xmldom/xmldom/pull/437) / [`#436`](https://github.com/xmldom/xmldom/issues/436) | ||
Thank you, [@Supraja9726](https://github.com/Supraja9726) for your contributions | ||
## [0.8.2](https://github.com/xmldom/xmldom/compare/0.8.1...0.8.2) | ||
### Fixed | ||
- fix(dom): Serialize `>` as specified (#395) [`#58`](https://github.com/xmldom/xmldom/issues/58) | ||
### Other | ||
- docs: Add `nodeType` values to public interface description [`#396`](https://github.com/xmldom/xmldom/pull/396) | ||
- test: Add executable examples for node and typescript [`#317`](https://github.com/xmldom/xmldom/pull/317) | ||
- fix(dom): Serialize `>` as specified [`#395`](https://github.com/xmldom/xmldom/pull/395) | ||
- chore: Add minimal `Object.assign` ponyfill [`#379`](https://github.com/xmldom/xmldom/pull/379) | ||
- docs: Refine release documentation [`#378`](https://github.com/xmldom/xmldom/pull/378) | ||
- chore: update various dev dependencies | ||
Thank you [@niklasl](https://github.com/niklasl), [@cburatto](https://github.com/cburatto), [@SheetJSDev](https://github.com/SheetJSDev), [@pyrsmk](https://github.com/pyrsmk) for your contributions | ||
## [0.8.1](https://github.com/xmldom/xmldom/compare/0.8.0...0.8.1) | ||
### Fixes | ||
- Only use own properties in entityMap [`#374`](https://github.com/xmldom/xmldom/pull/374) | ||
### Docs | ||
- Add security policy [`#365`](https://github.com/xmldom/xmldom/pull/365) | ||
- changelog: Correct contributor name and link [`#366`](https://github.com/xmldom/xmldom/pull/366) | ||
- Describe release/publish steps [`#358`](https://github.com/xmldom/xmldom/pull/358), [`#376`](https://github.com/xmldom/xmldom/pull/376) | ||
- Add snyk package health badge [`#360`](https://github.com/xmldom/xmldom/pull/360) | ||
## [0.8.0](https://github.com/xmldom/xmldom/compare/0.7.5...0.8.0) | ||
### Fixed | ||
- Normalize all line endings according to XML specs [1.0](https://w3.org/TR/xml/#sec-line-ends) and [1.1](https://www.w3.org/TR/xml11/#sec-line-ends) \ | ||
BREAKING CHANGE: Certain combination of line break characters are normalized to a single `\n` before parsing takes place and will no longer be preserved. | ||
- [`#303`](https://github.com/xmldom/xmldom/issues/303) / [`#307`](https://github.com/xmldom/xmldom/pull/307) | ||
- [`#49`](https://github.com/xmldom/xmldom/issues/49), [`#97`](https://github.com/xmldom/xmldom/issues/97), [`#324`](https://github.com/xmldom/xmldom/issues/324) / [`#314`](https://github.com/xmldom/xmldom/pull/314) | ||
- XMLSerializer: Preserve whitespace character references [`#284`](https://github.com/xmldom/xmldom/issues/284) / [`#310`](https://github.com/xmldom/xmldom/pull/310) \ | ||
BREAKING CHANGE: If you relied on the not spec compliant preservation of literal `\t`, `\n` or `\r` in **attribute values**. | ||
To preserve those you will have to create XML that instead contains the correct numerical (or hexadecimal) equivalent (e.g. `	`, `
`, `
`). | ||
- Drop deprecated exports `DOMImplementation` and `XMLSerializer` from `lib/dom-parser.js` [#53](https://github.com/xmldom/xmldom/issues/53) / [`#309`](https://github.com/xmldom/xmldom/pull/309) | ||
BREAKING CHANGE: Use the one provided by the main package export. | ||
- dom: Remove all links as part of `removeChild` [`#343`](https://github.com/xmldom/xmldom/issues/343) / [`#355`](https://github.com/xmldom/xmldom/pull/355) | ||
### Chore | ||
- ci: Restore latest tested node version to 16.x [`#325`](https://github.com/xmldom/xmldom/pull/325) | ||
- ci: Split test and lint steps into jobs [`#111`](https://github.com/xmldom/xmldom/issues/111) / [`#304`](https://github.com/xmldom/xmldom/pull/304) | ||
- Pinned and updated devDependencies | ||
Thank you [@marrus-sh](https://github.com/marrus-sh), [@victorandree](https://github.com/victorandree), [@mdierolf](https://github.com/mdierolf), [@tsabbay](https://github.com/tsabbay), [@fatihpense](https://github.com/fatihpense) for your contributions | ||
## 0.7.5 | ||
@@ -15,3 +120,3 @@ | ||
- Preserve default namespace when serializing [`#319`](https://github.com/xmldom/xmldom/issues/319) / [`#321`](https://github.com/xmldom/xmldom/pull/321) | ||
Thank you [@lupestro](https://github.com/lupestro) | ||
Thank you, [@lupestro](https://github.com/lupestro) | ||
@@ -25,3 +130,3 @@ ## 0.7.4 | ||
- Restore ability to parse `__prototype__` attributes [`#315`](https://github.com/xmldom/xmldom/pull/315) | ||
Thank you [@dsimsonOMF](https://github.com/dsimsonOMF) | ||
Thank you, [@dsimpsonOMF](https://github.com/dsimpsonOMF) | ||
@@ -36,3 +141,3 @@ ## 0.7.3 | ||
- Correct typo in error message [`#294`](https://github.com/xmldom/xmldom/pull/294) | ||
Thank you [@rrthomas](https://github.com/rrthomas) | ||
Thank you, [@rrthomas](https://github.com/rrthomas) | ||
@@ -62,3 +167,3 @@ ### Refactor: | ||
- Types: Add index.d.ts to packaged files [`#288`](https://github.com/xmldom/xmldom/pull/288) | ||
Thank you [@forty](https://github.com/forty) | ||
Thank you, [@forty](https://github.com/forty) | ||
@@ -72,3 +177,3 @@ ## 0.7.1 | ||
- Types: Copy types from DefinitelyTyped [`#283`](https://github.com/xmldom/xmldom/pull/283) | ||
Thank you [@kachkaev](https://github.com/kachkaev) | ||
Thank you, [@kachkaev](https://github.com/kachkaev) | ||
@@ -90,3 +195,3 @@ ### Chore: | ||
- Security: Misinterpretation of malicious XML input [`CVE-2021-32796`](https://github.com/xmldom/xmldom/security/advisories/GHSA-5fg8-2547-mr8q) | ||
- Implement `Document.getElementsByClassName` as specified [`#213`](https://github.com/xmldom/xmldom/pull/213), thank you [@ChALkeR](https://github.com/ChALkeR) | ||
- Implement `Document.getElementsByClassName` as specified [`#213`](https://github.com/xmldom/xmldom/pull/213), thank you, [@ChALkeR](https://github.com/ChALkeR) | ||
- Inherit namespace prefix from parent when required [`#268`](https://github.com/xmldom/xmldom/pull/268) | ||
@@ -99,3 +204,3 @@ - Handle whitespace in closing tags [`#267`](https://github.com/xmldom/xmldom/pull/267) | ||
BREAKING CHANGE: Only if you rely on ["unsetting" a namespace prefix](https://github.com/xmldom/xmldom/pull/168#issuecomment-886984994) by setting it to an empty string | ||
- Set `localName` as part of `Document.createElement` [`#229`](https://github.com/xmldom/xmldom/pull/229), thank you [@rrthomas](https://github.com/rrthomas) | ||
- Set `localName` as part of `Document.createElement` [`#229`](https://github.com/xmldom/xmldom/pull/229), thank you, [@rrthomas](https://github.com/rrthomas) | ||
@@ -119,3 +224,3 @@ ### CI | ||
BREAKING CHANGE: If your code expected empty namespaces attributes to be serialized. | ||
Thank you [@pdecat](https://github.com/pdecat) and [@FranckDepoortere](https://github.com/FranckDepoortere) | ||
Thank you, [@pdecat](https://github.com/pdecat) and [@FranckDepoortere](https://github.com/FranckDepoortere) | ||
- Escape `<` to `<` when serializing attribute values [`#198`](https://github.com/xmldom/xmldom/issues/198) / [`#199`](https://github.com/xmldom/xmldom/pull/199) | ||
@@ -122,0 +227,0 @@ |
'use strict' | ||
/** | ||
* Ponyfill for `Array.prototype.find` which is only available in ES6 runtimes. | ||
* | ||
* Works with anything that has a `length` property and index access properties, including NodeList. | ||
* | ||
* @template {unknown} T | ||
* @param {Array<T> | ({length:number, [number]: T})} list | ||
* @param {function (item: T, index: number, list:Array<T> | ({length:number, [number]: T})):boolean} predicate | ||
* @param {Partial<Pick<ArrayConstructor['prototype'], 'find'>>?} ac `Array.prototype` by default, | ||
* allows injecting a custom implementation in tests | ||
* @returns {T | undefined} | ||
* | ||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find | ||
* @see https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.find | ||
*/ | ||
function find(list, predicate, ac) { | ||
if (ac === undefined) { | ||
ac = Array.prototype; | ||
} | ||
if (list && typeof ac.find === 'function') { | ||
return ac.find.call(list, predicate); | ||
} | ||
for (var i = 0; i < list.length; i++) { | ||
if (Object.prototype.hasOwnProperty.call(list, i)) { | ||
var item = list[i]; | ||
if (predicate.call(undefined, item, i, list)) { | ||
return item; | ||
} | ||
} | ||
} | ||
} | ||
/** | ||
* "Shallow freezes" an object to render it immutable. | ||
@@ -26,2 +58,27 @@ * Uses `Object.freeze` if available, | ||
/** | ||
* Since we can not rely on `Object.assign` we provide a simplified version | ||
* that is sufficient for our needs. | ||
* | ||
* @param {Object} target | ||
* @param {Object | null | undefined} source | ||
* | ||
* @returns {Object} target | ||
* @throws TypeError if target is not an object | ||
* | ||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign | ||
* @see https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.assign | ||
*/ | ||
function assign(target, source) { | ||
if (target === null || typeof target !== 'object') { | ||
throw new TypeError('target is not an object') | ||
} | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key] | ||
} | ||
} | ||
return target | ||
} | ||
/** | ||
* All mime types that are allowed as input to `DOMParser.parseFromString` | ||
@@ -143,4 +200,6 @@ * | ||
exports.assign = assign; | ||
exports.find = find; | ||
exports.freeze = freeze; | ||
exports.MIME_TYPE = MIME_TYPE; | ||
exports.NAMESPACE = NAMESPACE; |
@@ -13,2 +13,60 @@ var conventions = require("./conventions"); | ||
/** | ||
* Normalizes line ending according to https://www.w3.org/TR/xml11/#sec-line-ends: | ||
* | ||
* > XML parsed entities are often stored in computer files which, | ||
* > for editing convenience, are organized into lines. | ||
* > These lines are typically separated by some combination | ||
* > of the characters CARRIAGE RETURN (#xD) and LINE FEED (#xA). | ||
* > | ||
* > To simplify the tasks of applications, the XML processor must behave | ||
* > as if it normalized all line breaks in external parsed entities (including the document entity) | ||
* > on input, before parsing, by translating all of the following to a single #xA character: | ||
* > | ||
* > 1. the two-character sequence #xD #xA | ||
* > 2. the two-character sequence #xD #x85 | ||
* > 3. the single character #x85 | ||
* > 4. the single character #x2028 | ||
* > 5. any #xD character that is not immediately followed by #xA or #x85. | ||
* | ||
* @param {string} input | ||
* @returns {string} | ||
*/ | ||
function normalizeLineEndings(input) { | ||
return input | ||
.replace(/\r[\n\u0085]/g, '\n') | ||
.replace(/[\r\u0085\u2028]/g, '\n') | ||
} | ||
/** | ||
* @typedef Locator | ||
* @property {number} [columnNumber] | ||
* @property {number} [lineNumber] | ||
*/ | ||
/** | ||
* @typedef DOMParserOptions | ||
* @property {DOMHandler} [domBuilder] | ||
* @property {Function} [errorHandler] | ||
* @property {(string) => string} [normalizeLineEndings] used to replace line endings before parsing | ||
* defaults to `normalizeLineEndings` | ||
* @property {Locator} [locator] | ||
* @property {Record<string, string>} [xmlns] | ||
* | ||
* @see normalizeLineEndings | ||
*/ | ||
/** | ||
* The DOMParser interface provides the ability to parse XML or HTML source code | ||
* from a string into a DOM `Document`. | ||
* | ||
* _xmldom is different from the spec in that it allows an `options` parameter, | ||
* to override the default behavior._ | ||
* | ||
* @param {DOMParserOptions} [options] | ||
* @constructor | ||
* | ||
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMParser | ||
* @see https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-parsing-and-serialization | ||
*/ | ||
function DOMParser(options){ | ||
@@ -37,6 +95,11 @@ this.options = options ||{locator:{}}; | ||
defaultNSMap.xml = defaultNSMap.xml || NAMESPACE.XML; | ||
if(source && typeof source === 'string'){ | ||
sax.parse(source,defaultNSMap,entityMap); | ||
}else{ | ||
sax.errorHandler.error("invalid doc source"); | ||
var normalize = options.normalizeLineEndings || normalizeLineEndings; | ||
if (source && typeof source === 'string') { | ||
sax.parse( | ||
normalize(source), | ||
defaultNSMap, | ||
entityMap | ||
) | ||
} else { | ||
sax.errorHandler.error('invalid doc source') | ||
} | ||
@@ -260,12 +323,3 @@ return domBuilder.doc; | ||
exports.__DOMHandler = DOMHandler; | ||
exports.normalizeLineEndings = normalizeLineEndings; | ||
exports.DOMParser = DOMParser; | ||
/** | ||
* @deprecated Import/require from main entry point instead | ||
*/ | ||
exports.DOMImplementation = dom.DOMImplementation; | ||
/** | ||
* @deprecated Import/require from main entry point instead | ||
*/ | ||
exports.XMLSerializer = dom.XMLSerializer; |
var conventions = require("./conventions"); | ||
var find = conventions.find; | ||
var NAMESPACE = conventions.NAMESPACE; | ||
@@ -65,3 +66,5 @@ | ||
for(var p in src){ | ||
dest[p] = src[p]; | ||
if (Object.prototype.hasOwnProperty.call(src, p)) { | ||
dest[p] = src[p]; | ||
} | ||
} | ||
@@ -160,10 +163,10 @@ } | ||
*/ | ||
length:0, | ||
length:0, | ||
/** | ||
* Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null. | ||
* @standard level1 | ||
* @param index unsigned long | ||
* @param index unsigned long | ||
* Index into the collection. | ||
* @return Node | ||
* The node at the indexth position in the NodeList, or null if that is not a valid index. | ||
* The node at the indexth position in the NodeList, or null if that is not a valid index. | ||
*/ | ||
@@ -178,3 +181,19 @@ item: function(index) { | ||
return buf.join(''); | ||
} | ||
}, | ||
/** | ||
* @private | ||
* @param {function (Node):boolean} predicate | ||
* @returns {Node[]} | ||
*/ | ||
filter: function (predicate) { | ||
return Array.prototype.filter.call(this, predicate); | ||
}, | ||
/** | ||
* @private | ||
* @param {Node} item | ||
* @returns {number} | ||
*/ | ||
indexOf: function (item) { | ||
return Array.prototype.indexOf.call(this, item); | ||
}, | ||
}; | ||
@@ -213,3 +232,3 @@ | ||
* NamedNodeMap objects in the DOM are live. | ||
* used for attributes or DocumentType entities | ||
* used for attributes or DocumentType entities | ||
*/ | ||
@@ -258,3 +277,3 @@ function NamedNodeMap() { | ||
}else{ | ||
throw DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr)) | ||
throw new DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr)) | ||
} | ||
@@ -304,6 +323,6 @@ } | ||
return attr; | ||
},// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR | ||
//for level2 | ||
@@ -454,7 +473,7 @@ removeNamedItemNS:function(namespaceURI,localName){ | ||
// Modified in DOM Level 2: | ||
insertBefore:function(newChild, refChild){//raises | ||
insertBefore:function(newChild, refChild){//raises | ||
return _insertBefore(this,newChild,refChild); | ||
}, | ||
replaceChild:function(newChild, oldChild){//raises | ||
this.insertBefore(newChild,oldChild); | ||
replaceChild:function(newChild, oldChild){//raises | ||
_insertBefore(this, newChild,oldChild, assertPreReplacementValidityInDocument); | ||
if(oldChild){ | ||
@@ -519,5 +538,5 @@ this.removeChild(oldChild); | ||
for(var n in map){ | ||
if(map[n] == namespaceURI){ | ||
return n; | ||
} | ||
if (Object.prototype.hasOwnProperty.call(map, n) && map[n] === namespaceURI) { | ||
return n; | ||
} | ||
} | ||
@@ -536,3 +555,3 @@ } | ||
if(map){ | ||
if(prefix in map){ | ||
if(Object.prototype.hasOwnProperty.call(map, prefix)){ | ||
return map[prefix] ; | ||
@@ -583,2 +602,3 @@ } | ||
function Document(){ | ||
this.ownerDocument = this; | ||
} | ||
@@ -604,3 +624,15 @@ | ||
function _onUpdateChild(doc,el,newChild){ | ||
/** | ||
* Updates `el.childNodes`, updating the indexed items and it's `length`. | ||
* Passing `newChild` means it will be appended. | ||
* Otherwise it's assumed that an item has been removed, | ||
* and `el.firstNode` and it's `.nextSibling` are used | ||
* to walk the current list of child nodes. | ||
* | ||
* @param {Document} doc | ||
* @param {Node} el | ||
* @param {Node} [newChild] | ||
* @private | ||
*/ | ||
function _onUpdateChild (doc, el, newChild) { | ||
if(doc && doc._inc){ | ||
@@ -610,13 +642,13 @@ doc._inc++; | ||
var cs = el.childNodes; | ||
if(newChild){ | ||
if (newChild) { | ||
cs[cs.length++] = newChild; | ||
}else{ | ||
//console.log(1) | ||
} else { | ||
var child = el.firstChild; | ||
var i = 0; | ||
while(child){ | ||
while (child) { | ||
cs[i++] = child; | ||
child =child.nextSibling; | ||
child = child.nextSibling; | ||
} | ||
cs.length = i; | ||
delete cs[cs.length]; | ||
} | ||
@@ -627,89 +659,369 @@ } | ||
/** | ||
* attributes; | ||
* children; | ||
* | ||
* writeable properties: | ||
* nodeValue,Attr:value,CharacterData:data | ||
* prefix | ||
* Removes the connections between `parentNode` and `child` | ||
* and any existing `child.previousSibling` or `child.nextSibling`. | ||
* | ||
* @see https://github.com/xmldom/xmldom/issues/135 | ||
* @see https://github.com/xmldom/xmldom/issues/145 | ||
* | ||
* @param {Node} parentNode | ||
* @param {Node} child | ||
* @returns {Node} the child that was removed. | ||
* @private | ||
*/ | ||
function _removeChild(parentNode,child){ | ||
function _removeChild (parentNode, child) { | ||
var previous = child.previousSibling; | ||
var next = child.nextSibling; | ||
if(previous){ | ||
if (previous) { | ||
previous.nextSibling = next; | ||
}else{ | ||
parentNode.firstChild = next | ||
} else { | ||
parentNode.firstChild = next; | ||
} | ||
if(next){ | ||
if (next) { | ||
next.previousSibling = previous; | ||
}else{ | ||
} else { | ||
parentNode.lastChild = previous; | ||
} | ||
_onUpdateChild(parentNode.ownerDocument,parentNode); | ||
child.parentNode = null; | ||
child.previousSibling = null; | ||
child.nextSibling = null; | ||
_onUpdateChild(parentNode.ownerDocument, parentNode); | ||
return child; | ||
} | ||
/** | ||
* preformance key(refChild == null) | ||
* Returns `true` if `node` can be a parent for insertion. | ||
* @param {Node} node | ||
* @returns {boolean} | ||
*/ | ||
function _insertBefore(parentNode,newChild,nextChild){ | ||
var cp = newChild.parentNode; | ||
function hasValidParentNodeType(node) { | ||
return ( | ||
node && | ||
(node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE || node.nodeType === Node.ELEMENT_NODE) | ||
); | ||
} | ||
/** | ||
* Returns `true` if `node` can be inserted according to it's `nodeType`. | ||
* @param {Node} node | ||
* @returns {boolean} | ||
*/ | ||
function hasInsertableNodeType(node) { | ||
return ( | ||
node && | ||
(isElementNode(node) || | ||
isTextNode(node) || | ||
isDocTypeNode(node) || | ||
node.nodeType === Node.DOCUMENT_FRAGMENT_NODE || | ||
node.nodeType === Node.COMMENT_NODE || | ||
node.nodeType === Node.PROCESSING_INSTRUCTION_NODE) | ||
); | ||
} | ||
/** | ||
* Returns true if `node` is a DOCTYPE node | ||
* @param {Node} node | ||
* @returns {boolean} | ||
*/ | ||
function isDocTypeNode(node) { | ||
return node && node.nodeType === Node.DOCUMENT_TYPE_NODE; | ||
} | ||
/** | ||
* Returns true if the node is an element | ||
* @param {Node} node | ||
* @returns {boolean} | ||
*/ | ||
function isElementNode(node) { | ||
return node && node.nodeType === Node.ELEMENT_NODE; | ||
} | ||
/** | ||
* Returns true if `node` is a text node | ||
* @param {Node} node | ||
* @returns {boolean} | ||
*/ | ||
function isTextNode(node) { | ||
return node && node.nodeType === Node.TEXT_NODE; | ||
} | ||
/** | ||
* Check if en element node can be inserted before `child`, or at the end if child is falsy, | ||
* according to the presence and position of a doctype node on the same level. | ||
* | ||
* @param {Document} doc The document node | ||
* @param {Node} child the node that would become the nextSibling if the element would be inserted | ||
* @returns {boolean} `true` if an element can be inserted before child | ||
* @private | ||
* https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity | ||
*/ | ||
function isElementInsertionPossible(doc, child) { | ||
var parentChildNodes = doc.childNodes || []; | ||
if (find(parentChildNodes, isElementNode) || isDocTypeNode(child)) { | ||
return false; | ||
} | ||
var docTypeNode = find(parentChildNodes, isDocTypeNode); | ||
return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child)); | ||
} | ||
/** | ||
* Check if en element node can be inserted before `child`, or at the end if child is falsy, | ||
* according to the presence and position of a doctype node on the same level. | ||
* | ||
* @param {Node} doc The document node | ||
* @param {Node} child the node that would become the nextSibling if the element would be inserted | ||
* @returns {boolean} `true` if an element can be inserted before child | ||
* @private | ||
* https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity | ||
*/ | ||
function isElementReplacementPossible(doc, child) { | ||
var parentChildNodes = doc.childNodes || []; | ||
function hasElementChildThatIsNotChild(node) { | ||
return isElementNode(node) && node !== child; | ||
} | ||
if (find(parentChildNodes, hasElementChildThatIsNotChild)) { | ||
return false; | ||
} | ||
var docTypeNode = find(parentChildNodes, isDocTypeNode); | ||
return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child)); | ||
} | ||
/** | ||
* @private | ||
* Steps 1-5 of the checks before inserting and before replacing a child are the same. | ||
* | ||
* @param {Node} parent the parent node to insert `node` into | ||
* @param {Node} node the node to insert | ||
* @param {Node=} child the node that should become the `nextSibling` of `node` | ||
* @returns {Node} | ||
* @throws DOMException for several node combinations that would create a DOM that is not well-formed. | ||
* @throws DOMException if `child` is provided but is not a child of `parent`. | ||
* @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity | ||
* @see https://dom.spec.whatwg.org/#concept-node-replace | ||
*/ | ||
function assertPreInsertionValidity1to5(parent, node, child) { | ||
// 1. If `parent` is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException. | ||
if (!hasValidParentNodeType(parent)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Unexpected parent node type ' + parent.nodeType); | ||
} | ||
// 2. If `node` is a host-including inclusive ancestor of `parent`, then throw a "HierarchyRequestError" DOMException. | ||
// not implemented! | ||
// 3. If `child` is non-null and its parent is not `parent`, then throw a "NotFoundError" DOMException. | ||
if (child && child.parentNode !== parent) { | ||
throw new DOMException(NOT_FOUND_ERR, 'child not in parent'); | ||
} | ||
if ( | ||
// 4. If `node` is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException. | ||
!hasInsertableNodeType(node) || | ||
// 5. If either `node` is a Text node and `parent` is a document, | ||
// the sax parser currently adds top level text nodes, this will be fixed in 0.9.0 | ||
// || (node.nodeType === Node.TEXT_NODE && parent.nodeType === Node.DOCUMENT_NODE) | ||
// or `node` is a doctype and `parent` is not a document, then throw a "HierarchyRequestError" DOMException. | ||
(isDocTypeNode(node) && parent.nodeType !== Node.DOCUMENT_NODE) | ||
) { | ||
throw new DOMException( | ||
HIERARCHY_REQUEST_ERR, | ||
'Unexpected node type ' + node.nodeType + ' for parent node type ' + parent.nodeType | ||
); | ||
} | ||
} | ||
/** | ||
* @private | ||
* Step 6 of the checks before inserting and before replacing a child are different. | ||
* | ||
* @param {Document} parent the parent node to insert `node` into | ||
* @param {Node} node the node to insert | ||
* @param {Node | undefined} child the node that should become the `nextSibling` of `node` | ||
* @returns {Node} | ||
* @throws DOMException for several node combinations that would create a DOM that is not well-formed. | ||
* @throws DOMException if `child` is provided but is not a child of `parent`. | ||
* @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity | ||
* @see https://dom.spec.whatwg.org/#concept-node-replace | ||
*/ | ||
function assertPreInsertionValidityInDocument(parent, node, child) { | ||
var parentChildNodes = parent.childNodes || []; | ||
var nodeChildNodes = node.childNodes || []; | ||
// DocumentFragment | ||
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { | ||
var nodeChildElements = nodeChildNodes.filter(isElementNode); | ||
// If node has more than one element child or has a Text node child. | ||
if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment'); | ||
} | ||
// Otherwise, if `node` has one element child and either `parent` has an element child, | ||
// `child` is a doctype, or `child` is non-null and a doctype is following `child`. | ||
if (nodeChildElements.length === 1 && !isElementInsertionPossible(parent, child)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype'); | ||
} | ||
} | ||
// Element | ||
if (isElementNode(node)) { | ||
// `parent` has an element child, `child` is a doctype, | ||
// or `child` is non-null and a doctype is following `child`. | ||
if (!isElementInsertionPossible(parent, child)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype'); | ||
} | ||
} | ||
// DocumentType | ||
if (isDocTypeNode(node)) { | ||
// `parent` has a doctype child, | ||
if (find(parentChildNodes, isDocTypeNode)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed'); | ||
} | ||
var parentElementChild = find(parentChildNodes, isElementNode); | ||
// `child` is non-null and an element is preceding `child`, | ||
if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element'); | ||
} | ||
// or `child` is null and `parent` has an element child. | ||
if (!child && parentElementChild) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can not be appended since element is present'); | ||
} | ||
} | ||
} | ||
/** | ||
* @private | ||
* Step 6 of the checks before inserting and before replacing a child are different. | ||
* | ||
* @param {Document} parent the parent node to insert `node` into | ||
* @param {Node} node the node to insert | ||
* @param {Node | undefined} child the node that should become the `nextSibling` of `node` | ||
* @returns {Node} | ||
* @throws DOMException for several node combinations that would create a DOM that is not well-formed. | ||
* @throws DOMException if `child` is provided but is not a child of `parent`. | ||
* @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity | ||
* @see https://dom.spec.whatwg.org/#concept-node-replace | ||
*/ | ||
function assertPreReplacementValidityInDocument(parent, node, child) { | ||
var parentChildNodes = parent.childNodes || []; | ||
var nodeChildNodes = node.childNodes || []; | ||
// DocumentFragment | ||
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { | ||
var nodeChildElements = nodeChildNodes.filter(isElementNode); | ||
// If `node` has more than one element child or has a Text node child. | ||
if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment'); | ||
} | ||
// Otherwise, if `node` has one element child and either `parent` has an element child that is not `child` or a doctype is following `child`. | ||
if (nodeChildElements.length === 1 && !isElementReplacementPossible(parent, child)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype'); | ||
} | ||
} | ||
// Element | ||
if (isElementNode(node)) { | ||
// `parent` has an element child that is not `child` or a doctype is following `child`. | ||
if (!isElementReplacementPossible(parent, child)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype'); | ||
} | ||
} | ||
// DocumentType | ||
if (isDocTypeNode(node)) { | ||
function hasDoctypeChildThatIsNotChild(node) { | ||
return isDocTypeNode(node) && node !== child; | ||
} | ||
// `parent` has a doctype child that is not `child`, | ||
if (find(parentChildNodes, hasDoctypeChildThatIsNotChild)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed'); | ||
} | ||
var parentElementChild = find(parentChildNodes, isElementNode); | ||
// or an element is preceding `child`. | ||
if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) { | ||
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element'); | ||
} | ||
} | ||
} | ||
/** | ||
* @private | ||
* @param {Node} parent the parent node to insert `node` into | ||
* @param {Node} node the node to insert | ||
* @param {Node=} child the node that should become the `nextSibling` of `node` | ||
* @returns {Node} | ||
* @throws DOMException for several node combinations that would create a DOM that is not well-formed. | ||
* @throws DOMException if `child` is provided but is not a child of `parent`. | ||
* @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity | ||
*/ | ||
function _insertBefore(parent, node, child, _inDocumentAssertion) { | ||
// To ensure pre-insertion validity of a node into a parent before a child, run these steps: | ||
assertPreInsertionValidity1to5(parent, node, child); | ||
// If parent is a document, and any of the statements below, switched on the interface node implements, | ||
// are true, then throw a "HierarchyRequestError" DOMException. | ||
if (parent.nodeType === Node.DOCUMENT_NODE) { | ||
(_inDocumentAssertion || assertPreInsertionValidityInDocument)(parent, node, child); | ||
} | ||
var cp = node.parentNode; | ||
if(cp){ | ||
cp.removeChild(newChild);//remove and update | ||
cp.removeChild(node);//remove and update | ||
} | ||
if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){ | ||
var newFirst = newChild.firstChild; | ||
if(node.nodeType === DOCUMENT_FRAGMENT_NODE){ | ||
var newFirst = node.firstChild; | ||
if (newFirst == null) { | ||
return newChild; | ||
return node; | ||
} | ||
var newLast = newChild.lastChild; | ||
var newLast = node.lastChild; | ||
}else{ | ||
newFirst = newLast = newChild; | ||
newFirst = newLast = node; | ||
} | ||
var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild; | ||
var pre = child ? child.previousSibling : parent.lastChild; | ||
newFirst.previousSibling = pre; | ||
newLast.nextSibling = nextChild; | ||
newLast.nextSibling = child; | ||
if(pre){ | ||
pre.nextSibling = newFirst; | ||
}else{ | ||
parentNode.firstChild = newFirst; | ||
parent.firstChild = newFirst; | ||
} | ||
if(nextChild == null){ | ||
parentNode.lastChild = newLast; | ||
if(child == null){ | ||
parent.lastChild = newLast; | ||
}else{ | ||
nextChild.previousSibling = newLast; | ||
child.previousSibling = newLast; | ||
} | ||
do{ | ||
newFirst.parentNode = parentNode; | ||
newFirst.parentNode = parent; | ||
}while(newFirst !== newLast && (newFirst= newFirst.nextSibling)) | ||
_onUpdateChild(parentNode.ownerDocument||parentNode,parentNode); | ||
//console.log(parentNode.lastChild.nextSibling == null) | ||
if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) { | ||
newChild.firstChild = newChild.lastChild = null; | ||
_onUpdateChild(parent.ownerDocument||parent, parent); | ||
//console.log(parent.lastChild.nextSibling == null) | ||
if (node.nodeType == DOCUMENT_FRAGMENT_NODE) { | ||
node.firstChild = node.lastChild = null; | ||
} | ||
return newChild; | ||
return node; | ||
} | ||
function _appendSingleChild(parentNode,newChild){ | ||
var cp = newChild.parentNode; | ||
if(cp){ | ||
var pre = parentNode.lastChild; | ||
cp.removeChild(newChild);//remove and update | ||
var pre = parentNode.lastChild; | ||
/** | ||
* Appends `newChild` to `parentNode`. | ||
* If `newChild` is already connected to a `parentNode` it is first removed from it. | ||
* | ||
* @see https://github.com/xmldom/xmldom/issues/135 | ||
* @see https://github.com/xmldom/xmldom/issues/145 | ||
* @param {Node} parentNode | ||
* @param {Node} newChild | ||
* @returns {Node} | ||
* @private | ||
*/ | ||
function _appendSingleChild (parentNode, newChild) { | ||
if (newChild.parentNode) { | ||
newChild.parentNode.removeChild(newChild); | ||
} | ||
var pre = parentNode.lastChild; | ||
newChild.parentNode = parentNode; | ||
newChild.previousSibling = pre; | ||
newChild.previousSibling = parentNode.lastChild; | ||
newChild.nextSibling = null; | ||
if(pre){ | ||
pre.nextSibling = newChild; | ||
}else{ | ||
if (newChild.previousSibling) { | ||
newChild.previousSibling.nextSibling = newChild; | ||
} else { | ||
parentNode.firstChild = newChild; | ||
} | ||
parentNode.lastChild = newChild; | ||
_onUpdateChild(parentNode.ownerDocument,parentNode,newChild); | ||
_onUpdateChild(parentNode.ownerDocument, parentNode, newChild); | ||
return newChild; | ||
//console.log("__aa",parentNode.lastChild.nextSibling == null) | ||
} | ||
Document.prototype = { | ||
@@ -739,7 +1051,9 @@ //implementation : null, | ||
} | ||
if(this.documentElement == null && newChild.nodeType == ELEMENT_NODE){ | ||
_insertBefore(this, newChild, refChild); | ||
newChild.ownerDocument = this; | ||
if (this.documentElement === null && newChild.nodeType === ELEMENT_NODE) { | ||
this.documentElement = newChild; | ||
} | ||
return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild; | ||
return newChild; | ||
}, | ||
@@ -752,2 +1066,13 @@ removeChild : function(oldChild){ | ||
}, | ||
replaceChild: function (newChild, oldChild) { | ||
//raises | ||
_insertBefore(this, newChild, oldChild, assertPreReplacementValidityInDocument); | ||
newChild.ownerDocument = this; | ||
if (oldChild) { | ||
this.removeChild(oldChild); | ||
} | ||
if (isElementNode(newChild)) { | ||
this.documentElement = newChild; | ||
} | ||
}, | ||
// Introduced in DOM Level 2: | ||
@@ -939,3 +1264,3 @@ importNode : function(importedNode,deep){ | ||
}, | ||
//four real opeartion method | ||
@@ -964,3 +1289,3 @@ appendChild:function(newChild){ | ||
}, | ||
hasAttributeNS : function(namespaceURI, localName){ | ||
@@ -981,3 +1306,3 @@ return this.getAttributeNodeNS(namespaceURI, localName)!=null; | ||
}, | ||
getElementsByTagName : function(tagName){ | ||
@@ -1003,3 +1328,3 @@ return new LiveNodeList(this,function(base){ | ||
return ls; | ||
}); | ||
@@ -1033,3 +1358,3 @@ } | ||
this.replaceData(offset,0,text); | ||
}, | ||
@@ -1128,3 +1453,3 @@ appendChild:function(newChild){ | ||
var uri = refNode.namespaceURI; | ||
if(uri && prefix == null){ | ||
@@ -1162,4 +1487,4 @@ //console.log(prefix) | ||
} | ||
var i = visibleNamespaces.length | ||
var i = visibleNamespaces.length | ||
while (i--) { | ||
@@ -1176,8 +1501,15 @@ var ns = visibleNamespaces[i]; | ||
* Well-formed constraint: No < in Attribute Values | ||
* The replacement text of any entity referred to directly or indirectly in an attribute value must not contain a <. | ||
* @see https://www.w3.org/TR/xml/#CleanAttrVals | ||
* @see https://www.w3.org/TR/xml/#NT-AttValue | ||
* > The replacement text of any entity referred to directly or indirectly | ||
* > in an attribute value must not contain a <. | ||
* @see https://www.w3.org/TR/xml11/#CleanAttrVals | ||
* @see https://www.w3.org/TR/xml11/#NT-AttValue | ||
* | ||
* Literal whitespace other than space that appear in attribute values | ||
* are serialized as their entity references, so they will be preserved. | ||
* (In contrast to whitespace literals in the input which are normalized to spaces) | ||
* @see https://www.w3.org/TR/xml11/#AVNormalize | ||
* @see https://w3c.github.io/DOM-Parsing/#serializing-an-element-s-attributes | ||
*/ | ||
function addSerializedAttribute(buf, qualifiedName, value) { | ||
buf.push(' ', qualifiedName, '="', value.replace(/[<&"]/g,_xmlEncoder), '"') | ||
buf.push(' ', qualifiedName, '="', value.replace(/[<>&"\t\n\r]/g, _xmlEncoder), '"') | ||
} | ||
@@ -1209,3 +1541,3 @@ | ||
var nodeName = node.tagName; | ||
isHTML = NAMESPACE.isHTML(node.namespaceURI) || isHTML | ||
@@ -1269,3 +1601,3 @@ | ||
// add namespace for current node | ||
// add namespace for current node | ||
if (nodeName === prefixedNodeName && needNamespaceDefine(node, isHTML, visibleNamespaces)) { | ||
@@ -1277,3 +1609,3 @@ var prefix = node.prefix||''; | ||
} | ||
if(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){ | ||
@@ -1330,6 +1662,6 @@ buf.push('>'); | ||
* @see https://www.w3.org/TR/xml/#NT-CharData | ||
* @see https://w3c.github.io/DOM-Parsing/#xml-serializing-a-text-node | ||
*/ | ||
return buf.push(node.data | ||
.replace(/[<&]/g,_xmlEncoder) | ||
.replace(/]]>/g, ']]>') | ||
.replace(/[<&>]/g,_xmlEncoder) | ||
); | ||
@@ -1420,7 +1752,9 @@ case CDATA_SECTION_NODE: | ||
var node2 = new node.constructor(); | ||
for(var n in node){ | ||
var v = node[n]; | ||
if(typeof v != 'object' ){ | ||
if(v != node2[n]){ | ||
node2[n] = v; | ||
for (var n in node) { | ||
if (Object.prototype.hasOwnProperty.call(node, n)) { | ||
var v = node[n]; | ||
if (typeof v != "object") { | ||
if (v != node2[n]) { | ||
node2[n] = v; | ||
} | ||
} | ||
@@ -1493,3 +1827,3 @@ } | ||
}) | ||
function getTextContent(node){ | ||
@@ -1496,0 +1830,0 @@ switch(node.nodeType){ |
@@ -15,3 +15,3 @@ var NAMESPACE = require("./conventions").NAMESPACE; | ||
var S_TAG = 0;//tag name offerring | ||
var S_ATTR = 1;//attr name offerring | ||
var S_ATTR = 1;//attr name offerring | ||
var S_ATTR_SPACE=2;//attr name end and space offer | ||
@@ -40,3 +40,3 @@ var S_EQ = 3;//=space? | ||
function XMLReader(){ | ||
} | ||
@@ -70,4 +70,4 @@ | ||
var k = a.slice(1,-1); | ||
if(k in entityMap){ | ||
return entityMap[k]; | ||
if (Object.hasOwnProperty.call(entityMap, k)) { | ||
return entityMap[k]; | ||
}else if(k.charAt(0) === '#'){ | ||
@@ -101,3 +101,3 @@ return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x'))) | ||
var locator = domBuilder.locator; | ||
var parseStack = [{currentNSMap:defaultNSMapCopy}] | ||
@@ -127,3 +127,3 @@ var closeMap = {}; | ||
if(end<0){ | ||
tagName = source.substring(tagStart+2).replace(/[\s<].*/,''); | ||
@@ -143,4 +143,6 @@ errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName); | ||
if(localNSMap){ | ||
for(var prefix in localNSMap){ | ||
domBuilder.endPrefixMapping(prefix) ; | ||
for (var prefix in localNSMap) { | ||
if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) { | ||
domBuilder.endPrefixMapping(prefix); | ||
} | ||
} | ||
@@ -154,3 +156,3 @@ } | ||
} | ||
end++; | ||
@@ -174,4 +176,4 @@ break; | ||
var len = el.length; | ||
if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){ | ||
@@ -244,3 +246,11 @@ el.closed = true; | ||
} | ||
el.addValue(qname, value, startIndex) | ||
el.addValue( | ||
qname, | ||
// @see https://www.w3.org/TR/xml/#AVNormalize | ||
// since the xmldom sax parser does not "interpret" DTD the following is not implemented: | ||
// - recursive replacement of (DTD) entity references | ||
// - trimming and collapsing multiple spaces into a single one for attributes that are not of type CDATA | ||
value.replace(/[\t\n\r]/g, ' ').replace(/&#?\w+;/g, entityReplacer), | ||
startIndex | ||
) | ||
} | ||
@@ -276,3 +286,3 @@ var attrName; | ||
if(p>0){ | ||
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer); | ||
value = source.slice(start, p); | ||
addAttribute(attrName, value, start-1); | ||
@@ -285,6 +295,4 @@ s = S_ATTR_END; | ||
}else if(s == S_ATTR_NOQUOT_VALUE){ | ||
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer); | ||
//console.log(attrName,value,start,p) | ||
value = source.slice(start, p); | ||
addAttribute(attrName, value, start); | ||
//console.dir(el) | ||
errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!'); | ||
@@ -309,4 +317,6 @@ start = p+1; | ||
case S_ATTR: | ||
case S_ATTR_SPACE: | ||
break; | ||
case S_ATTR_SPACE: | ||
el.closed = true; | ||
break; | ||
//case S_EQ: | ||
@@ -344,3 +354,3 @@ default: | ||
errorHandler.warning('attribute "'+value+'" missed quot(")!'); | ||
addAttribute(attrName, value.replace(/&#?\w+;/g,entityReplacer), start) | ||
addAttribute(attrName, value, start) | ||
}else{ | ||
@@ -373,3 +383,3 @@ if(!NAMESPACE.isHTML(currentNSMap['']) || !value.match(/^(?:disabled|checked|selected)$/i)){ | ||
case S_ATTR_NOQUOT_VALUE: | ||
var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer); | ||
var value = source.slice(start, p); | ||
errorHandler.warning('attribute "'+value+'" missed quot(")!!'); | ||
@@ -446,3 +456,3 @@ addAttribute(attrName, value, start) | ||
a.localName = localName ; | ||
//prefix == null for no ns prefix attribute | ||
//prefix == null for no ns prefix attribute | ||
if(nsPrefix !== false){//hack!! | ||
@@ -457,3 +467,3 @@ if(localNSMap == null){ | ||
a.uri = NAMESPACE.XMLNS | ||
domBuilder.startPrefixMapping(nsPrefix, value) | ||
domBuilder.startPrefixMapping(nsPrefix, value) | ||
} | ||
@@ -470,3 +480,3 @@ } | ||
a.uri = currentNSMap[prefix || ''] | ||
//{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)} | ||
@@ -492,4 +502,6 @@ } | ||
if(localNSMap){ | ||
for(prefix in localNSMap){ | ||
domBuilder.endPrefixMapping(prefix) | ||
for (prefix in localNSMap) { | ||
if (Object.prototype.hasOwnProperty.call(localNSMap, prefix)) { | ||
domBuilder.endPrefixMapping(prefix); | ||
} | ||
} | ||
@@ -521,3 +533,3 @@ } | ||
//} | ||
} | ||
@@ -539,7 +551,13 @@ } | ||
return pos<elStartEnd; | ||
//} | ||
//} | ||
} | ||
function _copy(source,target){ | ||
for(var n in source){target[n] = source[n]} | ||
function _copy (source, target) { | ||
for (var n in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, n)) { | ||
target[n] = source[n]; | ||
} | ||
} | ||
} | ||
function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!' | ||
@@ -568,7 +586,7 @@ var next= source.charAt(start+2) | ||
domBuilder.characters(source,start+9,end-start-9); | ||
domBuilder.endCDATA() | ||
domBuilder.endCDATA() | ||
return end+3; | ||
} | ||
//<!DOCTYPE | ||
//startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) | ||
//startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) | ||
var matchs = split(source,start); | ||
@@ -591,3 +609,3 @@ var len = matchs.length; | ||
domBuilder.endDTD(); | ||
return lastMatch.index+lastMatch[0].length | ||
@@ -641,3 +659,3 @@ } | ||
// if(localName){ | ||
// | ||
// | ||
// }else{ | ||
@@ -644,0 +662,0 @@ // var qName = uri |
{ | ||
"name": "@xmldom/xmldom", | ||
"version": "0.7.5", | ||
"version": "0.8.7", | ||
"description": "A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module.", | ||
@@ -26,2 +26,3 @@ "keywords": [ | ||
"readme.md", | ||
"SECURITY.md", | ||
"index.d.ts", | ||
@@ -32,6 +33,11 @@ "lib" | ||
"lint": "eslint lib test", | ||
"format": "prettier --write test", | ||
"changelog": "auto-changelog --unreleased-only", | ||
"start": "nodemon --watch package.json --watch lib --watch test --exec 'npm --silent run test && npm --silent run lint'", | ||
"stryker": "stryker run", | ||
"stryker:dry-run": "stryker run -m '' --reporters progress", | ||
"test": "jest" | ||
"test": "jest", | ||
"testrelease": "npm test && eslint lib", | ||
"version": "./changelog-has-version.sh", | ||
"release": "np --no-yarn --test-script testrelease --branch release-0.8.x patch" | ||
}, | ||
@@ -43,13 +49,15 @@ "engines": { | ||
"devDependencies": { | ||
"@stryker-mutator/core": "^5.2.2", | ||
"eslint": "^7.32.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-es5": "^1.5.0", | ||
"eslint-plugin-prettier": "^3.4.1", | ||
"get-stream": "^6.0.1", | ||
"jest": "^27.0.6", | ||
"nodemon": "^2.0.12", | ||
"prettier": "^2.3.2", | ||
"xmltest": "^1.5.0", | ||
"yauzl": "^2.10.0" | ||
"@stryker-mutator/core": "5.6.1", | ||
"auto-changelog": "2.4.0", | ||
"eslint": "8.25.0", | ||
"eslint-config-prettier": "8.5.0", | ||
"eslint-plugin-es5": "1.5.0", | ||
"eslint-plugin-prettier": "4.2.1", | ||
"get-stream": "6.0.1", | ||
"jest": "27.5.1", | ||
"nodemon": "2.0.20", | ||
"np": "7.6.2", | ||
"prettier": "2.7.1", | ||
"xmltest": "1.5.0", | ||
"yauzl": "2.10.0" | ||
}, | ||
@@ -59,3 +67,9 @@ "bugs": { | ||
}, | ||
"license": "MIT" | ||
"license": "MIT", | ||
"auto-changelog": { | ||
"prepend": true, | ||
"remote": "upstream", | ||
"tagPrefix": "", | ||
"template": "./auto-changelog.hbs" | ||
} | ||
} |
@@ -6,4 +6,5 @@ # @xmldom/xmldom | ||
[![license](https://img.shields.io/npm/l/@xmldom/xmldom?color=blue&style=flat-square)](LICENSE) | ||
[![license(MIT)](https://img.shields.io/npm/l/@xmldom/xmldom?color=blue&style=flat-square)](https://github.com/xmldom/xmldom/blob/master/LICENSE) | ||
[![npm](https://img.shields.io/npm/v/@xmldom/xmldom?style=flat-square)](https://www.npmjs.com/package/@xmldom/xmldom) | ||
[![snyk.io package health](https://snyk.io/advisor/npm-package/@xmldom/xmldom/badge.svg)](https://snyk.io/advisor/npm-package/@xmldom/xmldom) | ||
[![bug issues](https://img.shields.io/github/issues/xmldom/xmldom/bug?color=red&style=flat-square)](https://github.com/xmldom/xmldom/issues?q=is%3Aissue+is%3Aopen+label%3Abug) | ||
@@ -44,24 +45,19 @@ [![help-wanted issues](https://img.shields.io/github/issues/xmldom/xmldom/help-wanted?color=darkgreen&style=flat-square)](https://github.com/xmldom/xmldom/issues?q=is%3Aissue+is%3Aopen+label%3Ahelp-wanted) | ||
[In NodeJS](examples/nodejs/src/index.js) | ||
```javascript | ||
const { DOMParser } = require('@xmldom/xmldom') | ||
const { DOMParser, XMLSerializer } = require('@xmldom/xmldom') | ||
const doc = new DOMParser().parseFromString( | ||
'<xml xmlns="a" xmlns:c="./lite">\n' + | ||
'\t<child>test</child>\n' + | ||
'\t<child></child>\n' + | ||
'\t<child/>\n' + | ||
'</xml>', | ||
'text/xml' | ||
) | ||
doc.documentElement.setAttribute('x', 'y') | ||
doc.documentElement.setAttributeNS('./lite', 'c:x', 'y2') | ||
console.info(doc) | ||
const source = `<xml xmlns="a"> | ||
<child>test</child> | ||
<child/> | ||
</xml>` | ||
const nsAttr = doc.documentElement.getAttributeNS('./lite', 'x') | ||
console.info(nsAttr) | ||
const doc = new DOMParser().parseFromString(source, 'text/xml') | ||
const serialized = new XMLSerializer().serializeToString(doc) | ||
``` | ||
Note: in Typescript and ES6 you can use the import approach, as follows: | ||
Note: in Typescript ~and ES6~(see #316) you can use the `import` approach, as follows: | ||
```javascript | ||
```typescript | ||
import { DOMParser } from '@xmldom/xmldom' | ||
@@ -107,168 +103,192 @@ ``` | ||
* [Node](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247) | ||
attribute: | ||
nodeValue|prefix | ||
readonly attribute: | ||
nodeName|nodeType|parentNode|childNodes|firstChild|lastChild|previousSibling|nextSibling|attributes|ownerDocument|namespaceURI|localName | ||
method: | ||
insertBefore(newChild, refChild) | ||
replaceChild(newChild, oldChild) | ||
removeChild(oldChild) | ||
appendChild(newChild) | ||
hasChildNodes() | ||
cloneNode(deep) | ||
normalize() | ||
isSupported(feature, version) | ||
hasAttributes() | ||
* [Node](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247) | ||
readonly class properties (aka `NodeType`), | ||
these can be accessed from any `Node` instance `node`: | ||
`if (node.nodeType === node.ELEMENT_NODE) {...` | ||
1. `ELEMENT_NODE` (`1`) | ||
2. `ATTRIBUTE_NODE` (`2`) | ||
3. `TEXT_NODE` (`3`) | ||
4. `CDATA_SECTION_NODE` (`4`) | ||
5. `ENTITY_REFERENCE_NODE` (`5`) | ||
6. `ENTITY_NODE` (`6`) | ||
7. `PROCESSING_INSTRUCTION_NODE` (`7`) | ||
8. `COMMENT_NODE` (`8`) | ||
9. `DOCUMENT_NODE` (`9`) | ||
10. `DOCUMENT_TYPE_NODE` (`10`) | ||
11. `DOCUMENT_FRAGMENT_NODE` (`11`) | ||
12. `NOTATION_NODE` (`12`) | ||
attribute: | ||
- `nodeValue` | `prefix` | ||
readonly attribute: | ||
- `nodeName` | `nodeType` | `parentNode` | `childNodes` | `firstChild` | `lastChild` | `previousSibling` | `nextSibling` | `attributes` | `ownerDocument` | `namespaceURI` | `localName` | ||
method: | ||
* `insertBefore(newChild, refChild)` | ||
* `replaceChild(newChild, oldChild)` | ||
* `removeChild(oldChild)` | ||
* `appendChild(newChild)` | ||
* `hasChildNodes()` | ||
* `cloneNode(deep)` | ||
* `normalize()` | ||
* `isSupported(feature, version)` | ||
* `hasAttributes()` | ||
* [DOMException](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html) | ||
The DOMException class has the following constants (and `value` of type `Number`): | ||
1. `DOMException.INDEX_SIZE_ERR` (`1`) | ||
1. `DOMException.DOMSTRING_SIZE_ERR` (`2`) | ||
1. `DOMException.HIERARCHY_REQUEST_ERR` (`3`) | ||
1. `DOMException.WRONG_DOCUMENT_ERR` (`4`) | ||
1. `DOMException.INVALID_CHARACTER_ERR` (`5`) | ||
1. `DOMException.NO_DATA_ALLOWED_ERR` (`6`) | ||
1. `DOMException.NO_MODIFICATION_ALLOWED_ERR` (`7`) | ||
1. `DOMException.NOT_FOUND_ERR` (`8`) | ||
1. `DOMException.NOT_SUPPORTED_ERR` (`9`) | ||
1. `DOMException.INUSE_ATTRIBUTE_ERR` (`10`) | ||
1. `DOMException.INVALID_STATE_ERR` (`11`) | ||
1. `DOMException.SYNTAX_ERR` (`12`) | ||
1. `DOMException.INVALID_MODIFICATION_ERR` (`13`) | ||
1. `DOMException.NAMESPACE_ERR` (`14`) | ||
1. `DOMException.INVALID_ACCESS_ERR` (`15`) | ||
extends the Error type thrown as part of DOM API. | ||
readonly class properties: | ||
- `INDEX_SIZE_ERR` (`1`) | ||
- `DOMSTRING_SIZE_ERR` (`2`) | ||
- `HIERARCHY_REQUEST_ERR` (`3`) | ||
- `WRONG_DOCUMENT_ERR` (`4`) | ||
- `INVALID_CHARACTER_ERR` (`5`) | ||
- `NO_DATA_ALLOWED_ERR` (`6`) | ||
- `NO_MODIFICATION_ALLOWED_ERR` (`7`) | ||
- `NOT_FOUND_ERR` (`8`) | ||
- `NOT_SUPPORTED_ERR` (`9`) | ||
- `INUSE_ATTRIBUTE_ERR` (`10`) | ||
- `INVALID_STATE_ERR` (`11`) | ||
- `SYNTAX_ERR` (`12`) | ||
- `INVALID_MODIFICATION_ERR` (`13`) | ||
- `NAMESPACE_ERR` (`14`) | ||
- `INVALID_ACCESS_ERR` (`15`) | ||
The DOMException object has the following properties: | ||
code | ||
This property is of type Number. | ||
attributes: | ||
- `code` with a value matching one of the above constants. | ||
* extends the Error type thrown as part of DOM API: | ||
* [DOMImplementation](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-102161490) | ||
* [DOMImplementation](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-102161490) | ||
method: | ||
hasFeature(feature, version) | ||
createDocumentType(qualifiedName, publicId, systemId) | ||
createDocument(namespaceURI, qualifiedName, doctype) | ||
method: | ||
- `hasFeature(feature, version)` | ||
- `createDocumentType(qualifiedName, publicId, systemId)` | ||
- `createDocument(namespaceURI, qualifiedName, doctype)` | ||
* [Document](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#i-Document) : Node | ||
* [Document](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#i-Document) : Node | ||
readonly attribute: | ||
doctype|implementation|documentElement | ||
method: | ||
createElement(tagName) | ||
createDocumentFragment() | ||
createTextNode(data) | ||
createComment(data) | ||
createCDATASection(data) | ||
createProcessingInstruction(target, data) | ||
createAttribute(name) | ||
createEntityReference(name) | ||
getElementsByTagName(tagname) | ||
importNode(importedNode, deep) | ||
createElementNS(namespaceURI, qualifiedName) | ||
createAttributeNS(namespaceURI, qualifiedName) | ||
getElementsByTagNameNS(namespaceURI, localName) | ||
getElementById(elementId) | ||
readonly attribute: | ||
- `doctype` | `implementation` | `documentElement` | ||
method: | ||
- `createElement(tagName)` | ||
- `createDocumentFragment()` | ||
- `createTextNode(data)` | ||
- `createComment(data)` | ||
- `createCDATASection(data)` | ||
- `createProcessingInstruction(target, data)` | ||
- `createAttribute(name)` | ||
- `createEntityReference(name)` | ||
- `getElementsByTagName(tagname)` | ||
- `importNode(importedNode, deep)` | ||
- `createElementNS(namespaceURI, qualifiedName)` | ||
- `createAttributeNS(namespaceURI, qualifiedName)` | ||
- `getElementsByTagNameNS(namespaceURI, localName)` | ||
- `getElementById(elementId)` | ||
* [DocumentFragment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-B63ED1A3) : Node | ||
* [Element](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-745549614) : Node | ||
* [DocumentFragment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-B63ED1A3) : Node | ||
* [Element](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-745549614) : Node | ||
readonly attribute: | ||
tagName | ||
method: | ||
getAttribute(name) | ||
setAttribute(name, value) | ||
removeAttribute(name) | ||
getAttributeNode(name) | ||
setAttributeNode(newAttr) | ||
removeAttributeNode(oldAttr) | ||
getElementsByTagName(name) | ||
getAttributeNS(namespaceURI, localName) | ||
setAttributeNS(namespaceURI, qualifiedName, value) | ||
removeAttributeNS(namespaceURI, localName) | ||
getAttributeNodeNS(namespaceURI, localName) | ||
setAttributeNodeNS(newAttr) | ||
getElementsByTagNameNS(namespaceURI, localName) | ||
hasAttribute(name) | ||
hasAttributeNS(namespaceURI, localName) | ||
readonly attribute: | ||
- `tagName` | ||
* [Attr](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-637646024) : Node | ||
attribute: | ||
value | ||
readonly attribute: | ||
name|specified|ownerElement | ||
method: | ||
- `getAttribute(name)` | ||
- `setAttribute(name, value)` | ||
- `removeAttribute(name)` | ||
- `getAttributeNode(name)` | ||
- `setAttributeNode(newAttr)` | ||
- `removeAttributeNode(oldAttr)` | ||
- `getElementsByTagName(name)` | ||
- `getAttributeNS(namespaceURI, localName)` | ||
- `setAttributeNS(namespaceURI, qualifiedName, value)` | ||
- `removeAttributeNS(namespaceURI, localName)` | ||
- `getAttributeNodeNS(namespaceURI, localName)` | ||
- `setAttributeNodeNS(newAttr)` | ||
- `getElementsByTagNameNS(namespaceURI, localName)` | ||
- `hasAttribute(name)` | ||
- `hasAttributeNS(namespaceURI, localName)` | ||
* [NodeList](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177) | ||
* [Attr](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-637646024) : Node | ||
attribute: | ||
- `value` | ||
readonly attribute: | ||
- `name` | `specified` | `ownerElement` | ||
* [NodeList](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177) | ||
readonly attribute: | ||
length | ||
method: | ||
item(index) | ||
readonly attribute: | ||
- `length` | ||
method: | ||
- `item(index)` | ||
* [NamedNodeMap](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1780488922) | ||
* [NamedNodeMap](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1780488922) | ||
readonly attribute: | ||
length | ||
method: | ||
getNamedItem(name) | ||
setNamedItem(arg) | ||
removeNamedItem(name) | ||
item(index) | ||
getNamedItemNS(namespaceURI, localName) | ||
setNamedItemNS(arg) | ||
removeNamedItemNS(namespaceURI, localName) | ||
readonly attribute: | ||
- `length` | ||
method: | ||
- `getNamedItem(name)` | ||
- `setNamedItem(arg)` | ||
- `removeNamedItem(name)` | ||
- `item(index)` | ||
- `getNamedItemNS(namespaceURI, localName)` | ||
- `setNamedItemNS(arg)` | ||
- `removeNamedItemNS(namespaceURI, localName)` | ||
* [CharacterData](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-FF21A306) : Node | ||
* [CharacterData](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-FF21A306) : Node | ||
method: | ||
substringData(offset, count) | ||
appendData(arg) | ||
insertData(offset, arg) | ||
deleteData(offset, count) | ||
replaceData(offset, count, arg) | ||
method: | ||
- `substringData(offset, count)` | ||
- `appendData(arg)` | ||
- `insertData(offset, arg)` | ||
- `deleteData(offset, count)` | ||
- `replaceData(offset, count, arg)` | ||
* [Text](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1312295772) : CharacterData | ||
method: | ||
splitText(offset) | ||
* [Text](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1312295772) : CharacterData | ||
method: | ||
- `splitText(offset)` | ||
* [CDATASection](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-667469212) | ||
* [Comment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1728279322) : CharacterData | ||
* [CDATASection](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-667469212) | ||
* [Comment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1728279322) : CharacterData | ||
* [DocumentType](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-412266927) | ||
* [DocumentType](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-412266927) | ||
readonly attribute: | ||
name|entities|notations|publicId|systemId|internalSubset | ||
readonly attribute: | ||
- `name` | `entities` | `notations` | `publicId` | `systemId` | `internalSubset` | ||
* Notation : Node | ||
* Notation : Node | ||
readonly attribute: | ||
publicId|systemId | ||
readonly attribute: | ||
- `publicId` | `systemId` | ||
* Entity : Node | ||
* Entity : Node | ||
readonly attribute: | ||
publicId|systemId|notationName | ||
readonly attribute: | ||
- `publicId` | `systemId` | `notationName` | ||
* EntityReference : Node | ||
* ProcessingInstruction : Node | ||
attribute: | ||
data | ||
readonly attribute: | ||
target | ||
* EntityReference : Node | ||
* ProcessingInstruction : Node | ||
attribute: | ||
- `data` | ||
readonly attribute: | ||
- `target` | ||
### DOM level 3 support: | ||
* [Node](http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-textContent) | ||
* [Node](http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-textContent) | ||
attribute: | ||
textContent | ||
method: | ||
isDefaultNamespace(namespaceURI){ | ||
lookupNamespaceURI(prefix) | ||
attribute: | ||
- `textContent` | ||
method: | ||
- `isDefaultNamespace(namespaceURI)` | ||
- `lookupNamespaceURI(prefix)` | ||
@@ -279,7 +299,5 @@ ### DOM extension by xmldom | ||
attribute: | ||
//Numbered starting from '1' | ||
lineNumber | ||
//Numbered starting from '1' | ||
columnNumber | ||
attribute: | ||
- `lineNumber` //number starting from `1` | ||
- `columnNumber` //number starting from `1` | ||
@@ -342,2 +360,2 @@ ## Specs | ||
There is an idea/proposal to make ti possible to replace it with something else in <https://github.com/xmldom/xmldom/issues/55> | ||
There is an idea/proposal to make it possible to replace it with something else in <https://github.com/xmldom/xmldom/issues/55> |
{ | ||
"name": "pdf2json", | ||
"version": "2.0.1", | ||
"version": "2.0.2", | ||
"description": "PDF file parser that converts PDF binaries to text based JSON, powered by porting a fork of PDF.JS to Node.js", | ||
@@ -51,3 +51,3 @@ "keywords": [ | ||
"dependencies": { | ||
"@xmldom/xmldom": "^0.7.5" | ||
"@xmldom/xmldom": "^0.8.7" | ||
}, | ||
@@ -54,0 +54,0 @@ "devDependencies": {}, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1993185
67
47711
Updated@xmldom/xmldom@^0.8.7