@asamuzakjp/dom-selector 0.20.0 → 0.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/js/matcher.js +52 -63
- package/src/js/parser.js +3 -6
package/package.json
CHANGED
package/src/js/matcher.js
CHANGED
|
@@ -36,8 +36,8 @@ const PSEUDO_NTH = /^nth-(?:last-)?(?:child|of-type)$/;
|
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Matcher
|
|
39
|
-
* NOTE: #
|
|
40
|
-
* #
|
|
39
|
+
* NOTE: #ast[i] corresponds to #nodes[i]
|
|
40
|
+
* #ast: [
|
|
41
41
|
* {
|
|
42
42
|
* branch: branch[],
|
|
43
43
|
* skip: boolean
|
|
@@ -47,16 +47,9 @@ const PSEUDO_NTH = /^nth-(?:last-)?(?:child|of-type)$/;
|
|
|
47
47
|
* skip: boolean
|
|
48
48
|
* }
|
|
49
49
|
* ]
|
|
50
|
-
* #
|
|
51
|
-
* [
|
|
52
|
-
*
|
|
53
|
-
* Set([node, node, node]
|
|
54
|
-
* Set([node, node])
|
|
55
|
-
* ],
|
|
56
|
-
* [
|
|
57
|
-
* Set([node, node, node]),
|
|
58
|
-
* Set([node, node])
|
|
59
|
-
* ]
|
|
50
|
+
* #nodes: [
|
|
51
|
+
* Set([node{}, node{}]),
|
|
52
|
+
* Set([node{}, node, node{}])
|
|
60
53
|
* ]
|
|
61
54
|
* branch[]: [twig{}, twig{}]
|
|
62
55
|
* twig{}: {
|
|
@@ -65,13 +58,13 @@ const PSEUDO_NTH = /^nth-(?:last-)?(?:child|of-type)$/;
|
|
|
65
58
|
* }
|
|
66
59
|
* leaves[]: [leaf{}, leaf{}, leaf{}]
|
|
67
60
|
* leaf{}: AST leaf
|
|
68
|
-
* node: Element node
|
|
61
|
+
* node{}: Element node
|
|
69
62
|
*/
|
|
70
63
|
export class Matcher {
|
|
71
64
|
/* private fields */
|
|
72
|
-
#
|
|
73
|
-
#matrix;
|
|
65
|
+
#ast;
|
|
74
66
|
#node;
|
|
67
|
+
#nodes;
|
|
75
68
|
#root;
|
|
76
69
|
#selector;
|
|
77
70
|
#sort;
|
|
@@ -87,12 +80,12 @@ export class Matcher {
|
|
|
87
80
|
*/
|
|
88
81
|
constructor(selector, node, opt = {}) {
|
|
89
82
|
const { sort, warn } = opt;
|
|
83
|
+
[this.#ast, this.#nodes] = this._prepare(selector);
|
|
90
84
|
this.#node = node;
|
|
91
85
|
this.#root = this._getRoot(node);
|
|
92
86
|
this.#selector = selector;
|
|
93
87
|
this.#sort = !!sort;
|
|
94
88
|
this.#warn = !!warn;
|
|
95
|
-
[this.#list, this.#matrix] = this._prepare(selector);
|
|
96
89
|
}
|
|
97
90
|
|
|
98
91
|
/**
|
|
@@ -190,18 +183,17 @@ export class Matcher {
|
|
|
190
183
|
}
|
|
191
184
|
|
|
192
185
|
/**
|
|
193
|
-
* prepare
|
|
186
|
+
* prepare ast and nodes
|
|
194
187
|
* @param {string} selector - CSS selector
|
|
195
188
|
* @returns {Array} - list and matrix
|
|
196
189
|
*/
|
|
197
190
|
_prepare(selector = this.#selector) {
|
|
198
191
|
const ast = parseSelector(selector);
|
|
199
192
|
const branches = walkAST(ast).values();
|
|
200
|
-
const
|
|
201
|
-
const
|
|
193
|
+
const tree = [];
|
|
194
|
+
const nodes = [];
|
|
202
195
|
let i = 0;
|
|
203
|
-
for (const
|
|
204
|
-
const [...items] = branchItem;
|
|
196
|
+
for (const [...items] of branches) {
|
|
205
197
|
const branch = [];
|
|
206
198
|
let item = items.shift();
|
|
207
199
|
if (item && item.type !== COMBINATOR) {
|
|
@@ -233,20 +225,16 @@ export class Matcher {
|
|
|
233
225
|
}
|
|
234
226
|
}
|
|
235
227
|
}
|
|
236
|
-
|
|
237
|
-
matrix[i] = [];
|
|
238
|
-
for (let j = 0; j < branchLen; j++) {
|
|
239
|
-
matrix[i][j] = new Set();
|
|
240
|
-
}
|
|
241
|
-
list.push({
|
|
228
|
+
tree.push({
|
|
242
229
|
branch,
|
|
243
230
|
skip: false
|
|
244
231
|
});
|
|
232
|
+
nodes[i] = new Set();
|
|
245
233
|
i++;
|
|
246
234
|
}
|
|
247
235
|
return [
|
|
248
|
-
|
|
249
|
-
|
|
236
|
+
tree,
|
|
237
|
+
nodes
|
|
250
238
|
];
|
|
251
239
|
}
|
|
252
240
|
|
|
@@ -1334,8 +1322,7 @@ export class Matcher {
|
|
|
1334
1322
|
const {
|
|
1335
1323
|
prefix: astAttrPrefix, tagName: astAttrLocalName
|
|
1336
1324
|
} = selectorToNodeProps(astAttrName);
|
|
1337
|
-
for (
|
|
1338
|
-
let { name: itemName, value: itemValue } = attr;
|
|
1325
|
+
for (let { name: itemName, value: itemValue } of attributes) {
|
|
1339
1326
|
if (caseInsensitive) {
|
|
1340
1327
|
itemName = itemName.toLowerCase();
|
|
1341
1328
|
itemValue = itemValue.toLowerCase();
|
|
@@ -1369,8 +1356,7 @@ export class Matcher {
|
|
|
1369
1356
|
}
|
|
1370
1357
|
}
|
|
1371
1358
|
} else {
|
|
1372
|
-
for (
|
|
1373
|
-
let { name: itemName, value: itemValue } = attr;
|
|
1359
|
+
for (let { name: itemName, value: itemValue } of attributes) {
|
|
1374
1360
|
if (caseInsensitive) {
|
|
1375
1361
|
itemName = itemName.toLowerCase();
|
|
1376
1362
|
itemValue = itemValue.toLowerCase();
|
|
@@ -2011,23 +1997,21 @@ export class Matcher {
|
|
|
2011
1997
|
*/
|
|
2012
1998
|
_collectNodes(targetType) {
|
|
2013
1999
|
const pendingItems = new Set();
|
|
2014
|
-
const
|
|
2000
|
+
const ast = this.#ast.values();
|
|
2015
2001
|
let i = 0;
|
|
2016
|
-
for (const
|
|
2017
|
-
const { branch } = list;
|
|
2002
|
+
for (const { branch } of ast) {
|
|
2018
2003
|
if (targetType === TARGET_ALL || targetType === TARGET_FIRST) {
|
|
2019
2004
|
const twig = branch[0];
|
|
2020
2005
|
const { nodes, pending } = this._findNodes(twig, targetType);
|
|
2021
2006
|
if (nodes.size) {
|
|
2022
|
-
this.#
|
|
2007
|
+
this.#nodes[i] = nodes;
|
|
2023
2008
|
} else if (pending) {
|
|
2024
2009
|
pendingItems.add(new Map([
|
|
2025
2010
|
['i', i],
|
|
2026
|
-
['j', 0],
|
|
2027
2011
|
['twig', twig]
|
|
2028
2012
|
]));
|
|
2029
2013
|
} else {
|
|
2030
|
-
this.#
|
|
2014
|
+
this.#ast[i].skip = true;
|
|
2031
2015
|
}
|
|
2032
2016
|
} else {
|
|
2033
2017
|
const branchLen = branch.length;
|
|
@@ -2035,9 +2019,9 @@ export class Matcher {
|
|
|
2035
2019
|
const twig = branch[lastIndex];
|
|
2036
2020
|
const { nodes } = this._findNodes(twig, targetType);
|
|
2037
2021
|
if (nodes.size) {
|
|
2038
|
-
this.#
|
|
2022
|
+
this.#nodes[i] = nodes;
|
|
2039
2023
|
} else {
|
|
2040
|
-
this.#
|
|
2024
|
+
this.#ast[i].skip = true;
|
|
2041
2025
|
}
|
|
2042
2026
|
}
|
|
2043
2027
|
i++;
|
|
@@ -2047,7 +2031,7 @@ export class Matcher {
|
|
|
2047
2031
|
const iterator = document.createNodeIterator(root, SHOW_ELEMENT);
|
|
2048
2032
|
let nextNode = iterator.nextNode();
|
|
2049
2033
|
while (nextNode) {
|
|
2050
|
-
let bool;
|
|
2034
|
+
let bool = false;
|
|
2051
2035
|
if (targetType === TARGET_ALL || targetType === TARGET_FIRST) {
|
|
2052
2036
|
if (this.#node.nodeType === ELEMENT_NODE) {
|
|
2053
2037
|
bool = isSameOrDescendant(nextNode, this.#node);
|
|
@@ -2061,8 +2045,7 @@ export class Matcher {
|
|
|
2061
2045
|
const matched = this._matchLeaves(leaves, nextNode);
|
|
2062
2046
|
if (matched) {
|
|
2063
2047
|
const indexI = pendingItem.get('i');
|
|
2064
|
-
|
|
2065
|
-
this.#matrix[indexI][indexJ].add(nextNode);
|
|
2048
|
+
this.#nodes[indexI].add(nextNode);
|
|
2066
2049
|
}
|
|
2067
2050
|
}
|
|
2068
2051
|
}
|
|
@@ -2070,8 +2053,8 @@ export class Matcher {
|
|
|
2070
2053
|
}
|
|
2071
2054
|
}
|
|
2072
2055
|
return [
|
|
2073
|
-
this.#
|
|
2074
|
-
this.#
|
|
2056
|
+
this.#ast,
|
|
2057
|
+
this.#nodes
|
|
2075
2058
|
];
|
|
2076
2059
|
}
|
|
2077
2060
|
|
|
@@ -2104,7 +2087,7 @@ export class Matcher {
|
|
|
2104
2087
|
* @returns {object} - collection of matched nodes
|
|
2105
2088
|
*/
|
|
2106
2089
|
_matchNodes(targetType) {
|
|
2107
|
-
const [...branches] = this.#
|
|
2090
|
+
const [...branches] = this.#ast;
|
|
2108
2091
|
const l = branches.length;
|
|
2109
2092
|
let nodes = new Set();
|
|
2110
2093
|
for (let i = 0; i < l; i++) {
|
|
@@ -2113,16 +2096,24 @@ export class Matcher {
|
|
|
2113
2096
|
if (skip) {
|
|
2114
2097
|
continue;
|
|
2115
2098
|
} else if (branchLen) {
|
|
2099
|
+
const matched = this.#nodes[i];
|
|
2116
2100
|
const lastIndex = branchLen - 1;
|
|
2117
2101
|
if (lastIndex === 0) {
|
|
2118
|
-
const matched = this.#matrix[i][0];
|
|
2119
2102
|
if ((targetType === TARGET_ALL || targetType === TARGET_FIRST) &&
|
|
2120
2103
|
this.#node.nodeType === ELEMENT_NODE) {
|
|
2121
2104
|
for (const node of matched) {
|
|
2122
|
-
if (
|
|
2123
|
-
|
|
2105
|
+
if (node !== this.#node) {
|
|
2106
|
+
if (isSameOrDescendant(node, this.#node)) {
|
|
2107
|
+
nodes.add(node);
|
|
2108
|
+
if (targetType === TARGET_FIRST) {
|
|
2109
|
+
break;
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2124
2112
|
}
|
|
2125
2113
|
}
|
|
2114
|
+
} else if (targetType === TARGET_FIRST) {
|
|
2115
|
+
const [node] = [...matched];
|
|
2116
|
+
nodes.add(node);
|
|
2126
2117
|
} else {
|
|
2127
2118
|
const n = [...nodes];
|
|
2128
2119
|
const m = [...matched];
|
|
@@ -2130,8 +2121,7 @@ export class Matcher {
|
|
|
2130
2121
|
}
|
|
2131
2122
|
} else if (targetType === TARGET_ALL || targetType === TARGET_FIRST) {
|
|
2132
2123
|
let { combo } = branch[0];
|
|
2133
|
-
const
|
|
2134
|
-
for (const node of startNodes) {
|
|
2124
|
+
for (const node of matched) {
|
|
2135
2125
|
let nextNodes = new Set([node]);
|
|
2136
2126
|
for (let j = 1; j < branchLen; j++) {
|
|
2137
2127
|
const { combo: nextCombo, leaves } = branch[j];
|
|
@@ -2148,21 +2138,21 @@ export class Matcher {
|
|
|
2148
2138
|
arr.push(...m);
|
|
2149
2139
|
}
|
|
2150
2140
|
}
|
|
2151
|
-
const
|
|
2152
|
-
if (
|
|
2141
|
+
const matchedNodes = new Set(arr);
|
|
2142
|
+
if (matchedNodes.size) {
|
|
2153
2143
|
if (j === lastIndex) {
|
|
2154
2144
|
if (targetType === TARGET_FIRST) {
|
|
2155
|
-
const [
|
|
2156
|
-
nodes.add(
|
|
2145
|
+
const [node] = [...matchedNodes];
|
|
2146
|
+
nodes.add(node);
|
|
2157
2147
|
} else {
|
|
2158
2148
|
const n = [...nodes];
|
|
2159
|
-
const m = [...
|
|
2149
|
+
const m = [...matchedNodes];
|
|
2160
2150
|
nodes = new Set([...n, ...m]);
|
|
2161
2151
|
}
|
|
2162
2152
|
break;
|
|
2163
2153
|
} else {
|
|
2164
2154
|
combo = nextCombo;
|
|
2165
|
-
nextNodes =
|
|
2155
|
+
nextNodes = matchedNodes;
|
|
2166
2156
|
}
|
|
2167
2157
|
} else {
|
|
2168
2158
|
break;
|
|
@@ -2170,8 +2160,7 @@ export class Matcher {
|
|
|
2170
2160
|
}
|
|
2171
2161
|
}
|
|
2172
2162
|
} else {
|
|
2173
|
-
const
|
|
2174
|
-
for (const node of startNodes) {
|
|
2163
|
+
for (const node of matched) {
|
|
2175
2164
|
let nextNodes = new Set([node]);
|
|
2176
2165
|
let bool;
|
|
2177
2166
|
for (let j = lastIndex - 1; j >= 0; j--) {
|
|
@@ -2185,14 +2174,14 @@ export class Matcher {
|
|
|
2185
2174
|
arr.push(...m);
|
|
2186
2175
|
}
|
|
2187
2176
|
}
|
|
2188
|
-
const
|
|
2189
|
-
if (
|
|
2177
|
+
const matchedNodes = new Set(arr);
|
|
2178
|
+
if (matchedNodes.size) {
|
|
2190
2179
|
bool = true;
|
|
2191
2180
|
if (j === 0) {
|
|
2192
2181
|
nodes.add(node);
|
|
2193
2182
|
break;
|
|
2194
2183
|
} else {
|
|
2195
|
-
nextNodes =
|
|
2184
|
+
nextNodes = matchedNodes;
|
|
2196
2185
|
}
|
|
2197
2186
|
} else {
|
|
2198
2187
|
bool = false;
|
package/src/js/parser.js
CHANGED
|
@@ -164,14 +164,11 @@ export const walkAST = (ast = {}) => {
|
|
|
164
164
|
const { name, type } = i;
|
|
165
165
|
return type === PSEUDO_CLASS_SELECTOR && PSEUDO_FUNC.test(name);
|
|
166
166
|
});
|
|
167
|
-
for (const
|
|
168
|
-
const { children } = i;
|
|
167
|
+
for (const { children } of itemList) {
|
|
169
168
|
// SelectorList
|
|
170
|
-
for (const
|
|
171
|
-
const { children: grandChildren } = j;
|
|
169
|
+
for (const { children: grandChildren } of children) {
|
|
172
170
|
// Selector
|
|
173
|
-
for (const
|
|
174
|
-
const { children: greatGrandChildren } = k;
|
|
171
|
+
for (const { children: greatGrandChildren } of grandChildren) {
|
|
175
172
|
if (branches.has(greatGrandChildren)) {
|
|
176
173
|
branches.delete(greatGrandChildren);
|
|
177
174
|
}
|