UNPKG

4.52 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.uniqueSort = exports.compareDocumentPosition = exports.removeSubsets = void 0;
4var domhandler_1 = require("domhandler");
5/**
6 * Given an array of nodes, remove any member that is contained by another.
7 *
8 * @param nodes Nodes to filter.
9 * @returns Remaining nodes that aren't subtrees of each other.
10 */
11function removeSubsets(nodes) {
12 var idx = nodes.length;
13 /*
14 * Check if each node (or one of its ancestors) is already contained in the
15 * array.
16 */
17 while (--idx >= 0) {
18 var node = nodes[idx];
19 /*
20 * Remove the node if it is not unique.
21 * We are going through the array from the end, so we only
22 * have to check nodes that preceed the node under consideration in the array.
23 */
24 if (idx > 0 && nodes.lastIndexOf(node, idx - 1) >= 0) {
25 nodes.splice(idx, 1);
26 continue;
27 }
28 for (var ancestor = node.parent; ancestor; ancestor = ancestor.parent) {
29 if (nodes.includes(ancestor)) {
30 nodes.splice(idx, 1);
31 break;
32 }
33 }
34 }
35 return nodes;
36}
37exports.removeSubsets = removeSubsets;
38/**
39 * Compare the position of one node against another node in any other document.
40 * The return value is a bitmask with the following values:
41 *
42 * Document order:
43 * > There is an ordering, document order, defined on all the nodes in the
44 * > document corresponding to the order in which the first character of the
45 * > XML representation of each node occurs in the XML representation of the
46 * > document after expansion of general entities. Thus, the document element
47 * > node will be the first node. Element nodes occur before their children.
48 * > Thus, document order orders element nodes in order of the occurrence of
49 * > their start-tag in the XML (after expansion of entities). The attribute
50 * > nodes of an element occur after the element and before its children. The
51 * > relative order of attribute nodes is implementation-dependent./
52 *
53 * Source:
54 * http://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-document-order
55 *
56 * @param nodeA The first node to use in the comparison
57 * @param nodeB The second node to use in the comparison
58 * @returns A bitmask describing the input nodes' relative position.
59 *
60 * See http://dom.spec.whatwg.org/#dom-node-comparedocumentposition for
61 * a description of these values.
62 */
63function compareDocumentPosition(nodeA, nodeB) {
64 var aParents = [];
65 var bParents = [];
66 if (nodeA === nodeB) {
67 return 0;
68 }
69 var current = (0, domhandler_1.hasChildren)(nodeA) ? nodeA : nodeA.parent;
70 while (current) {
71 aParents.unshift(current);
72 current = current.parent;
73 }
74 current = (0, domhandler_1.hasChildren)(nodeB) ? nodeB : nodeB.parent;
75 while (current) {
76 bParents.unshift(current);
77 current = current.parent;
78 }
79 var maxIdx = Math.min(aParents.length, bParents.length);
80 var idx = 0;
81 while (idx < maxIdx && aParents[idx] === bParents[idx]) {
82 idx++;
83 }
84 if (idx === 0) {
85 return 1 /* DISCONNECTED */;
86 }
87 var sharedParent = aParents[idx - 1];
88 var siblings = sharedParent.children;
89 var aSibling = aParents[idx];
90 var bSibling = bParents[idx];
91 if (siblings.indexOf(aSibling) > siblings.indexOf(bSibling)) {
92 if (sharedParent === nodeB) {
93 return 4 /* FOLLOWING */ | 16 /* CONTAINED_BY */;
94 }
95 return 4 /* FOLLOWING */;
96 }
97 if (sharedParent === nodeA) {
98 return 2 /* PRECEDING */ | 8 /* CONTAINS */;
99 }
100 return 2 /* PRECEDING */;
101}
102exports.compareDocumentPosition = compareDocumentPosition;
103/**
104 * Sort an array of nodes based on their relative position in the document and
105 * remove any duplicate nodes. If the array contains nodes that do not belong
106 * to the same document, sort order is unspecified.
107 *
108 * @param nodes Array of DOM nodes.
109 * @returns Collection of unique nodes, sorted in document order.
110 */
111function uniqueSort(nodes) {
112 nodes = nodes.filter(function (node, i, arr) { return !arr.includes(node, i + 1); });
113 nodes.sort(function (a, b) {
114 var relative = compareDocumentPosition(a, b);
115 if (relative & 2 /* PRECEDING */) {
116 return -1;
117 }
118 else if (relative & 4 /* FOLLOWING */) {
119 return 1;
120 }
121 return 0;
122 });
123 return nodes;
124}
125exports.uniqueSort = uniqueSort;