projen
Version:
CDK for software projects
543 lines • 21.2 kB
JavaScript
"use strict";
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
var DOMImpl_1 = require("../dom/DOMImpl");
var util_1 = require("../util");
var infra_1 = require("@oozcitak/infra");
var CreateAlgorithm_1 = require("./CreateAlgorithm");
var OrderedSetAlgorithm_1 = require("./OrderedSetAlgorithm");
var DOMAlgorithm_1 = require("./DOMAlgorithm");
var MutationAlgorithm_1 = require("./MutationAlgorithm");
var ElementAlgorithm_1 = require("./ElementAlgorithm");
/**
* Replaces the contents of the given node with a single text node.
*
* @param string - node contents
* @param parent - a node
*/
function node_stringReplaceAll(str, parent) {
/**
* 1. Let node be null.
* 2. If string is not the empty string, then set node to a new Text node
* whose data is string and node document is parent’s node document.
* 3. Replace all with node within parent.
*/
var node = null;
if (str !== '') {
node = CreateAlgorithm_1.create_text(parent._nodeDocument, str);
}
MutationAlgorithm_1.mutation_replaceAll(node, parent);
}
exports.node_stringReplaceAll = node_stringReplaceAll;
/**
* Clones a node.
*
* @param node - a node to clone
* @param document - the document to own the cloned node
* @param cloneChildrenFlag - whether to clone node's children
*/
function node_clone(node, document, cloneChildrenFlag) {
var e_1, _a, e_2, _b;
if (document === void 0) { document = null; }
if (cloneChildrenFlag === void 0) { cloneChildrenFlag = false; }
/**
* 1. If document is not given, let document be node’s node document.
*/
if (document === null)
document = node._nodeDocument;
var copy;
if (util_1.Guard.isElementNode(node)) {
/**
* 2. If node is an element, then:
* 2.1. Let copy be the result of creating an element, given document,
* node’s local name, node’s namespace, node’s namespace prefix,
* and node’s is value, with the synchronous custom elements flag unset.
* 2.2. For each attribute in node’s attribute list:
* 2.2.1. Let copyAttribute be a clone of attribute.
* 2.2.2. Append copyAttribute to copy.
*/
copy = ElementAlgorithm_1.element_createAnElement(document, node._localName, node._namespace, node._namespacePrefix, node._is, false);
try {
for (var _c = __values(node._attributeList), _d = _c.next(); !_d.done; _d = _c.next()) {
var attribute = _d.value;
var copyAttribute = node_clone(attribute, document);
ElementAlgorithm_1.element_append(copyAttribute, copy);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_1) throw e_1.error; }
}
}
else {
/**
* 3. Otherwise, let copy be a node that implements the same interfaces as
* node, and fulfills these additional requirements, switching on node:
* - Document
* Set copy’s encoding, content type, URL, origin, type, and mode, to those
* of node.
* - DocumentType
* Set copy’s name, public ID, and system ID, to those of node.
* - Attr
* Set copy’s namespace, namespace prefix, local name, and value, to
* those of node.
* - Text
* - Comment
* Set copy’s data, to that of node.
* - ProcessingInstruction
* Set copy’s target and data to those of node.
* - Any other node
*/
if (util_1.Guard.isDocumentNode(node)) {
var doc = CreateAlgorithm_1.create_document();
doc._encoding = node._encoding;
doc._contentType = node._contentType;
doc._URL = node._URL;
doc._origin = node._origin;
doc._type = node._type;
doc._mode = node._mode;
copy = doc;
}
else if (util_1.Guard.isDocumentTypeNode(node)) {
var doctype = CreateAlgorithm_1.create_documentType(document, node._name, node._publicId, node._systemId);
copy = doctype;
}
else if (util_1.Guard.isAttrNode(node)) {
var attr = CreateAlgorithm_1.create_attr(document, node.localName);
attr._namespace = node._namespace;
attr._namespacePrefix = node._namespacePrefix;
attr._value = node._value;
copy = attr;
}
else if (util_1.Guard.isExclusiveTextNode(node)) {
copy = CreateAlgorithm_1.create_text(document, node._data);
}
else if (util_1.Guard.isCDATASectionNode(node)) {
copy = CreateAlgorithm_1.create_cdataSection(document, node._data);
}
else if (util_1.Guard.isCommentNode(node)) {
copy = CreateAlgorithm_1.create_comment(document, node._data);
}
else if (util_1.Guard.isProcessingInstructionNode(node)) {
copy = CreateAlgorithm_1.create_processingInstruction(document, node._target, node._data);
}
else if (util_1.Guard.isDocumentFragmentNode(node)) {
copy = CreateAlgorithm_1.create_documentFragment(document);
}
else {
copy = Object.create(node);
}
}
/**
* 4. Set copy’s node document and document to copy, if copy is a document,
* and set copy’s node document to document otherwise.
*/
if (util_1.Guard.isDocumentNode(copy)) {
copy._nodeDocument = copy;
document = copy;
}
else {
copy._nodeDocument = document;
}
/**
* 5. Run any cloning steps defined for node in other applicable
* specifications and pass copy, node, document and the clone children flag
* if set, as parameters.
*/
if (DOMImpl_1.dom.features.steps) {
DOMAlgorithm_1.dom_runCloningSteps(copy, node, document, cloneChildrenFlag);
}
/**
* 6. If the clone children flag is set, clone all the children of node and
* append them to copy, with document as specified and the clone children
* flag being set.
*/
if (cloneChildrenFlag) {
try {
for (var _e = __values(node._children), _f = _e.next(); !_f.done; _f = _e.next()) {
var child = _f.value;
var childCopy = node_clone(child, document, true);
MutationAlgorithm_1.mutation_append(childCopy, copy);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
}
finally { if (e_2) throw e_2.error; }
}
}
/**
* 7. Return copy.
*/
return copy;
}
exports.node_clone = node_clone;
/**
* Determines if two nodes can be considered equal.
*
* @param a - node to compare
* @param b - node to compare
*/
function node_equals(a, b) {
var e_3, _a, e_4, _b;
/**
* 1. A and B’s nodeType attribute value is identical.
*/
if (a._nodeType !== b._nodeType)
return false;
/**
* 2. The following are also equal, depending on A:
* - DocumentType
* Its name, public ID, and system ID.
* - Element
* Its namespace, namespace prefix, local name, and its attribute list’s size.
* - Attr
* Its namespace, local name, and value.
* - ProcessingInstruction
* Its target and data.
* - Text
* - Comment
* Its data.
*/
if (util_1.Guard.isDocumentTypeNode(a) && util_1.Guard.isDocumentTypeNode(b)) {
if (a._name !== b._name || a._publicId !== b._publicId ||
a._systemId !== b._systemId)
return false;
}
else if (util_1.Guard.isElementNode(a) && util_1.Guard.isElementNode(b)) {
if (a._namespace !== b._namespace || a._namespacePrefix !== b._namespacePrefix ||
a._localName !== b._localName ||
a._attributeList.length !== b._attributeList.length)
return false;
}
else if (util_1.Guard.isAttrNode(a) && util_1.Guard.isAttrNode(b)) {
if (a._namespace !== b._namespace || a._localName !== b._localName ||
a._value !== b._value)
return false;
}
else if (util_1.Guard.isProcessingInstructionNode(a) && util_1.Guard.isProcessingInstructionNode(b)) {
if (a._target !== b._target || a._data !== b._data)
return false;
}
else if (util_1.Guard.isCharacterDataNode(a) && util_1.Guard.isCharacterDataNode(b)) {
if (a._data !== b._data)
return false;
}
/**
* 3. If A is an element, each attribute in its attribute list has an attribute
* that equals an attribute in B’s attribute list.
*/
if (util_1.Guard.isElementNode(a) && util_1.Guard.isElementNode(b)) {
var attrMap = {};
try {
for (var _c = __values(a._attributeList), _d = _c.next(); !_d.done; _d = _c.next()) {
var attrA = _d.value;
attrMap[attrA._localName] = attrA;
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_3) throw e_3.error; }
}
try {
for (var _e = __values(b._attributeList), _f = _e.next(); !_f.done; _f = _e.next()) {
var attrB = _f.value;
var attrA = attrMap[attrB._localName];
if (!attrA)
return false;
if (!node_equals(attrA, attrB))
return false;
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
}
finally { if (e_4) throw e_4.error; }
}
}
/**
* 4. A and B have the same number of children.
* 5. Each child of A equals the child of B at the identical index.
*/
if (a._children.size !== b._children.size)
return false;
var itA = a._children[Symbol.iterator]();
var itB = b._children[Symbol.iterator]();
var resultA = itA.next();
var resultB = itB.next();
while (!resultA.done && !resultB.done) {
var child1 = resultA.value;
var child2 = resultB.value;
if (!node_equals(child1, child2))
return false;
resultA = itA.next();
resultB = itB.next();
}
return true;
}
exports.node_equals = node_equals;
/**
* Returns a collection of elements with the given qualified name which are
* descendants of the given root node.
* See: https://dom.spec.whatwg.org/#concept-getelementsbytagname
*
* @param qualifiedName - qualified name
* @param root - root node
*/
function node_listOfElementsWithQualifiedName(qualifiedName, root) {
/**
* 1. If qualifiedName is "*" (U+002A), return a HTMLCollection rooted at
* root, whose filter matches only descendant elements.
* 2. Otherwise, if root’s node document is an HTML document, return a
* HTMLCollection rooted at root, whose filter matches the following
* descendant elements:
* 2.1. Whose namespace is the HTML namespace and whose qualified name is
* qualifiedName, in ASCII lowercase.
* 2.2. Whose namespace is not the HTML namespace and whose qualified name
* is qualifiedName.
* 3. Otherwise, return a HTMLCollection rooted at root, whose filter
* matches descendant elements whose qualified name is qualifiedName.
*/
if (qualifiedName === "*") {
return CreateAlgorithm_1.create_htmlCollection(root);
}
else if (root._nodeDocument._type === "html") {
return CreateAlgorithm_1.create_htmlCollection(root, function (ele) {
if (ele._namespace === infra_1.namespace.HTML &&
ele._qualifiedName === qualifiedName.toLowerCase()) {
return true;
}
else if (ele._namespace !== infra_1.namespace.HTML &&
ele._qualifiedName === qualifiedName) {
return true;
}
else {
return false;
}
});
}
else {
return CreateAlgorithm_1.create_htmlCollection(root, function (ele) {
return (ele._qualifiedName === qualifiedName);
});
}
}
exports.node_listOfElementsWithQualifiedName = node_listOfElementsWithQualifiedName;
/**
* Returns a collection of elements with the given namespace which are
* descendants of the given root node.
* See: https://dom.spec.whatwg.org/#concept-getelementsbytagnamens
*
* @param namespace - element namespace
* @param localName - local name
* @param root - root node
*/
function node_listOfElementsWithNamespace(namespace, localName, root) {
/**
* 1. If namespace is the empty string, set it to null.
* 2. If both namespace and localName are "*" (U+002A), return a
* HTMLCollection rooted at root, whose filter matches descendant elements.
* 3. Otherwise, if namespace is "*" (U+002A), return a HTMLCollection
* rooted at root, whose filter matches descendant elements whose local
* name is localName.
* 4. Otherwise, if localName is "*" (U+002A), return a HTMLCollection
* rooted at root, whose filter matches descendant elements whose
* namespace is namespace.
* 5. Otherwise, return a HTMLCollection rooted at root, whose filter
* matches descendant elements whose namespace is namespace and local
* name is localName.
*/
if (namespace === '')
namespace = null;
if (namespace === "*" && localName === "*") {
return CreateAlgorithm_1.create_htmlCollection(root);
}
else if (namespace === "*") {
return CreateAlgorithm_1.create_htmlCollection(root, function (ele) {
return (ele._localName === localName);
});
}
else if (localName === "*") {
return CreateAlgorithm_1.create_htmlCollection(root, function (ele) {
return (ele._namespace === namespace);
});
}
else {
return CreateAlgorithm_1.create_htmlCollection(root, function (ele) {
return (ele._localName === localName && ele._namespace === namespace);
});
}
}
exports.node_listOfElementsWithNamespace = node_listOfElementsWithNamespace;
/**
* Returns a collection of elements with the given class names which are
* descendants of the given root node.
* See: https://dom.spec.whatwg.org/#concept-getelementsbyclassname
*
* @param namespace - element namespace
* @param localName - local name
* @param root - root node
*/
function node_listOfElementsWithClassNames(classNames, root) {
/**
* 1. Let classes be the result of running the ordered set parser
* on classNames.
* 2. If classes is the empty set, return an empty HTMLCollection.
* 3. Return a HTMLCollection rooted at root, whose filter matches
* descendant elements that have all their classes in classes.
* The comparisons for the classes must be done in an ASCII case-insensitive
* manner if root’s node document’s mode is "quirks", and in a
* case-sensitive manner otherwise.
*/
var classes = OrderedSetAlgorithm_1.orderedSet_parse(classNames);
if (classes.size === 0) {
return CreateAlgorithm_1.create_htmlCollection(root, function () { return false; });
}
var caseSensitive = (root._nodeDocument._mode !== "quirks");
return CreateAlgorithm_1.create_htmlCollection(root, function (ele) {
var eleClasses = ele.classList;
return OrderedSetAlgorithm_1.orderedSet_contains(eleClasses._tokenSet, classes, caseSensitive);
});
}
exports.node_listOfElementsWithClassNames = node_listOfElementsWithClassNames;
/**
* Searches for a namespace prefix associated with the given namespace
* starting from the given element through its ancestors.
*
* @param element - an element node to start searching at
* @param namespace - namespace to search for
*/
function node_locateANamespacePrefix(element, namespace) {
/**
* 1. If element’s namespace is namespace and its namespace prefix is not
* null, then return its namespace prefix.
*/
if (element._namespace === namespace && element._namespacePrefix !== null) {
return element._namespacePrefix;
}
/**
* 2. If element has an attribute whose namespace prefix is "xmlns" and
* value is namespace, then return element’s first such attribute’s
* local name.
*/
for (var i = 0; i < element._attributeList.length; i++) {
var attr = element._attributeList[i];
if (attr._namespacePrefix === "xmlns" && attr._value === namespace) {
return attr._localName;
}
}
/**
* 3. If element’s parent element is not null, then return the result of
* running locate a namespace prefix on that element using namespace.
*/
if (element._parent && util_1.Guard.isElementNode(element._parent)) {
return node_locateANamespacePrefix(element._parent, namespace);
}
/**
* 4. Return null.
*/
return null;
}
exports.node_locateANamespacePrefix = node_locateANamespacePrefix;
/**
* Searches for a namespace associated with the given namespace prefix
* starting from the given node through its ancestors.
*
* @param node - a node to start searching at
* @param prefix - namespace prefix to search for
*/
function node_locateANamespace(node, prefix) {
if (util_1.Guard.isElementNode(node)) {
/**
* 1. If its namespace is not null and its namespace prefix is prefix,
* then return namespace.
*/
if (node._namespace !== null && node._namespacePrefix === prefix) {
return node._namespace;
}
/**
* 2. If it has an attribute whose namespace is the XMLNS namespace,
* namespace prefix is "xmlns", and local name is prefix, or if prefix
* is null and it has an attribute whose namespace is the XMLNS namespace,
* namespace prefix is null, and local name is "xmlns", then return its
* value if it is not the empty string, and null otherwise.
*/
for (var i = 0; i < node._attributeList.length; i++) {
var attr = node._attributeList[i];
if (attr._namespace === infra_1.namespace.XMLNS &&
attr._namespacePrefix === "xmlns" &&
attr._localName === prefix) {
return attr._value || null;
}
if (prefix === null && attr._namespace === infra_1.namespace.XMLNS &&
attr._namespacePrefix === null && attr._localName === "xmlns") {
return attr._value || null;
}
}
/**
* 3. If its parent element is null, then return null.
*/
if (node.parentElement === null)
return null;
/**
* 4. Return the result of running locate a namespace on its parent
* element using prefix.
*/
return node_locateANamespace(node.parentElement, prefix);
}
else if (util_1.Guard.isDocumentNode(node)) {
/**
* 1. If its document element is null, then return null.
* 2. Return the result of running locate a namespace on its document
* element using prefix.
*/
if (node.documentElement === null)
return null;
return node_locateANamespace(node.documentElement, prefix);
}
else if (util_1.Guard.isDocumentTypeNode(node) || util_1.Guard.isDocumentFragmentNode(node)) {
return null;
}
else if (util_1.Guard.isAttrNode(node)) {
/**
* 1. If its element is null, then return null.
* 2. Return the result of running locate a namespace on its element
* using prefix.
*/
if (node._element === null)
return null;
return node_locateANamespace(node._element, prefix);
}
else {
/**
* 1. If its parent element is null, then return null.
* 2. Return the result of running locate a namespace on its parent
* element using prefix.
*/
if (!node._parent || !util_1.Guard.isElementNode(node._parent))
return null;
return node_locateANamespace(node._parent, prefix);
}
}
exports.node_locateANamespace = node_locateANamespace;
//# sourceMappingURL=NodeAlgorithm.js.map