@oozcitak/dom
Advanced tools
Comparing version 1.2.1 to 1.3.0
@@ -40,3 +40,3 @@ "use strict"; | ||
*/ | ||
if (TreeAlgorithm_1.tree_isAncestorOf(parent, node, true, true)) | ||
if (TreeAlgorithm_1.tree_isHostIncludingAncestorOf(parent, node, true)) | ||
throw new DOMException_1.HierarchyRequestError(`The node to be inserted cannot be an ancestor of parent node. Node is ${node.nodeName}, parent node is ${parent.nodeName}.`); | ||
@@ -194,3 +194,3 @@ /** | ||
// Optimized common case | ||
if (child === null && node.nodeType !== interfaces_1.NodeType.DocumentFragment && node._children.size === 0) { | ||
if (child === null && node.nodeType !== interfaces_1.NodeType.DocumentFragment) { | ||
mutation_insert_single(node, parent, suppressObservers); | ||
@@ -547,3 +547,3 @@ return; | ||
*/ | ||
if (TreeAlgorithm_1.tree_isAncestorOf(parent, node, true, true)) | ||
if (TreeAlgorithm_1.tree_isHostIncludingAncestorOf(parent, node, true)) | ||
throw new DOMException_1.HierarchyRequestError(`The node to be inserted cannot be an ancestor of parent node. Node is ${node.nodeName}, parent node is ${parent.nodeName}.`); | ||
@@ -550,0 +550,0 @@ /** |
@@ -166,2 +166,13 @@ import { Element, Node } from "../dom/interfaces"; | ||
/** | ||
* Determines whether `other` is a host-including ancestor of `node`. An | ||
* object A is a host-including inclusive ancestor of an object B, if either | ||
* A is an inclusive ancestor of B, or if B’s root has a non-null host and | ||
* A is a host-including inclusive ancestor of B’s root’s host. | ||
* | ||
* @param node - a node | ||
* @param other - the node to check | ||
* @param self - if `true`, traversal includes `node` itself | ||
*/ | ||
export declare function tree_isHostIncludingAncestorOf(node: Node, other: Node, self?: boolean): boolean; | ||
/** | ||
* Determines whether `other` is a sibling of `node`. An object A is | ||
@@ -168,0 +179,0 @@ * called a sibling of an object B, if and only if B and A share |
@@ -534,2 +534,22 @@ "use strict"; | ||
/** | ||
* Determines whether `other` is a host-including ancestor of `node`. An | ||
* object A is a host-including inclusive ancestor of an object B, if either | ||
* A is an inclusive ancestor of B, or if B’s root has a non-null host and | ||
* A is a host-including inclusive ancestor of B’s root’s host. | ||
* | ||
* @param node - a node | ||
* @param other - the node to check | ||
* @param self - if `true`, traversal includes `node` itself | ||
*/ | ||
function tree_isHostIncludingAncestorOf(node, other, self = false) { | ||
if (tree_isAncestorOf(node, other, self)) | ||
return true; | ||
const root = tree_rootNode(node); | ||
if (util_1.Guard.isDocumentFragmentNode(root) && root._host !== null && | ||
tree_isAncestorOf(root._host, other, true)) | ||
return true; | ||
return false; | ||
} | ||
exports.tree_isHostIncludingAncestorOf = tree_isHostIncludingAncestorOf; | ||
/** | ||
* Determines whether `other` is a sibling of `node`. An object A is | ||
@@ -536,0 +556,0 @@ * called a sibling of an object B, if and only if B and A share |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const dom_1 = require("../dom"); | ||
/** | ||
@@ -10,3 +9,44 @@ * Determines if the given string is valid for a `"Name"` construct. | ||
function xml_isName(name) { | ||
return dom_1.dom.regExp.Name.value.test(name); | ||
for (let i = 0; i < name.length; i++) { | ||
const c1 = name.charCodeAt(i); | ||
let n = c1; | ||
if (c1 >= 0xD800 && c1 <= 0xDBFF && i < name.length - 1) { | ||
const c2 = name.charCodeAt(i + 1); | ||
if (c2 >= 0xDC00 && c2 <= 0xDFFF) { | ||
n = (c1 - 0xD800) * 0x400 + c2 - 0xDC00 + 0x10000; | ||
} | ||
} | ||
// NameStartChar | ||
if ((n >= 97 && n <= 122) || // [a-z] | ||
(n >= 65 && n <= 90) || // [A-Z] | ||
n === 58 || n === 95 || // ':' or '_' | ||
(n >= 0xC0 && n <= 0xD6) || | ||
(n >= 0xD8 && n <= 0xF6) || | ||
(n >= 0xF8 && n <= 0x2FF) || | ||
(n >= 0x370 && n <= 0x37D) || | ||
(n >= 0x37F && n <= 0x1FFF) || | ||
(n >= 0x200C && n <= 0x200D) || | ||
(n >= 0x2070 && n <= 0x218F) || | ||
(n >= 0x2C00 && n <= 0x2FEF) || | ||
(n >= 0x3001 && n <= 0xD7FF) || | ||
(n >= 0xF900 && n <= 0xFDCF) || | ||
(n >= 0xFDF0 && n <= 0xFFFD) || | ||
(n >= 0x10000 && n <= 0xEFFFF)) { | ||
continue; | ||
} | ||
else if (i === 0) { | ||
return false; | ||
} | ||
else if (n === 45 || n === 46 || // '-' or '.' | ||
(n >= 48 && n <= 57) || // [0-9] | ||
(n === 0xB7) || | ||
(n >= 0x0300 && n <= 0x036F) || | ||
(n >= 0x203F && n <= 0x2040)) { | ||
continue; | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
@@ -20,3 +60,53 @@ exports.xml_isName = xml_isName; | ||
function xml_isQName(name) { | ||
return dom_1.dom.regExp.QName.value.test(name); | ||
let colonFound = false; | ||
for (let i = 0; i < name.length; i++) { | ||
const c1 = name.charCodeAt(i); | ||
let n = c1; | ||
if (c1 >= 0xD800 && c1 <= 0xDBFF && i < name.length - 1) { | ||
const c2 = name.charCodeAt(i + 1); | ||
if (c2 >= 0xDC00 && c2 <= 0xDFFF) { | ||
n = (c1 - 0xD800) * 0x400 + c2 - 0xDC00 + 0x10000; | ||
} | ||
} | ||
// NameStartChar | ||
if ((n >= 97 && n <= 122) || // [a-z] | ||
(n >= 65 && n <= 90) || // [A-Z] | ||
n === 95 || // or '_' | ||
(n >= 0xC0 && n <= 0xD6) || | ||
(n >= 0xD8 && n <= 0xF6) || | ||
(n >= 0xF8 && n <= 0x2FF) || | ||
(n >= 0x370 && n <= 0x37D) || | ||
(n >= 0x37F && n <= 0x1FFF) || | ||
(n >= 0x200C && n <= 0x200D) || | ||
(n >= 0x2070 && n <= 0x218F) || | ||
(n >= 0x2C00 && n <= 0x2FEF) || | ||
(n >= 0x3001 && n <= 0xD7FF) || | ||
(n >= 0xF900 && n <= 0xFDCF) || | ||
(n >= 0xFDF0 && n <= 0xFFFD) || | ||
(n >= 0x10000 && n <= 0xEFFFF)) { | ||
continue; | ||
} | ||
else if (i === 0) { | ||
return false; | ||
} | ||
else if (n === 58) { // ':' | ||
if (colonFound) | ||
return false; // multiple colons in qname | ||
if (i === name.length - 1) | ||
return false; // colon at the end of qname | ||
colonFound = true; | ||
continue; | ||
} | ||
else if (n === 45 || n === 46 || // '-' or '.' | ||
(n >= 48 && n <= 57) || // [0-9] | ||
(n === 0xB7) || | ||
(n >= 0x0300 && n <= 0x036F) || | ||
(n >= 0x203F && n <= 0x2040)) { | ||
continue; | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
@@ -31,8 +121,36 @@ exports.xml_isQName = xml_isQName; | ||
function xml_isLegalChar(chars, xmlVersion = "1.0") { | ||
if (xmlVersion === "1.0") { | ||
return (!dom_1.dom.regExp.InvalidChar_10.value.test(chars)); | ||
for (let i = 0; i < chars.length; i++) { | ||
const c1 = chars.charCodeAt(i); | ||
let n = c1; | ||
if (c1 >= 0xD800 && c1 <= 0xDBFF && i < chars.length - 1) { | ||
const c2 = chars.charCodeAt(i + 1); | ||
if (c2 >= 0xDC00 && c2 <= 0xDFFF) { | ||
n = (c1 - 0xD800) * 0x400 + c2 - 0xDC00 + 0x10000; | ||
} | ||
} | ||
if (xmlVersion === "1.0") { | ||
// #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] | ||
if (n === 0x9 || n === 0xA || n === 0xD || | ||
(n >= 0x20 && n <= 0xD7FF) || | ||
(n >= 0xE000 && n <= 0xFFFD) || | ||
(n >= 0x10000 && n <= 0x10FFFF)) { | ||
continue; | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
else { | ||
// [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] | ||
if ((n >= 0x1 && n <= 0xD7FF) || | ||
(n >= 0xE000 && n <= 0xFFFD) || | ||
(n >= 0x10000 && n <= 0x10FFFF)) { | ||
continue; | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
} | ||
else { | ||
return (!dom_1.dom.regExp.InvalidChar_11.value.test(chars)); | ||
} | ||
return true; | ||
} | ||
@@ -47,5 +165,29 @@ exports.xml_isLegalChar = xml_isLegalChar; | ||
function xml_isPubidChar(chars) { | ||
return dom_1.dom.regExp.PubidChar.value.test(chars); | ||
for (let i = 0; i < chars.length; i++) { | ||
const c1 = chars.charCodeAt(i); | ||
let n = c1; | ||
if (c1 >= 0xD800 && c1 <= 0xDBFF && i < chars.length - 1) { | ||
const c2 = chars.charCodeAt(i + 1); | ||
if (c2 >= 0xDC00 && c2 <= 0xDFFF) { | ||
n = (c1 - 0xD800) * 0x400 + c2 - 0xDC00 + 0x10000; | ||
} | ||
} | ||
// #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] | ||
if ((n >= 97 && n <= 122) || // [a-z] | ||
(n >= 65 && n <= 90) || // [A-Z] | ||
(n >= 48 && n <= 57) || // [0-9] | ||
n === 0x20 || n === 0xD || n === 0xA || | ||
n === 45 || n === 39 || n === 40 || n === 41 || n === 43 || n === 44 || | ||
n === 46 || n === 47 || n === 58 || n === 61 || n === 63 || n === 59 || | ||
n === 33 || n === 42 || n === 35 || n === 64 || n === 36 || n === 95 || | ||
n === 37) { | ||
continue; | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
exports.xml_isPubidChar = xml_isPubidChar; | ||
//# sourceMappingURL=XMLAlgorithm.js.map |
@@ -217,3 +217,3 @@ "use strict"; | ||
throw new DOMException_1.NotSupportedError(); | ||
if (data.includes(']]>')) | ||
if (data.indexOf(']]>') !== -1) | ||
throw new DOMException_1.InvalidCharacterError(); | ||
@@ -242,3 +242,3 @@ return algorithm_1.create_cdataSection(this, data); | ||
throw new DOMException_1.InvalidCharacterError(); | ||
if (data.includes("?>")) | ||
if (data.indexOf("?>") !== -1) | ||
throw new DOMException_1.InvalidCharacterError(); | ||
@@ -245,0 +245,0 @@ return algorithm_1.create_processingInstruction(this, target, data); |
import { DOMFeatures, Window, Node, Range } from "./interfaces"; | ||
import { CompareCache, FixedSizeSet, Lazy } from "@oozcitak/util"; | ||
declare type RegExpDict = { | ||
Name: Lazy<RegExp>; | ||
QName: Lazy<RegExp>; | ||
PubidChar: Lazy<RegExp>; | ||
InvalidChar_10: Lazy<RegExp>; | ||
InvalidChar_11: Lazy<RegExp>; | ||
}; | ||
import { CompareCache, FixedSizeSet } from "@oozcitak/util"; | ||
/** | ||
@@ -19,3 +12,2 @@ * Represents an object implementing DOM algorithms. | ||
private _rangeList; | ||
private _regExp; | ||
/** | ||
@@ -49,6 +41,2 @@ * Initializes a new instance of `DOM`. | ||
/** | ||
* Gets the global RegExp list. | ||
*/ | ||
get regExp(): RegExpDict; | ||
/** | ||
* Returns the instance of `DOM`. | ||
@@ -55,0 +43,0 @@ */ |
@@ -22,14 +22,2 @@ "use strict"; | ||
this._rangeList = new util_1.FixedSizeSet(); | ||
this._regExp = { | ||
/** Matches a valid XML name */ | ||
Name: new util_1.Lazy(() => /^([:A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])([\x2D\.0-:A-Z_a-z\xB7\xC0-\xD6\xD8-\xF6\xF8-\u037D\u037F-\u1FFF\u200C\u200D\u203F\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])*$/), | ||
/** Matches a valid XML qualified name */ | ||
QName: new util_1.Lazy(() => /^(([A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])([\x2D\.0-9A-Z_a-z\xB7\xC0-\xD6\xD8-\xF6\xF8-\u037D\u037F-\u1FFF\u200C\u200D\u203F\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])*:([A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])([\x2D\.0-9A-Z_a-z\xB7\xC0-\xD6\xD8-\xF6\xF8-\u037D\u037F-\u1FFF\u200C\u200D\u203F\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])*)|(([A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])([\x2D\.0-9A-Z_a-z\xB7\xC0-\xD6\xD8-\xF6\xF8-\u037D\u037F-\u1FFF\u200C\u200D\u203F\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])*)$/), | ||
/** Matches a valid XML public identifier string */ | ||
PubidChar: new util_1.Lazy(() => /^[\x20\x0D\x0AA-Z-a-z0-9-'()+,./:=?;!*#@$_%]*$/), | ||
/** Matches an invalid character according to XML 1.0 */ | ||
InvalidChar_10: new util_1.Lazy(() => /[\0-\x08\x0B\f\x0E-\x1F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/), | ||
/** Matches an invalid character according to XML 1.1 */ | ||
InvalidChar_11: new util_1.Lazy(() => /[\0\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/) | ||
}; | ||
} | ||
@@ -79,6 +67,2 @@ /** | ||
/** | ||
* Gets the global RegExp list. | ||
*/ | ||
get regExp() { return this._regExp; } | ||
/** | ||
* Returns the instance of `DOM`. | ||
@@ -85,0 +69,0 @@ */ |
@@ -93,2 +93,3 @@ "use strict"; | ||
else { | ||
// attribute name | ||
const attName = this.takeUntil('=', true); | ||
@@ -99,3 +100,5 @@ this.skipSpace(); | ||
} | ||
this.skipWhile('=', true); | ||
this.seek(1); | ||
// attribute value | ||
this.skipSpace(); | ||
const startQuote = this.c(); | ||
@@ -102,0 +105,0 @@ if (!XMLStringLexer.isQuote(startQuote)) { |
@@ -1,1 +0,1 @@ | ||
export { XMLSerializerImpl as XMLSerializer } from "./XMLSerializer"; | ||
export { XMLSerializer } from "./XMLSerializer"; |
@@ -5,3 +5,3 @@ "use strict"; | ||
var XMLSerializer_1 = require("./XMLSerializer"); | ||
exports.XMLSerializer = XMLSerializer_1.XMLSerializerImpl; | ||
exports.XMLSerializer = XMLSerializer_1.XMLSerializer; | ||
//# sourceMappingURL=index.js.map |
@@ -19,7 +19,4 @@ /** | ||
private _items; | ||
private _nullItems; | ||
/** | ||
* Initializes a new instance of `NamespacePrefixMap`. | ||
*/ | ||
constructor(items?: [[string, string | null]]); | ||
/** | ||
* Creates a copy of the map. | ||
@@ -26,0 +23,0 @@ */ |
@@ -20,10 +20,5 @@ "use strict"; | ||
class NamespacePrefixMap { | ||
/** | ||
* Initializes a new instance of `NamespacePrefixMap`. | ||
*/ | ||
constructor(items) { | ||
this._items = new Map(); | ||
if (items !== undefined) { | ||
items.forEach(item => this.set(item[0], item[1])); | ||
} | ||
constructor() { | ||
this._items = {}; | ||
this._nullItems = []; | ||
} | ||
@@ -41,3 +36,6 @@ /** | ||
const mapCopy = new NamespacePrefixMap(); | ||
this._items.forEach((list, key) => mapCopy._items.set(key, list.slice(0))); | ||
for (const key in this._items) { | ||
mapCopy._items[key] = this._items[key].slice(0); | ||
} | ||
mapCopy._nullItems = this._nullItems.slice(0); | ||
return mapCopy; | ||
@@ -57,3 +55,3 @@ } | ||
*/ | ||
const candidatesList = this._items.get(ns) || null; | ||
const candidatesList = ns === null ? this._nullItems : (this._items[ns] || null); | ||
if (candidatesList === null) { | ||
@@ -98,3 +96,3 @@ return null; | ||
*/ | ||
const candidatesList = this._items.get(ns) || null; | ||
const candidatesList = ns === null ? this._nullItems : (this._items[ns] || null); | ||
if (candidatesList === null) { | ||
@@ -107,3 +105,3 @@ return false; | ||
*/ | ||
return (candidatesList.includes(prefix)); | ||
return (candidatesList.indexOf(prefix) !== -1); | ||
} | ||
@@ -116,6 +114,7 @@ /** | ||
hasPrefix(prefix) { | ||
for (const [, candidatesList] of this._items) { | ||
if (candidatesList.includes(prefix)) { | ||
if (this._nullItems.indexOf(prefix) !== -1) | ||
return true; | ||
for (const key in this._items) { | ||
if (this._items[key].indexOf(prefix) !== -1) | ||
return true; | ||
} | ||
} | ||
@@ -136,3 +135,3 @@ return false; | ||
*/ | ||
const candidatesList = this._items.get(ns) || null; | ||
const candidatesList = ns === null ? this._nullItems : (this._items[ns] || null); | ||
/** | ||
@@ -149,4 +148,4 @@ * 2. If candidates list is null, then create a new list with prefix as the | ||
*/ | ||
if (candidatesList === null) { | ||
this._items.set(ns, [prefix]); | ||
if (ns !== null && candidatesList === null) { | ||
this._items[ns] = [prefix]; | ||
} | ||
@@ -153,0 +152,0 @@ else { |
import { Node } from "../dom/interfaces"; | ||
import { PreSerializedNode } from "./interfaces"; | ||
/** | ||
@@ -7,9 +6,31 @@ * Pre-serializes XML nodes. | ||
export declare class PreSerializer { | ||
private static _VoidElementNames; | ||
private _xmlVersion; | ||
private _docType; | ||
private _comment; | ||
private _text; | ||
private _instruction; | ||
private _cdata; | ||
private _openTagBegin; | ||
private _openTagEnd; | ||
private _closeTag; | ||
private _attribute; | ||
private _namespace; | ||
private _level; | ||
/** | ||
* Returns the current depth of the XML tree. | ||
*/ | ||
get level(): number; | ||
private _currentNode; | ||
/** | ||
* Returns the current XML node. | ||
*/ | ||
get currentNode(): Node; | ||
/** | ||
* Initializes a new instance of `PreSerializer`. | ||
* | ||
* @param xmlVersion - XML specification version | ||
* @param functions - serializer functions | ||
*/ | ||
constructor(xmlVersion: "1.0" | "1.1"); | ||
constructor(xmlVersion: "1.0" | "1.1", functions: SerializerFunctions); | ||
/** | ||
@@ -20,9 +41,6 @@ * Produces an XML serialization of the given node. The pre-serializer inserts | ||
* | ||
* A serializer should process each `PreSerializedNode` produced by this | ||
* function and use the information provided to serialize the node. | ||
* | ||
* @param node - node to serialize | ||
* @param requireWellFormed - whether to check conformance | ||
*/ | ||
serialize(node: Node, requireWellFormed: boolean): PreSerializedNode<Node>; | ||
serialize(node: Node, requireWellFormed: boolean): void; | ||
/** | ||
@@ -36,3 +54,2 @@ * Produces an XML serialization of a node. | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
@@ -48,3 +65,2 @@ private _serializeNode; | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
@@ -60,3 +76,2 @@ private _serializeElement; | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
@@ -68,7 +83,3 @@ private _serializeDocument; | ||
* @param node - node to serialize | ||
* @param namespace - context namespace | ||
* @param prefixMap - namespace prefix map | ||
* @param prefixIndex - generated namespace prefix index | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
@@ -80,5 +91,2 @@ private _serializeComment; | ||
* @param node - node to serialize | ||
* @param namespace - context namespace | ||
* @param prefixMap - namespace prefix map | ||
* @param prefixIndex - generated namespace prefix index | ||
* @param requireWellFormed - whether to check conformance | ||
@@ -96,3 +104,2 @@ * @param level - current depth of the XML tree | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
@@ -108,3 +115,2 @@ private _serializeDocumentFragment; | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
@@ -116,7 +122,3 @@ private _serializeDocumentType; | ||
* @param node - node to serialize | ||
* @param namespace - context namespace | ||
* @param prefixMap - namespace prefix map | ||
* @param prefixIndex - generated namespace prefix index | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
@@ -128,7 +130,3 @@ private _serializeProcessingInstruction; | ||
* @param node - node to serialize | ||
* @param namespace - context namespace | ||
* @param prefixMap - namespace prefix map | ||
* @param prefixIndex - generated namespace prefix index | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
@@ -166,1 +164,17 @@ private _serializeCData; | ||
} | ||
/** | ||
* Represents the serializer functions. | ||
*/ | ||
declare type SerializerFunctions = { | ||
docType: ((name: string, publicId: string, systemId: string) => void); | ||
comment: ((data: string) => void); | ||
text: ((data: string) => void); | ||
instruction: ((target: string, data: string) => void); | ||
cdata: ((data: string) => void); | ||
openTagBegin: ((name: string) => void); | ||
openTagEnd: ((selfClosing: boolean, voidElement: boolean) => void); | ||
closeTag: ((name: string) => void); | ||
attribute: ((name: string, value: string) => void); | ||
namespace: ((name: string, value: string) => void); | ||
}; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const interfaces_1 = require("../dom/interfaces"); | ||
const TupleSet_1 = require("./TupleSet"); | ||
const LocalNameSet_1 = require("./LocalNameSet"); | ||
const NamespacePrefixMap_1 = require("./NamespacePrefixMap"); | ||
@@ -17,7 +17,28 @@ const DOMException_1 = require("../dom/DOMException"); | ||
* @param xmlVersion - XML specification version | ||
* @param functions - serializer functions | ||
*/ | ||
constructor(xmlVersion) { | ||
constructor(xmlVersion, functions) { | ||
this._level = 0; | ||
this._currentNode = undefined; | ||
this._xmlVersion = xmlVersion; | ||
this._docType = functions.docType; | ||
this._comment = functions.comment; | ||
this._text = functions.text; | ||
this._instruction = functions.instruction; | ||
this._cdata = functions.cdata; | ||
this._openTagBegin = functions.openTagBegin; | ||
this._openTagEnd = functions.openTagEnd; | ||
this._closeTag = functions.closeTag; | ||
this._attribute = functions.attribute; | ||
this._namespace = functions.namespace; | ||
} | ||
/** | ||
* Returns the current depth of the XML tree. | ||
*/ | ||
get level() { return this._level; } | ||
/** | ||
* Returns the current XML node. | ||
*/ | ||
get currentNode() { return this._currentNode; } | ||
/** | ||
* Produces an XML serialization of the given node. The pre-serializer inserts | ||
@@ -27,5 +48,2 @@ * namespace declarations where necessary and produces qualified names for | ||
* | ||
* A serializer should process each `PreSerializedNode` produced by this | ||
* function and use the information provided to serialize the node. | ||
* | ||
* @param node - node to serialize | ||
@@ -52,3 +70,4 @@ * @param requireWellFormed - whether to check conformance | ||
const namespace = null; | ||
const prefixMap = new NamespacePrefixMap_1.NamespacePrefixMap([["xml", infra_1.namespace.XML]]); | ||
const prefixMap = new NamespacePrefixMap_1.NamespacePrefixMap(); | ||
prefixMap.set("xml", infra_1.namespace.XML); | ||
const prefixIndex = { value: 1 }; | ||
@@ -64,3 +83,5 @@ /** | ||
try { | ||
return this._serializeNode(node, namespace, prefixMap, prefixIndex, requireWellFormed); | ||
this._level = 0; | ||
this._currentNode = node; | ||
this._serializeNode(node, namespace, prefixMap, prefixIndex, requireWellFormed); | ||
} | ||
@@ -79,29 +100,32 @@ catch (_a) { | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
_serializeNode(node, namespace, prefixMap, prefixIndex, requireWellFormed, level = 0) { | ||
_serializeNode(node, namespace, prefixMap, prefixIndex, requireWellFormed) { | ||
this._currentNode = node; | ||
switch (node.nodeType) { | ||
case interfaces_1.NodeType.Element: | ||
return this._serializeElement(node, namespace, prefixMap, prefixIndex, requireWellFormed, level); | ||
this._serializeElement(node, namespace, prefixMap, prefixIndex, requireWellFormed); | ||
break; | ||
case interfaces_1.NodeType.Document: | ||
return this._serializeDocument(node, namespace, prefixMap, prefixIndex, requireWellFormed, level); | ||
this._serializeDocument(node, namespace, prefixMap, prefixIndex, requireWellFormed); | ||
break; | ||
case interfaces_1.NodeType.Comment: | ||
return this._serializeComment(node, namespace, prefixMap, prefixIndex, requireWellFormed, level); | ||
this._serializeComment(node, requireWellFormed); | ||
break; | ||
case interfaces_1.NodeType.Text: | ||
return this._serializeText(node, namespace, prefixMap, prefixIndex, requireWellFormed, level); | ||
this._serializeText(node, requireWellFormed); | ||
break; | ||
case interfaces_1.NodeType.DocumentFragment: | ||
return this._serializeDocumentFragment(node, namespace, prefixMap, prefixIndex, requireWellFormed, level); | ||
this._serializeDocumentFragment(node, namespace, prefixMap, prefixIndex, requireWellFormed); | ||
break; | ||
case interfaces_1.NodeType.DocumentType: | ||
return this._serializeDocumentType(node, namespace, prefixMap, prefixIndex, requireWellFormed, level); | ||
this._serializeDocumentType(node, requireWellFormed); | ||
break; | ||
case interfaces_1.NodeType.ProcessingInstruction: | ||
return this._serializeProcessingInstruction(node, namespace, prefixMap, prefixIndex, requireWellFormed, level); | ||
this._serializeProcessingInstruction(node, requireWellFormed); | ||
break; | ||
case interfaces_1.NodeType.CData: | ||
return this._serializeCData(node, namespace, prefixMap, prefixIndex, requireWellFormed, level); | ||
this._serializeCData(node, requireWellFormed); | ||
break; | ||
default: | ||
return { | ||
node: node, | ||
level: level, | ||
attributes: [], | ||
children: [] | ||
}; | ||
throw new Error(`Unknown node type: ${node.nodeType}`); | ||
} | ||
@@ -117,7 +141,4 @@ } | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
_serializeElement(node, namespace, prefixMap, prefixIndex, requireWellFormed, level) { | ||
const attributes = []; | ||
const children = []; | ||
_serializeElement(node, namespace, prefixMap, prefixIndex, requireWellFormed) { | ||
/** | ||
@@ -131,3 +152,3 @@ * From: https://w3c.github.io/DOM-Parsing/#xml-serializing-an-element-node | ||
*/ | ||
if (requireWellFormed && (node.localName.includes(":") || | ||
if (requireWellFormed && (node.localName.indexOf(":") !== -1 || | ||
!algorithm_1.xml_isName(node.localName))) { | ||
@@ -167,5 +188,6 @@ throw new Error("Node local name contains invalid characters (well-formed required)."); | ||
let qualifiedName = ''; | ||
let skipEndTag = false; | ||
let ignoreNamespaceDefinitionAttribute = false; | ||
let map = prefixMap.copy(); | ||
let localPrefixesMap = new Map(); | ||
let localPrefixesMap = {}; | ||
let localDefaultNamespace = this._recordNamespaceInformation(node, map, localPrefixesMap); | ||
@@ -190,3 +212,3 @@ let inheritedNS = namespace; | ||
if (ns === infra_1.namespace.XML) { | ||
qualifiedName = `xml:${node.localName}`; | ||
qualifiedName = 'xml:' + node.localName; | ||
} | ||
@@ -197,2 +219,3 @@ else { | ||
/** 11.4. Append the value of qualified name to markup. */ | ||
this._openTagBegin(qualifiedName); | ||
} | ||
@@ -257,6 +280,10 @@ else { | ||
*/ | ||
qualifiedName = `${candidatePrefix}:${node.localName}`; | ||
qualifiedName = candidatePrefix + ':' + node.localName; | ||
if (localDefaultNamespace !== null && localDefaultNamespace !== infra_1.namespace.XML) { | ||
inheritedNS = localDefaultNamespace || null; | ||
} | ||
/** | ||
* 12.4.3. Append the value of qualified name to markup. | ||
*/ | ||
this._openTagBegin(qualifiedName); | ||
/** 12.5. Otherwise, if prefix is not null, then: */ | ||
@@ -278,3 +305,3 @@ } | ||
*/ | ||
if (localPrefixesMap.has(prefix)) { | ||
if (prefix in localPrefixesMap) { | ||
prefix = this._generatePrefix(ns, map, prefixIndex); | ||
@@ -289,3 +316,4 @@ } | ||
map.set(prefix, ns); | ||
qualifiedName += `${prefix}:${node.localName}`; | ||
qualifiedName += prefix + ':' + node.localName; | ||
this._openTagBegin(qualifiedName); | ||
/** | ||
@@ -305,3 +333,3 @@ * 12.5.5. Append the following to markup, in the order listed: | ||
*/ | ||
attributes.push({ name: 'xmlns:' + prefix, value: ns || '' }); | ||
this._namespace('xmlns:' + prefix, ns || ''); | ||
/** | ||
@@ -338,4 +366,2 @@ * 12.5.5.7. If local default namespace is not null (there exists a | ||
* its children. | ||
* | ||
* 12.6.4. Append the value of qualified name to markup. | ||
*/ | ||
@@ -346,2 +372,6 @@ ignoreNamespaceDefinitionAttribute = true; | ||
/** | ||
* 12.6.4. Append the value of qualified name to markup. | ||
*/ | ||
this._openTagBegin(qualifiedName); | ||
/** | ||
* 12.6.5. Append the following to markup, in the order listed: | ||
@@ -359,3 +389,3 @@ * | ||
*/ | ||
attributes.push({ name: 'xmlns', value: ns || '' }); | ||
this._namespace('xmlns', ns || ''); | ||
/** | ||
@@ -371,2 +401,3 @@ * 12.7. Otherwise, the node has a local default namespace that matches | ||
inheritedNS = ns; | ||
this._openTagBegin(qualifiedName); | ||
} | ||
@@ -379,4 +410,3 @@ } | ||
*/ | ||
const eleAttributes = this._serializeAttributes(node, map, prefixIndex, localPrefixesMap, ignoreNamespaceDefinitionAttribute, requireWellFormed); | ||
attributes.push(...eleAttributes); | ||
this._serializeAttributes(node, map, prefixIndex, localPrefixesMap, ignoreNamespaceDefinitionAttribute, requireWellFormed); | ||
/** | ||
@@ -396,4 +426,23 @@ * 14. If ns is the HTML namespace, and the node's list of children is | ||
* 16. Append ">" (U+003E GREATER-THAN SIGN) to markup. | ||
*/ | ||
const isHTML = (ns === infra_1.namespace.HTML); | ||
if (isHTML && node._children.size === 0 && | ||
PreSerializer._VoidElementNames.has(node._localName)) { | ||
this._openTagEnd(true, true); | ||
skipEndTag = true; | ||
} | ||
else if (!isHTML && node._children.size === 0) { | ||
this._openTagEnd(true, false); | ||
skipEndTag = true; | ||
} | ||
else { | ||
this._openTagEnd(false, false); | ||
} | ||
/** | ||
* 17. If the value of skip end tag is true, then return the value of markup | ||
* and skip the remaining steps. The node is a leaf-node. | ||
*/ | ||
if (skipEndTag) | ||
return; | ||
/** | ||
* 18. If ns is the HTML namespace, and the node's localName matches the | ||
@@ -413,3 +462,12 @@ * string "template", then this is a template element. Append to markup the | ||
*/ | ||
node._children.forEach(childNode => children.push(this._serializeNode(childNode, inheritedNS, map, prefixIndex, requireWellFormed, level + 1))); | ||
if (isHTML && node._localName === "template") { | ||
// TODO: serialize template contents | ||
} | ||
else { | ||
node._children.forEach(childNode => { | ||
this._level++; | ||
this._serializeNode(childNode, inheritedNS, map, prefixIndex, requireWellFormed); | ||
this._level--; | ||
}); | ||
} | ||
/** | ||
@@ -422,9 +480,3 @@ * 20. Append the following to markup, in the order listed: | ||
*/ | ||
return { | ||
node: node, | ||
level: level, | ||
name: qualifiedName, | ||
attributes: attributes, | ||
children: children | ||
}; | ||
this._closeTag(qualifiedName); | ||
} | ||
@@ -439,5 +491,4 @@ /** | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
_serializeDocument(node, namespace, prefixMap, prefixIndex, requireWellFormed, level) { | ||
_serializeDocument(node, namespace, prefixMap, prefixIndex, requireWellFormed) { | ||
/** | ||
@@ -466,10 +517,3 @@ * If the require well-formed flag is set (its value is true), and this node | ||
*/ | ||
const children = []; | ||
node._children.forEach(childNode => children.push(this._serializeNode(childNode, namespace, prefixMap, prefixIndex, requireWellFormed, level))); | ||
return { | ||
node: node, | ||
level: level, | ||
attributes: [], | ||
children: children | ||
}; | ||
node._children.forEach(childNode => this._serializeNode(childNode, namespace, prefixMap, prefixIndex, requireWellFormed)); | ||
} | ||
@@ -480,9 +524,5 @@ /** | ||
* @param node - node to serialize | ||
* @param namespace - context namespace | ||
* @param prefixMap - namespace prefix map | ||
* @param prefixIndex - generated namespace prefix index | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
_serializeComment(node, namespace, prefixMap, prefixIndex, requireWellFormed, level) { | ||
_serializeComment(node, requireWellFormed) { | ||
/** | ||
@@ -496,3 +536,3 @@ * If the require well-formed flag is set (its value is true), and node's | ||
if (requireWellFormed && (!algorithm_1.xml_isLegalChar(node.data, this._xmlVersion) || | ||
node.data.includes("--") || node.data.endsWith("-"))) { | ||
node.data.indexOf("--") !== -1 || node.data.endsWith("-"))) { | ||
throw new Error("Comment data contains invalid characters (well-formed required)."); | ||
@@ -503,8 +543,3 @@ } | ||
*/ | ||
return { | ||
node: node, | ||
level: level, | ||
attributes: [], | ||
children: [] | ||
}; | ||
this._comment(node.data); | ||
} | ||
@@ -515,9 +550,6 @@ /** | ||
* @param node - node to serialize | ||
* @param namespace - context namespace | ||
* @param prefixMap - namespace prefix map | ||
* @param prefixIndex - generated namespace prefix index | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
_serializeText(node, namespace, prefixMap, prefixIndex, requireWellFormed, level) { | ||
_serializeText(node, requireWellFormed) { | ||
/** | ||
@@ -539,8 +571,3 @@ * 1. If the require well-formed flag is set (its value is true), and | ||
*/ | ||
return { | ||
node: node, | ||
level: level, | ||
attributes: [], | ||
children: [] | ||
}; | ||
this._text(node.data); | ||
} | ||
@@ -555,5 +582,4 @@ /** | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
_serializeDocumentFragment(node, namespace, prefixMap, prefixIndex, requireWellFormed, level) { | ||
_serializeDocumentFragment(node, namespace, prefixMap, prefixIndex, requireWellFormed) { | ||
/** | ||
@@ -566,10 +592,3 @@ * 1. Let markup the empty string. | ||
*/ | ||
const children = []; | ||
node._children.forEach(childNode => children.push(this._serializeNode(childNode, namespace, prefixMap, prefixIndex, requireWellFormed, level))); | ||
return { | ||
node: node, | ||
level: level, | ||
attributes: [], | ||
children: children | ||
}; | ||
node._children.forEach(childNode => this._serializeNode(childNode, namespace, prefixMap, prefixIndex, requireWellFormed)); | ||
} | ||
@@ -584,5 +603,4 @@ /** | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
_serializeDocumentType(node, namespace, prefixMap, prefixIndex, requireWellFormed, level) { | ||
_serializeDocumentType(node, requireWellFormed) { | ||
/** | ||
@@ -606,3 +624,3 @@ * 1. If the require well-formed flag is true and the node's publicId | ||
(!algorithm_1.xml_isLegalChar(node.systemId, this._xmlVersion) || | ||
(node.systemId.includes('"') && node.systemId.includes("'")))) { | ||
(node.systemId.indexOf('"') !== -1 && node.systemId.indexOf("'") !== -1))) { | ||
throw new Error("DocType system identifier contains invalid characters (well-formed required)."); | ||
@@ -638,8 +656,3 @@ } | ||
*/ | ||
return { | ||
node: node, | ||
level: level, | ||
attributes: [], | ||
children: [] | ||
}; | ||
this._docType(node.name, node.publicId, node.systemId); | ||
} | ||
@@ -650,9 +663,5 @@ /** | ||
* @param node - node to serialize | ||
* @param namespace - context namespace | ||
* @param prefixMap - namespace prefix map | ||
* @param prefixIndex - generated namespace prefix index | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
_serializeProcessingInstruction(node, namespace, prefixMap, prefixIndex, requireWellFormed, level) { | ||
_serializeProcessingInstruction(node, requireWellFormed) { | ||
/** | ||
@@ -664,3 +673,3 @@ * 1. If the require well-formed flag is set (its value is true), and node's | ||
*/ | ||
if (requireWellFormed && (node.target.includes(":") || (/^xml$/i).test(node.target))) { | ||
if (requireWellFormed && (node.target.indexOf(":") !== -1 || (/^xml$/i).test(node.target))) { | ||
throw new Error("Processing instruction target contains invalid characters (well-formed required)."); | ||
@@ -676,3 +685,3 @@ } | ||
if (requireWellFormed && (!algorithm_1.xml_isLegalChar(node.data, this._xmlVersion) || | ||
node.data.includes("?>"))) { | ||
node.data.indexOf("?>") !== -1)) { | ||
throw new Error("Processing instruction data contains invalid characters (well-formed required)."); | ||
@@ -689,8 +698,3 @@ } | ||
*/ | ||
return { | ||
node: node, | ||
level: level, | ||
attributes: [], | ||
children: [] | ||
}; | ||
this._instruction(node.target, node.data); | ||
} | ||
@@ -701,18 +705,9 @@ /** | ||
* @param node - node to serialize | ||
* @param namespace - context namespace | ||
* @param prefixMap - namespace prefix map | ||
* @param prefixIndex - generated namespace prefix index | ||
* @param requireWellFormed - whether to check conformance | ||
* @param level - current depth of the XML tree | ||
*/ | ||
_serializeCData(node, namespace, prefixMap, prefixIndex, requireWellFormed, level) { | ||
if (requireWellFormed && (node.data.includes("]]>"))) { | ||
_serializeCData(node, requireWellFormed) { | ||
if (requireWellFormed && (node.data.indexOf("]]>") !== -1)) { | ||
throw new Error("CDATA contains invalid characters (well-formed required)."); | ||
} | ||
return { | ||
node: node, | ||
level: level, | ||
attributes: [], | ||
children: [] | ||
}; | ||
this._cdata(node.data); | ||
} | ||
@@ -731,3 +726,2 @@ /** | ||
_serializeAttributes(node, map, prefixIndex, localPrefixesMap, ignoreNamespaceDefinitionAttribute, requireWellFormed) { | ||
const result = []; | ||
/** | ||
@@ -743,3 +737,3 @@ * 1. Let result be the empty string. | ||
*/ | ||
const localNameSet = new TupleSet_1.TupleSet(); | ||
const localNameSet = requireWellFormed ? new LocalNameSet_1.LocalNameSet() : undefined; | ||
/** | ||
@@ -749,4 +743,9 @@ * 3. Loop: For each attribute attr in element's attributes, in the order | ||
*/ | ||
for (let i = 0; i < node.attributes._attributeList.length; i++) { | ||
for (let i = 0; i < node._attributeList._attributeList.length; i++) { | ||
const attr = node.attributes._attributeList[i]; | ||
// Optimize common case | ||
if (!requireWellFormed && attr.namespaceURI === null) { | ||
this._attribute(attr.localName, attr.value); | ||
continue; | ||
} | ||
/** | ||
@@ -759,3 +758,3 @@ * 3.1. If the require well-formed flag is set (its value is true), and the | ||
*/ | ||
if (requireWellFormed && localNameSet.has([attr.namespaceURI, attr.localName])) { | ||
if (requireWellFormed && localNameSet && localNameSet.has(attr.namespaceURI, attr.localName)) { | ||
throw new Error("Element contains duplicate attributes (well-formed required)."); | ||
@@ -769,3 +768,4 @@ } | ||
*/ | ||
localNameSet.set([attr.namespaceURI, attr.localName]); | ||
if (requireWellFormed && localNameSet) | ||
localNameSet.set(attr.namespaceURI, attr.localName); | ||
let attributeNamespace = attr.namespaceURI; | ||
@@ -811,4 +811,4 @@ let candidatePrefix = null; | ||
(attr.prefix === null && ignoreNamespaceDefinitionAttribute) || | ||
(attr.prefix !== null && (!localPrefixesMap.has(attr.localName) || | ||
localPrefixesMap.get(attr.localName) !== attr.value) && | ||
(attr.prefix !== null && (!(attr.localName in localPrefixesMap) || | ||
localPrefixesMap[attr.localName] !== attr.value) && | ||
map.has(attr.localName, attr.value))) | ||
@@ -883,3 +883,3 @@ continue; | ||
*/ | ||
result.push({ name: 'xmlns:' + candidatePrefix, value: attributeNamespace }); | ||
this._namespace('xmlns:' + candidatePrefix, attributeNamespace); | ||
} | ||
@@ -904,3 +904,3 @@ } | ||
*/ | ||
if (requireWellFormed && (attr.localName.includes(":") || | ||
if (requireWellFormed && (attr.localName.indexOf(":") !== -1 || | ||
!algorithm_1.xml_isName(attr.localName) || | ||
@@ -919,3 +919,3 @@ (attr.localName === "xmlns" && attributeNamespace === null))) { | ||
attrName += attr.localName; | ||
result.push({ attr: attr, name: attrName, value: attr.value }); | ||
this._attribute(attrName, attr.value); | ||
} | ||
@@ -925,3 +925,2 @@ /** | ||
*/ | ||
return result; | ||
} | ||
@@ -1025,3 +1024,3 @@ /** | ||
*/ | ||
localPrefixesMap.set(prefixDefinition, namespaceDefinition || ''); | ||
localPrefixesMap[prefixDefinition] = namespaceDefinition || ''; | ||
} | ||
@@ -1060,2 +1059,5 @@ } | ||
exports.PreSerializer = PreSerializer; | ||
PreSerializer._VoidElementNames = new Set(['area', 'base', 'basefont', | ||
'bgsound', 'br', 'col', 'embed', 'frame', 'hr', 'img', 'input', 'keygen', | ||
'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']); | ||
//# sourceMappingURL=PreSerializer.js.map |
@@ -1,2 +0,1 @@ | ||
import { XMLSerializer } from "./interfaces"; | ||
import { Node } from "../dom/interfaces"; | ||
@@ -8,3 +7,3 @@ /** | ||
*/ | ||
export declare class XMLSerializerImpl implements XMLSerializer { | ||
export declare class XMLSerializer { | ||
private _xmlVersion; | ||
@@ -24,26 +23,2 @@ /** | ||
/** | ||
* Produces an XML serialization of `node`. | ||
* | ||
* @param preNode - node to serialize | ||
*/ | ||
private _serializeNode; | ||
/** | ||
* Produces an XML serialization of the given node's children. | ||
* | ||
* @param preNode - node to serialize | ||
*/ | ||
private _serializeChildNodes; | ||
/** | ||
* Produces an XML serialization of the given node's attributes. | ||
* | ||
* @param preNode - the node whose attributes to serialize | ||
*/ | ||
private _serializeAttributes; | ||
/** | ||
* Produces an XML serialization of an attribute. | ||
* | ||
* @param preAttr - attribute node to serialize | ||
*/ | ||
private _serializeAttribute; | ||
/** | ||
* Produces an XML serialization of an attribute value. | ||
@@ -55,49 +30,7 @@ * | ||
/** | ||
* Produces an XML serialization of an element node. | ||
* Produces an XML serialization of a text node data. | ||
* | ||
* @param preNode - element node to serialize | ||
* @param data - text node data to serialize | ||
*/ | ||
private _serializeElement; | ||
/** | ||
* Produces an XML serialization of a document node. | ||
* | ||
* @param preNode - document node to serialize | ||
*/ | ||
private _serializeDocument; | ||
/** | ||
* Produces an XML serialization of a comment node. | ||
* | ||
* @param preNode - comment node to serialize | ||
*/ | ||
private _serializeComment; | ||
/** | ||
* Produces an XML serialization of a text node. | ||
* | ||
* @param preNode - text node to serialize | ||
*/ | ||
private _serializeText; | ||
/** | ||
* Produces an XML serialization of a document fragment node. | ||
* | ||
* @param preNode - document fragment node to serialize | ||
*/ | ||
private _serializeDocumentFragment; | ||
/** | ||
* Produces an XML serialization of a document type node. | ||
* | ||
* @param preNode - document type node to serialize | ||
*/ | ||
private _serializeDocumentType; | ||
/** | ||
* Produces an XML serialization of a processing instruction node. | ||
* | ||
* @param preNode - processing instruction node to serialize | ||
*/ | ||
private _serializeProcessingInstruction; | ||
/** | ||
* Produces an XML serialization of a CDATA node. | ||
* | ||
* @param preNode - CDATA node to serialize | ||
*/ | ||
private _serializeCData; | ||
private _serializeTextData; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const interfaces_1 = require("../dom/interfaces"); | ||
const PreSerializer_1 = require("./PreSerializer"); | ||
@@ -10,3 +9,3 @@ /** | ||
*/ | ||
class XMLSerializerImpl { | ||
class XMLSerializer { | ||
/** | ||
@@ -26,61 +25,26 @@ * Initializes a new instance of `XMLSerializer`. | ||
serializeToString(node) { | ||
const pre = new PreSerializer_1.PreSerializer(this._xmlVersion); | ||
return this._serializeNode(pre.serialize(node, false)); | ||
} | ||
/** | ||
* Produces an XML serialization of `node`. | ||
* | ||
* @param preNode - node to serialize | ||
*/ | ||
_serializeNode(preNode) { | ||
switch (preNode.node.nodeType) { | ||
case interfaces_1.NodeType.Element: | ||
return this._serializeElement(preNode); | ||
case interfaces_1.NodeType.Document: | ||
return this._serializeDocument(preNode); | ||
case interfaces_1.NodeType.Comment: | ||
return this._serializeComment(preNode); | ||
case interfaces_1.NodeType.Text: | ||
return this._serializeText(preNode); | ||
case interfaces_1.NodeType.DocumentFragment: | ||
return this._serializeDocumentFragment(preNode); | ||
case interfaces_1.NodeType.DocumentType: | ||
return this._serializeDocumentType(preNode); | ||
case interfaces_1.NodeType.ProcessingInstruction: | ||
return this._serializeProcessingInstruction(preNode); | ||
case interfaces_1.NodeType.CData: | ||
return this._serializeCData(preNode); | ||
default: | ||
throw new Error("Invalid node type."); | ||
} | ||
} | ||
/** | ||
* Produces an XML serialization of the given node's children. | ||
* | ||
* @param preNode - node to serialize | ||
*/ | ||
_serializeChildNodes(preNode) { | ||
let markup = ''; | ||
preNode.children.forEach(child => markup += this._serializeNode(child)); | ||
let markup = ""; | ||
const pre = new PreSerializer_1.PreSerializer(this._xmlVersion, { | ||
openTagBegin: (name) => markup += "<" + name, | ||
openTagEnd: (selfClosing, voidElement) => markup += voidElement ? " />" : selfClosing ? "/>" : ">", | ||
closeTag: (name) => markup += "</" + name + ">", | ||
namespace: (name, value) => markup += " " + name + "=\"" + this._serializeAttributeValue(value) + "\"", | ||
attribute: (name, value) => markup += " " + name + "=\"" + this._serializeAttributeValue(value) + "\"", | ||
comment: (data) => markup += "<!--" + data + "-->", | ||
text: (data) => markup += this._serializeTextData(data), | ||
instruction: (target, data) => markup += "<?" + target + " " + data + "?>", | ||
cdata: (data) => markup += "<![CDATA[" + data + "]]>", | ||
docType: (name, publicId, systemId) => markup += publicId && systemId ? | ||
"<!DOCTYPE " + name + " PUBLIC \"" + publicId + "\" \"" + systemId + "\">" | ||
: publicId ? | ||
"<!DOCTYPE " + name + " PUBLIC \"" + publicId + "\">" | ||
: systemId ? | ||
"<!DOCTYPE " + name + " SYSTEM \"" + systemId + "\">" | ||
: | ||
"<!DOCTYPE " + name + ">" | ||
}); | ||
pre.serialize(node, false); | ||
return markup; | ||
} | ||
/** | ||
* Produces an XML serialization of the given node's attributes. | ||
* | ||
* @param preNode - the node whose attributes to serialize | ||
*/ | ||
_serializeAttributes(preNode) { | ||
let markup = ''; | ||
preNode.attributes.forEach(preAttr => markup += ` ${this._serializeAttribute(preAttr)}`); | ||
return markup; | ||
} | ||
/** | ||
* Produces an XML serialization of an attribute. | ||
* | ||
* @param preAttr - attribute node to serialize | ||
*/ | ||
_serializeAttribute(preAttr) { | ||
return `${preAttr.name}="${this._serializeAttributeValue(preAttr.value)}"`; | ||
} | ||
/** | ||
* Produces an XML serialization of an attribute value. | ||
@@ -99,91 +63,13 @@ * | ||
/** | ||
* Produces an XML serialization of an element node. | ||
* Produces an XML serialization of a text node data. | ||
* | ||
* @param preNode - element node to serialize | ||
* @param data - text node data to serialize | ||
*/ | ||
_serializeElement(preNode) { | ||
let markup = `<${preNode.name}`; | ||
markup += this._serializeAttributes(preNode); | ||
if (preNode.children.length === 0) { | ||
markup += "/>"; | ||
return markup; | ||
} | ||
else { | ||
markup += ">"; | ||
markup += this._serializeChildNodes(preNode); | ||
markup += `</${preNode.name}>`; | ||
return markup; | ||
} | ||
} | ||
/** | ||
* Produces an XML serialization of a document node. | ||
* | ||
* @param preNode - document node to serialize | ||
*/ | ||
_serializeDocument(preNode) { | ||
return this._serializeChildNodes(preNode); | ||
} | ||
/** | ||
* Produces an XML serialization of a comment node. | ||
* | ||
* @param preNode - comment node to serialize | ||
*/ | ||
_serializeComment(preNode) { | ||
return `<!--${preNode.node.data}-->`; | ||
} | ||
/** | ||
* Produces an XML serialization of a text node. | ||
* | ||
* @param preNode - text node to serialize | ||
*/ | ||
_serializeText(preNode) { | ||
return preNode.node.data.replace("&", "&") | ||
_serializeTextData(data) { | ||
return data.replace("&", "&") | ||
.replace("<", "<") | ||
.replace(">", ">"); | ||
} | ||
/** | ||
* Produces an XML serialization of a document fragment node. | ||
* | ||
* @param preNode - document fragment node to serialize | ||
*/ | ||
_serializeDocumentFragment(preNode) { | ||
return this._serializeChildNodes(preNode); | ||
} | ||
/** | ||
* Produces an XML serialization of a document type node. | ||
* | ||
* @param preNode - document type node to serialize | ||
*/ | ||
_serializeDocumentType(preNode) { | ||
if (preNode.node.publicId && preNode.node.systemId) { | ||
return `<!DOCTYPE ${preNode.node.name} PUBLIC "${preNode.node.publicId}" "${preNode.node.systemId}">`; | ||
} | ||
else if (preNode.node.publicId) { | ||
return `<!DOCTYPE ${preNode.node.name} PUBLIC "${preNode.node.publicId}">`; | ||
} | ||
else if (preNode.node.systemId) { | ||
return `<!DOCTYPE ${preNode.node.name} SYSTEM "${preNode.node.systemId}">`; | ||
} | ||
else { | ||
return `<!DOCTYPE ${preNode.node.name}>`; | ||
} | ||
} | ||
/** | ||
* Produces an XML serialization of a processing instruction node. | ||
* | ||
* @param preNode - processing instruction node to serialize | ||
*/ | ||
_serializeProcessingInstruction(preNode) { | ||
return `<?${preNode.node.target} ${preNode.node.data}?>`; | ||
} | ||
/** | ||
* Produces an XML serialization of a CDATA node. | ||
* | ||
* @param preNode - CDATA node to serialize | ||
*/ | ||
_serializeCData(preNode) { | ||
return `<![CDATA[${preNode.node.data}]]>`; | ||
} | ||
} | ||
exports.XMLSerializerImpl = XMLSerializerImpl; | ||
exports.XMLSerializer = XMLSerializer; | ||
//# sourceMappingURL=XMLSerializer.js.map |
{ | ||
"name": "@oozcitak/dom", | ||
"version": "1.2.1", | ||
"version": "1.3.0", | ||
"keywords": [ | ||
@@ -68,4 +68,5 @@ "dom", | ||
"prof-parse": "npm run compile && rm -f isolate-*-v8.log && node --prof ./perf/prof-parse.js && find . -name isolate-*-v8.log -exec mv {} isolate-v8.log ; && node --prof-process isolate-v8.log > isolate-parse.log && rm isolate-v8.log", | ||
"prof-serialize": "npm run compile && rm -f isolate-*-v8.log && node --prof ./perf/prof-serialize.js && find . -name isolate-*-v8.log -exec mv {} isolate-v8.log ; && node --prof-process isolate-v8.log > isolate-serialize.log && rm isolate-v8.log", | ||
"publish-public": "npm run test && npm publish --access public" | ||
} | ||
} |
@@ -27,5 +27,5 @@ # DOM | ||
const dom = new DOMImplementation(); | ||
const doc = dom.implementation.createDocument('ns', 'root'); | ||
const doc = dom.createDocument('ns', 'root'); | ||
``` | ||
The module also exports `DOMParser` and `XMLSerializer` classes as in the browser. | ||
The module also exports `DOMParser` and `XMLSerializer` classes as in the browser. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
31
1066236
261
21195