UNPKG

projen

Version:

CDK for software projects

853 lines 28.2 kB
"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 util_1 = require("../util"); var interfaces_1 = require("../dom/interfaces"); /** * Gets the next descendant of the given node of the tree rooted at `root` * in depth-first pre-order. * * @param root - root node of the tree * @param node - a node * @param shadow - whether to visit shadow tree nodes */ function _getNextDescendantNode(root, node, shadow) { if (shadow === void 0) { shadow = false; } // traverse shadow tree if (shadow && util_1.Guard.isElementNode(node) && util_1.Guard.isShadowRoot(node.shadowRoot)) { if (node.shadowRoot._firstChild) return node.shadowRoot._firstChild; } // traverse child nodes if (node._firstChild) return node._firstChild; if (node === root) return null; // traverse siblings if (node._nextSibling) return node._nextSibling; // traverse parent's next sibling var parent = node._parent; while (parent && parent !== root) { if (parent._nextSibling) return parent._nextSibling; parent = parent._parent; } return null; } function _emptyIterator() { var _a; return _a = {}, _a[Symbol.iterator] = function () { return { next: function () { return { done: true, value: null }; } }; }, _a; } /** * Returns the first descendant node of the tree rooted at `node` in * depth-first pre-order. * * @param node - root node of the tree * @param self - whether to include `node` in traversal * @param shadow - whether to visit shadow tree nodes * @param filter - a function to filter nodes */ function tree_getFirstDescendantNode(node, self, shadow, filter) { if (self === void 0) { self = false; } if (shadow === void 0) { shadow = false; } var firstNode = (self ? node : _getNextDescendantNode(node, node, shadow)); while (firstNode && filter && !filter(firstNode)) { firstNode = _getNextDescendantNode(node, firstNode, shadow); } return firstNode; } exports.tree_getFirstDescendantNode = tree_getFirstDescendantNode; /** * Returns the next descendant node of the tree rooted at `node` in * depth-first pre-order. * * @param node - root node of the tree * @param currentNode - current descendant node * @param self - whether to include `node` in traversal * @param shadow - whether to visit shadow tree nodes * @param filter - a function to filter nodes */ function tree_getNextDescendantNode(node, currentNode, self, shadow, filter) { if (self === void 0) { self = false; } if (shadow === void 0) { shadow = false; } var nextNode = _getNextDescendantNode(node, currentNode, shadow); while (nextNode && filter && !filter(nextNode)) { nextNode = _getNextDescendantNode(node, nextNode, shadow); } return nextNode; } exports.tree_getNextDescendantNode = tree_getNextDescendantNode; /** * Traverses through all descendant nodes of the tree rooted at * `node` in depth-first pre-order. * * @param node - root node of the tree * @param self - whether to include `node` in traversal * @param shadow - whether to visit shadow tree nodes * @param filter - a function to filter nodes */ function tree_getDescendantNodes(node, self, shadow, filter) { var _a; if (self === void 0) { self = false; } if (shadow === void 0) { shadow = false; } if (!self && node._children.size === 0) { return _emptyIterator(); } return _a = {}, _a[Symbol.iterator] = function () { var currentNode = (self ? node : _getNextDescendantNode(node, node, shadow)); return { next: function () { while (currentNode && filter && !filter(currentNode)) { currentNode = _getNextDescendantNode(node, currentNode, shadow); } if (currentNode === null) { return { done: true, value: null }; } else { var result = { done: false, value: currentNode }; currentNode = _getNextDescendantNode(node, currentNode, shadow); return result; } } }; }, _a; } exports.tree_getDescendantNodes = tree_getDescendantNodes; /** * Traverses through all descendant element nodes of the tree rooted at * `node` in depth-first preorder. * * @param node - root node of the tree * @param self - whether to include `node` in traversal * @param shadow - whether to visit shadow tree nodes * @param filter - a function to filter nodes */ function tree_getDescendantElements(node, self, shadow, filter) { var _a; if (self === void 0) { self = false; } if (shadow === void 0) { shadow = false; } if (!self && node._children.size === 0) { return _emptyIterator(); } return _a = {}, _a[Symbol.iterator] = function () { var it = tree_getDescendantNodes(node, self, shadow, function (e) { return util_1.Guard.isElementNode(e); })[Symbol.iterator](); var currentNode = it.next().value; return { next: function () { while (currentNode && filter && !filter(currentNode)) { currentNode = it.next().value; } if (currentNode === null) { return { done: true, value: null }; } else { var result = { done: false, value: currentNode }; currentNode = it.next().value; return result; } } }; }, _a; } exports.tree_getDescendantElements = tree_getDescendantElements; /** * Traverses through all sibling nodes of `node`. * * @param node - root node of the tree * @param self - whether to include `node` in traversal * @param filter - a function to filter nodes */ function tree_getSiblingNodes(node, self, filter) { var _a; if (self === void 0) { self = false; } if (!node._parent || node._parent._children.size === 0) { return _emptyIterator(); } return _a = {}, _a[Symbol.iterator] = function () { var currentNode = node._parent ? node._parent._firstChild : null; return { next: function () { while (currentNode && (filter && !filter(currentNode) || (!self && currentNode === node))) { currentNode = currentNode._nextSibling; } if (currentNode === null) { return { done: true, value: null }; } else { var result = { done: false, value: currentNode }; currentNode = currentNode._nextSibling; return result; } } }; }, _a; } exports.tree_getSiblingNodes = tree_getSiblingNodes; /** * Gets the first ancestor of `node` in reverse tree order. * * @param node - root node of the tree * @param self - whether to include `node` in traversal * @param filter - a function to filter nodes */ function tree_getFirstAncestorNode(node, self, filter) { if (self === void 0) { self = false; } var firstNode = self ? node : node._parent; while (firstNode && filter && !filter(firstNode)) { firstNode = firstNode._parent; } return firstNode; } exports.tree_getFirstAncestorNode = tree_getFirstAncestorNode; /** * Gets the first ancestor of `node` in reverse tree order. * * @param node - root node of the tree * @param self - whether to include `node` in traversal * @param filter - a function to filter nodes */ function tree_getNextAncestorNode(node, currentNode, self, filter) { if (self === void 0) { self = false; } var nextNode = currentNode._parent; while (nextNode && filter && !filter(nextNode)) { nextNode = nextNode._parent; } return nextNode; } exports.tree_getNextAncestorNode = tree_getNextAncestorNode; /** * Traverses through all ancestor nodes `node` in reverse tree order. * * @param node - root node of the tree * @param self - whether to include `node` in traversal * @param filter - a function to filter nodes */ function tree_getAncestorNodes(node, self, filter) { var _a; if (self === void 0) { self = false; } if (!self && !node._parent) { return _emptyIterator(); } return _a = {}, _a[Symbol.iterator] = function () { var currentNode = tree_getFirstAncestorNode(node, self, filter); return { next: function () { if (currentNode === null) { return { done: true, value: null }; } else { var result = { done: false, value: currentNode }; currentNode = tree_getNextAncestorNode(node, currentNode, self, filter); return result; } } }; }, _a; } exports.tree_getAncestorNodes = tree_getAncestorNodes; /** * Returns the common ancestor of the given nodes. * * @param nodeA - a node * @param nodeB - a node */ function tree_getCommonAncestor(nodeA, nodeB) { if (nodeA === nodeB) { return nodeA._parent; } // lists of parent nodes var parentsA = []; var parentsB = []; var pA = tree_getFirstAncestorNode(nodeA, true); while (pA !== null) { parentsA.push(pA); pA = tree_getNextAncestorNode(nodeA, pA, true); } var pB = tree_getFirstAncestorNode(nodeB, true); while (pB !== null) { parentsB.push(pB); pB = tree_getNextAncestorNode(nodeB, pB, true); } // walk through parents backwards until they differ var pos1 = parentsA.length; var pos2 = parentsB.length; var parent = null; for (var i = Math.min(pos1, pos2); i > 0; i--) { var parent1 = parentsA[--pos1]; var parent2 = parentsB[--pos2]; if (parent1 !== parent2) { break; } parent = parent1; } return parent; } exports.tree_getCommonAncestor = tree_getCommonAncestor; /** * Returns the node following `node` in depth-first preorder. * * @param root - root of the subtree * @param node - a node */ function tree_getFollowingNode(root, node) { if (node._firstChild) { return node._firstChild; } else if (node._nextSibling) { return node._nextSibling; } else { while (true) { var parent = node._parent; if (parent === null || parent === root) { return null; } else if (parent._nextSibling) { return parent._nextSibling; } else { node = parent; } } } } exports.tree_getFollowingNode = tree_getFollowingNode; /** * Returns the node preceding `node` in depth-first preorder. * * @param root - root of the subtree * @param node - a node */ function tree_getPrecedingNode(root, node) { if (node === root) { return null; } if (node._previousSibling) { node = node._previousSibling; if (node._lastChild) { return node._lastChild; } else { return node; } } else { return node._parent; } } exports.tree_getPrecedingNode = tree_getPrecedingNode; /** * Determines if the node tree is constrained. A node tree is * constrained as follows, expressed as a relationship between the * type of node and its allowed children: * - Document (In tree order) * * Zero or more nodes each of which is ProcessingInstruction * or Comment. * * Optionally one DocumentType node. * * Zero or more nodes each of which is ProcessingInstruction * or Comment. * * Optionally one Element node. * * Zero or more nodes each of which is ProcessingInstruction * or Comment. * - DocumentFragment, Element * * Zero or more nodes each of which is Element, Text, * ProcessingInstruction, or Comment. * - DocumentType, Text, ProcessingInstruction, Comment * * None. * * @param node - the root of the tree */ function tree_isConstrained(node) { var e_1, _a, e_2, _b, e_3, _c; switch (node._nodeType) { case interfaces_1.NodeType.Document: var hasDocType = false; var hasElement = false; try { for (var _d = __values(node._children), _e = _d.next(); !_e.done; _e = _d.next()) { var childNode = _e.value; switch (childNode._nodeType) { case interfaces_1.NodeType.ProcessingInstruction: case interfaces_1.NodeType.Comment: break; case interfaces_1.NodeType.DocumentType: if (hasDocType || hasElement) return false; hasDocType = true; break; case interfaces_1.NodeType.Element: if (hasElement) return false; hasElement = true; break; default: return false; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_e && !_e.done && (_a = _d.return)) _a.call(_d); } finally { if (e_1) throw e_1.error; } } break; case interfaces_1.NodeType.DocumentFragment: case interfaces_1.NodeType.Element: try { for (var _f = __values(node._children), _g = _f.next(); !_g.done; _g = _f.next()) { var childNode = _g.value; switch (childNode._nodeType) { case interfaces_1.NodeType.Element: case interfaces_1.NodeType.Text: case interfaces_1.NodeType.ProcessingInstruction: case interfaces_1.NodeType.CData: case interfaces_1.NodeType.Comment: break; default: return false; } } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_g && !_g.done && (_b = _f.return)) _b.call(_f); } finally { if (e_2) throw e_2.error; } } break; case interfaces_1.NodeType.DocumentType: case interfaces_1.NodeType.Text: case interfaces_1.NodeType.ProcessingInstruction: case interfaces_1.NodeType.CData: case interfaces_1.NodeType.Comment: return (!node.hasChildNodes()); } try { for (var _h = __values(node._children), _j = _h.next(); !_j.done; _j = _h.next()) { var childNode = _j.value; // recursively check child nodes if (!tree_isConstrained(childNode)) return false; } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_j && !_j.done && (_c = _h.return)) _c.call(_h); } finally { if (e_3) throw e_3.error; } } return true; } exports.tree_isConstrained = tree_isConstrained; /** * Returns the length of a node. * * @param node - a node to check */ function tree_nodeLength(node) { /** * To determine the length of a node node, switch on node: * - DocumentType * Zero. * - Text * - ProcessingInstruction * - Comment * Its data’s length. * - Any other node * Its number of children. */ if (util_1.Guard.isDocumentTypeNode(node)) { return 0; } else if (util_1.Guard.isCharacterDataNode(node)) { return node._data.length; } else { return node._children.size; } } exports.tree_nodeLength = tree_nodeLength; /** * Determines if a node is empty. * * @param node - a node to check */ function tree_isEmpty(node) { /** * A node is considered empty if its length is zero. */ return (tree_nodeLength(node) === 0); } exports.tree_isEmpty = tree_isEmpty; /** * Returns the root node of a tree. The root of an object is itself, * if its parent is `null`, or else it is the root of its parent. * The root of a tree is any object participating in that tree * whose parent is `null`. * * @param node - a node of the tree * @param shadow - `true` to return shadow-including root, otherwise * `false` */ function tree_rootNode(node, shadow) { if (shadow === void 0) { shadow = false; } /** * The root of an object is itself, if its parent is null, or else it is the * root of its parent. The root of a tree is any object participating in * that tree whose parent is null. */ if (shadow) { var root = tree_rootNode(node, false); if (util_1.Guard.isShadowRoot(root)) return tree_rootNode(root._host, true); else return root; } else { if (!node._parent) return node; else return tree_rootNode(node._parent); } } exports.tree_rootNode = tree_rootNode; /** * Determines whether `other` is a descendant of `node`. An object * A is called a descendant of an object B, if either A is a child * of B or A is a child of an object C that is a descendant of B. * * @param node - a node * @param other - the node to check * @param self - if `true`, traversal includes `node` itself * @param shadow - if `true`, traversal includes the * node's and its descendant's shadow trees as well. */ function tree_isDescendantOf(node, other, self, shadow) { if (self === void 0) { self = false; } if (shadow === void 0) { shadow = false; } /** * An object A is called a descendant of an object B, if either A is a * child of B or A is a child of an object C that is a descendant of B. * * An inclusive descendant is an object or one of its descendants. */ var child = tree_getFirstDescendantNode(node, self, shadow); while (child !== null) { if (child === other) { return true; } child = tree_getNextDescendantNode(node, child, self, shadow); } return false; } exports.tree_isDescendantOf = tree_isDescendantOf; /** * Determines whether `other` is an ancestor of `node`. An object A * is called an ancestor of an object B if and only if B is a * descendant of A. * * @param node - a node * @param other - the node to check * @param self - if `true`, traversal includes `node` itself * @param shadow - if `true`, traversal includes the * node's and its descendant's shadow trees as well. */ function tree_isAncestorOf(node, other, self, shadow) { if (self === void 0) { self = false; } if (shadow === void 0) { shadow = false; } var ancestor = self ? node : shadow && util_1.Guard.isShadowRoot(node) ? node._host : node._parent; while (ancestor !== null) { if (ancestor === other) return true; ancestor = shadow && util_1.Guard.isShadowRoot(ancestor) ? ancestor._host : ancestor._parent; } return false; } exports.tree_isAncestorOf = tree_isAncestorOf; /** * 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) { if (self === void 0) { self = false; } if (tree_isAncestorOf(node, other, self)) return true; var root = tree_rootNode(node); if (util_1.Guard.isDocumentFragmentNode(root) && root._host !== null && tree_isHostIncludingAncestorOf(root._host, other, self)) return true; return false; } exports.tree_isHostIncludingAncestorOf = tree_isHostIncludingAncestorOf; /** * Determines whether `other` is a sibling of `node`. An object A is * called a sibling of an object B, if and only if B and A share * the same non-null parent. * * @param node - a node * @param other - the node to check * @param self - if `true`, traversal includes `node` itself */ function tree_isSiblingOf(node, other, self) { if (self === void 0) { self = false; } /** * An object A is called a sibling of an object B, if and only if B and A * share the same non-null parent. * * An inclusive sibling is an object or one of its siblings. */ if (node === other) { if (self) return true; } else { return (node._parent !== null && node._parent === other._parent); } return false; } exports.tree_isSiblingOf = tree_isSiblingOf; /** * Determines whether `other` is preceding `node`. An object A is * preceding an object B if A and B are in the same tree and A comes * before B in tree order. * * @param node - a node * @param other - the node to check */ function tree_isPreceding(node, other) { /** * An object A is preceding an object B if A and B are in the same tree and * A comes before B in tree order. */ var nodePos = tree_treePosition(node); var otherPos = tree_treePosition(other); if (nodePos === -1 || otherPos === -1) return false; else if (tree_rootNode(node) !== tree_rootNode(other)) return false; else return otherPos < nodePos; } exports.tree_isPreceding = tree_isPreceding; /** * Determines whether `other` is following `node`. An object A is * following an object B if A and B are in the same tree and A comes * after B in tree order. * * @param node - a node * @param other - the node to check */ function tree_isFollowing(node, other) { /** * An object A is following an object B if A and B are in the same tree and * A comes after B in tree order. */ var nodePos = tree_treePosition(node); var otherPos = tree_treePosition(other); if (nodePos === -1 || otherPos === -1) return false; else if (tree_rootNode(node) !== tree_rootNode(other)) return false; else return otherPos > nodePos; } exports.tree_isFollowing = tree_isFollowing; /** * Determines whether `other` is the parent node of `node`. * * @param node - a node * @param other - the node to check */ function tree_isParentOf(node, other) { /** * An object that participates in a tree has a parent, which is either * null or an object, and has children, which is an ordered set of objects. * An object A whose parent is object B is a child of B. */ return (node._parent === other); } exports.tree_isParentOf = tree_isParentOf; /** * Determines whether `other` is a child node of `node`. * * @param node - a node * @param other - the node to check */ function tree_isChildOf(node, other) { /** * An object that participates in a tree has a parent, which is either * null or an object, and has children, which is an ordered set of objects. * An object A whose parent is object B is a child of B. */ return (other._parent === node); } exports.tree_isChildOf = tree_isChildOf; /** * Returns the previous sibling node of `node` or null if it has no * preceding sibling. * * @param node */ function tree_previousSibling(node) { /** * The previous sibling of an object is its first preceding sibling or null * if it has no preceding sibling. */ return node._previousSibling; } exports.tree_previousSibling = tree_previousSibling; /** * Returns the next sibling node of `node` or null if it has no * following sibling. * * @param node */ function tree_nextSibling(node) { /** * The next sibling of an object is its first following sibling or null * if it has no following sibling. */ return node._nextSibling; } exports.tree_nextSibling = tree_nextSibling; /** * Returns the first child node of `node` or null if it has no * children. * * @param node */ function tree_firstChild(node) { /** * The first child of an object is its first child or null if it has no * children. */ return node._firstChild; } exports.tree_firstChild = tree_firstChild; /** * Returns the last child node of `node` or null if it has no * children. * * @param node */ function tree_lastChild(node) { /** * The last child of an object is its last child or null if it has no * children. */ return node._lastChild; } exports.tree_lastChild = tree_lastChild; /** * Returns the zero-based index of `node` when counted preorder in * the tree rooted at `root`. Returns `-1` if `node` is not in * the tree. * * @param node - the node to get the index of */ function tree_treePosition(node) { var root = tree_rootNode(node); var pos = 0; var childNode = tree_getFirstDescendantNode(root); while (childNode !== null) { pos++; if (childNode === node) return pos; childNode = tree_getNextDescendantNode(root, childNode); } return -1; } exports.tree_treePosition = tree_treePosition; /** * Determines the index of `node`. The index of an object is its number of * preceding siblings, or 0 if it has none. * * @param node - a node * @param other - the node to check */ function tree_index(node) { /** * The index of an object is its number of preceding siblings, or 0 if it * has none. */ var n = 0; while (node._previousSibling !== null) { n++; node = node._previousSibling; } return n; } exports.tree_index = tree_index; /** * Retargets an object against another object. * * @param a - an object to retarget * @param b - an object to retarget against */ function tree_retarget(a, b) { /** * To retarget an object A against an object B, repeat these steps until * they return an object: * 1. If one of the following is true * - A is not a node * - A's root is not a shadow root * - B is a node and A's root is a shadow-including inclusive ancestor * of B * then return A. * 2. Set A to A's root's host. */ while (true) { if (!a || !util_1.Guard.isNode(a)) { return a; } var rootOfA = tree_rootNode(a); if (!util_1.Guard.isShadowRoot(rootOfA)) { return a; } if (b && util_1.Guard.isNode(b) && tree_isAncestorOf(rootOfA, b, true, true)) { return a; } a = rootOfA.host; } } exports.tree_retarget = tree_retarget; //# sourceMappingURL=TreeAlgorithm.js.map