@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 CHANGED
@@ -45,5 +45,5 @@
45
45
  "test": "c8 --reporter=text mocha --exit test/**/*.test.js",
46
46
  "tsc": "npx tsc"
47
47
  },
48
- "version": "0.20.0"
48
+ "version": "0.20.2"
49
49
  }
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: #list[i] corresponds to #matrix[i]
40
- * #list: [
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
- * #matrix: [
51
- * [
52
- * Set([node, node]),
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
- #list;
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 list and matrix
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 list = [];
201
- const matrix = [];
193
+ const tree = [];
194
+ const nodes = [];
202
195
  let i = 0;
203
- for (const branchItem of branches) {
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
- const branchLen = branch.length;
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
- list,
249
- matrix
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 (const attr of attributes) {
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 (const attr of attributes) {
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 listIterator = this.#list.values();
2000
+ const ast = this.#ast.values();
2015
2001
  let i = 0;
2016
- for (const list of listIterator) {
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.#matrix[i][0] = nodes;
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.#list[i].skip = true;
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.#matrix[i][lastIndex] = nodes;
2022
+ this.#nodes[i] = nodes;
2039
2023
  } else {
2040
- this.#list[i].skip = true;
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
- const indexJ = pendingItem.get('j');
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.#list,
2074
- this.#matrix
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.#list;
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 (isSameOrDescendant(node, this.#node)) {
2123
- nodes.add(node);
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 startNodes = this.#matrix[i][0];
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 matched = new Set(arr);
2152
- if (matched.size) {
2141
+ const matchedNodes = new Set(arr);
2142
+ if (matchedNodes.size) {
2153
2143
  if (j === lastIndex) {
2154
2144
  if (targetType === TARGET_FIRST) {
2155
- const [matchedNode] = this._sortNodes(matched);
2156
- nodes.add(matchedNode);
2145
+ const [node] = [...matchedNodes];
2146
+ nodes.add(node);
2157
2147
  } else {
2158
2148
  const n = [...nodes];
2159
- const m = [...matched];
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 = matched;
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 startNodes = this.#matrix[i][lastIndex];
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 matched = new Set(arr);
2189
- if (matched.size) {
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 = matched;
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 i of itemList) {
168
- const { children } = i;
167
+ for (const { children } of itemList) {
169
168
  // SelectorList
170
- for (const j of children) {
171
- const { children: grandChildren } = j;
169
+ for (const { children: grandChildren } of children) {
172
170
  // Selector
173
- for (const k of grandChildren) {
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
  }