@asamuzakjp/dom-selector 4.2.2 → 4.4.0
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/README.md +34 -29
- package/dist/cjs/js/constant.js +1 -1
- package/dist/cjs/js/constant.js.map +2 -2
- package/dist/cjs/js/dom-util.js +1 -1
- package/dist/cjs/js/dom-util.js.map +2 -2
- package/dist/cjs/js/finder.js +1 -1
- package/dist/cjs/js/finder.js.map +3 -3
- package/dist/cjs/js/parser.js +2 -2
- package/dist/cjs/js/parser.js.map +3 -3
- package/package.json +13 -13
- package/src/js/constant.js +1 -1
- package/src/js/dom-util.js +3 -3
- package/src/js/finder.js +84 -22
- package/src/js/parser.js +74 -28
- package/types/js/finder.d.ts +1 -0
- package/types/js/parser.d.ts +2 -2
package/src/js/parser.js
CHANGED
|
@@ -8,7 +8,7 @@ import { findAll, parse, toPlainObject, walk } from 'css-tree';
|
|
|
8
8
|
/* constants */
|
|
9
9
|
import {
|
|
10
10
|
BIT_01, BIT_02, BIT_04, BIT_08, BIT_16, BIT_32, BIT_FFFF, BIT_HYPHEN,
|
|
11
|
-
DUO, EMPTY, HEX, REG_LOGICAL_PSEUDO, REG_SHADOW_PSEUDO, SELECTOR,
|
|
11
|
+
COMBINATOR, DUO, EMPTY, HEX, REG_LOGICAL_PSEUDO, REG_SHADOW_PSEUDO, SELECTOR,
|
|
12
12
|
SELECTOR_ATTR, SELECTOR_CLASS, SELECTOR_ID, SELECTOR_PSEUDO_CLASS,
|
|
13
13
|
SELECTOR_PSEUDO_ELEMENT, SELECTOR_TYPE, SYNTAX_ERR, TYPE_FROM, TYPE_TO, U_FFFD
|
|
14
14
|
} from './constant.js';
|
|
@@ -169,11 +169,12 @@ export const parseSelector = selector => {
|
|
|
169
169
|
/**
|
|
170
170
|
* walk AST
|
|
171
171
|
* @param {object} ast - AST
|
|
172
|
-
* @returns {
|
|
172
|
+
* @returns {object} - branches and complex
|
|
173
173
|
*/
|
|
174
174
|
export const walkAST = (ast = {}) => {
|
|
175
175
|
const branches = new Set();
|
|
176
176
|
let hasPseudoFunc;
|
|
177
|
+
let hasComplexSelector;
|
|
177
178
|
const opt = {
|
|
178
179
|
enter: node => {
|
|
179
180
|
if (node.type === SELECTOR) {
|
|
@@ -204,6 +205,13 @@ export const walkAST = (ast = {}) => {
|
|
|
204
205
|
// Selector
|
|
205
206
|
for (const { children: greatGrandChildren } of grandChildren) {
|
|
206
207
|
if (branches.has(greatGrandChildren)) {
|
|
208
|
+
for (const greatGrandChild of greatGrandChildren) {
|
|
209
|
+
const { type: greatGrandChildType } = greatGrandChild;
|
|
210
|
+
if (greatGrandChildType === COMBINATOR) {
|
|
211
|
+
hasComplexSelector = true;
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
207
215
|
branches.delete(greatGrandChildren);
|
|
208
216
|
}
|
|
209
217
|
}
|
|
@@ -229,7 +237,10 @@ export const walkAST = (ast = {}) => {
|
|
|
229
237
|
}
|
|
230
238
|
});
|
|
231
239
|
}
|
|
232
|
-
return
|
|
240
|
+
return {
|
|
241
|
+
branches: [...branches],
|
|
242
|
+
complex: !!hasComplexSelector
|
|
243
|
+
};
|
|
233
244
|
};
|
|
234
245
|
|
|
235
246
|
/**
|
|
@@ -291,12 +302,56 @@ export const parseAstName = selector => {
|
|
|
291
302
|
};
|
|
292
303
|
};
|
|
293
304
|
|
|
305
|
+
/* filter selector constants */
|
|
306
|
+
// :first-child, :last-child etc.
|
|
307
|
+
const N_ST = '(?:first|last|only)-(?:child|of-type)';
|
|
308
|
+
const DIGIT = '(?:0|[1-9]\\d*)';
|
|
309
|
+
const ANB = `[+-]?(?:${DIGIT}n?|n)|(?:[+-]?${DIGIT})?n\\s*[+-]\\s*${DIGIT}`;
|
|
310
|
+
// exclude An+B with selector list, e.g. :nth-child(2n+1 of .foo)
|
|
311
|
+
const N_TH = `nth-(?:last-)?(?:child|of-type)\\(\\s*(?:even|odd|${ANB})\\s*\\)`;
|
|
312
|
+
// *, tag
|
|
313
|
+
const TAG_TYPE = '\\*|[A-Za-z][\\w-]*';
|
|
314
|
+
// attr, id, class, pseudo-class
|
|
315
|
+
const SUB_CLASS = '\\[[^\\]]+\\]|[#.:][\\w-]+';
|
|
316
|
+
const LOGICAL_KEY = '(?:is|not|where)';
|
|
317
|
+
const COMBO_A = '\\s?[\\s>~+]\\s?';
|
|
318
|
+
const COMBO_B = '\\s?[~+]\\s?';
|
|
319
|
+
const COMPOUND_A = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_CLASS})+)`;
|
|
320
|
+
const COMPLEX_A = `${COMPOUND_A}(?:${COMBO_A}${COMPOUND_A})*`;
|
|
321
|
+
const COMPLEX_B = `${COMPOUND_A}(?:${COMBO_B}${COMPOUND_A})*`;
|
|
322
|
+
const NESTED_LOGICAL_A =
|
|
323
|
+
`:${LOGICAL_KEY}\\(\\s*${COMPOUND_A}(?:\\s*,\\s*${COMPOUND_A})*\\s*\\)`;
|
|
324
|
+
const NESTED_LOGICAL_B =
|
|
325
|
+
`:${LOGICAL_KEY}\\(\\s*${COMPLEX_A}(?:\\s*,\\s*${COMPLEX_A})*\\s*\\)`;
|
|
326
|
+
const NESTED_LOGICAL_C =
|
|
327
|
+
`:${LOGICAL_KEY}\\(\\s*${COMPLEX_B}(?:\\s*,\\s*${COMPLEX_B})*\\s*\\)`;
|
|
328
|
+
const COMPOUND_B =
|
|
329
|
+
`(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_CLASS}|${NESTED_LOGICAL_A})+)`;
|
|
330
|
+
const COMPOUND_C =
|
|
331
|
+
`(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_CLASS}|${NESTED_LOGICAL_B})+)`;
|
|
332
|
+
const COMPOUND_D =
|
|
333
|
+
`(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_CLASS}|${NESTED_LOGICAL_C})+)`;
|
|
334
|
+
const COMPLEX_C = `${COMPOUND_C}(?:${COMBO_A}${COMPOUND_C})*`;
|
|
335
|
+
const COMPLEX_D = `${COMPOUND_D}(?:${COMBO_B}${COMPOUND_D})*`;
|
|
336
|
+
const LOGICAL_COMPOUND =
|
|
337
|
+
`${LOGICAL_KEY}\\(\\s*${COMPOUND_B}(?:\\s*,\\s*${COMPOUND_B})*\\s*\\)`;
|
|
338
|
+
const LOGICAL_COMPLEX_A =
|
|
339
|
+
`${LOGICAL_KEY}\\(\\s*${COMPLEX_C}(?:\\s*,\\s*${COMPLEX_C})*\\s*\\)`;
|
|
340
|
+
const LOGICAL_COMPLEX_B =
|
|
341
|
+
`${LOGICAL_KEY}\\(\\s*${COMPLEX_D}(?:\\s*,\\s*${COMPLEX_D})*\\s*\\)`;
|
|
342
|
+
const REG_LOGICAL_KEY = new RegExp(`:${LOGICAL_KEY}\\(`);
|
|
343
|
+
const REG_COMPLEX_A = new RegExp(`:(?!${N_ST}|${N_TH}|${LOGICAL_COMPLEX_A})`);
|
|
344
|
+
const REG_COMPLEX_B = new RegExp(`:(?!${N_ST}|${N_TH}|${LOGICAL_COMPLEX_B})`);
|
|
345
|
+
const REG_COMPOUND = new RegExp(`:(?!${N_ST}|${N_TH}|${LOGICAL_COMPOUND})`);
|
|
346
|
+
const REG_CHILD_INDEXED = new RegExp(`:(?!${N_ST}|${N_TH})`);
|
|
347
|
+
|
|
294
348
|
/**
|
|
295
349
|
* filter selector (for nwsapi)
|
|
296
350
|
* @param {string} selector - selector
|
|
351
|
+
* @param {object} opt - options
|
|
297
352
|
* @returns {boolean} - result
|
|
298
353
|
*/
|
|
299
|
-
export const filterSelector = selector => {
|
|
354
|
+
export const filterSelector = (selector, opt = {}) => {
|
|
300
355
|
if (!selector || typeof selector !== 'string') {
|
|
301
356
|
return false;
|
|
302
357
|
}
|
|
@@ -305,31 +360,22 @@ export const filterSelector = selector => {
|
|
|
305
360
|
if (/\||::|\[\s*[\w$*=^|~-]+(?:(?:"[\w$*=^|~\s'-]+"|'[\w$*=^|~\s"-]+')?(?:\s+[\w$*=^|~-]+)+|"[^"\]]{1,255}|'[^'\]]{1,255})\s*\]/.test(selector)) {
|
|
306
361
|
return false;
|
|
307
362
|
}
|
|
308
|
-
// filter pseudo-
|
|
363
|
+
// filter pseudo-classes other than child-indexed and logical combination
|
|
309
364
|
if (selector.includes(':')) {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
// nst:
|
|
325
|
-
// `(?:first|last|only)-(?:child|of-type)`
|
|
326
|
-
// nth: exclude An+B with selector list, e.g. :nth-child(2n+1 of .foo)
|
|
327
|
-
// `nth-(?:last-)?(?:child|of-type)\(\s*(?:even|odd|${anb})\s*\)`
|
|
328
|
-
// logical: exclude complex selector, e.g. :is(.foo > .bar)
|
|
329
|
-
// `(?:is|not|where)\(\s*${compoundB}(?:\s*,\s*${compoundB})*\s*\)`
|
|
330
|
-
// filter pseudos other than child-indexed and logical combination pseudos
|
|
331
|
-
// `:(?!${nst}|${nth}|${logical})`
|
|
332
|
-
if (/:(?!(?:first|last|only)-(?:child|of-type)|nth-(?:last-)?(?:child|of-type)\(\s*(?:even|odd|[+-]?(?:(?:0|[1-9]\d*)n?|n)|(?:[+-]?(?:0|[1-9]\d*))?n\s*[+-]\s*(?:0|[1-9]\d*))\s*\)|(?:is|not|where)\(\s*(?:\*|[A-Za-z][\w-]*|(?:\*|[A-Za-z][\w-]*)?(?:\[[^\]]+\]|[#.:][\w-]+|:(?:is|not|where)\(\s*(?:\*|[A-Za-z][\w-]*|(?:\*|[A-Za-z][\w-]*)?(?:\[[^\]]+\]|[#.:][\w-]+)+)(?:\s*,\s*(?:\*|[A-Za-z][\w-]*|(?:\*|[A-Za-z][\w-]*)?(?:\[[^\]]+\]|[#.:][\w-]+)+))*\s*\))+)(?:\s*,\s*(?:\*|[A-Za-z][\w-]*|(?:\*|[A-Za-z][\w-]*)?(?:\[[^\]]+\]|[#.:][\w-]+|:(?:is|not|where)\(\s*(?:\*|[A-Za-z][\w-]*|(?:\*|[A-Za-z][\w-]*)?(?:\[[^\]]+\]|[#.:][\w-]+)+)(?:\s*,\s*(?:\*|[A-Za-z][\w-]*|(?:\*|[A-Za-z][\w-]*)?(?:\[[^\]]+\]|[#.:][\w-]+)+))*\s*\))+))*\s*\))/.test(selector)) {
|
|
365
|
+
let reg;
|
|
366
|
+
if (REG_LOGICAL_KEY.test(selector)) {
|
|
367
|
+
const { complex, descendant } = opt;
|
|
368
|
+
if (complex && descendant) {
|
|
369
|
+
reg = REG_COMPLEX_A;
|
|
370
|
+
} else if (complex) {
|
|
371
|
+
reg = REG_COMPLEX_B;
|
|
372
|
+
} else {
|
|
373
|
+
reg = REG_COMPOUND;
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
reg = REG_CHILD_INDEXED;
|
|
377
|
+
}
|
|
378
|
+
if (reg.test(selector)) {
|
|
333
379
|
return false;
|
|
334
380
|
}
|
|
335
381
|
}
|
package/types/js/finder.d.ts
CHANGED
package/types/js/parser.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export function unescapeSelector(selector?: string): string | null;
|
|
2
2
|
export function preprocess(...args: any[]): string;
|
|
3
3
|
export function parseSelector(selector: string): object;
|
|
4
|
-
export function walkAST(ast?: object):
|
|
4
|
+
export function walkAST(ast?: object): object;
|
|
5
5
|
export function sortAST(asts: Array<object>): Array<object>;
|
|
6
6
|
export function parseAstName(selector: string): object;
|
|
7
|
-
export function filterSelector(selector: string): boolean;
|
|
7
|
+
export function filterSelector(selector: string, opt?: object): boolean;
|
|
8
8
|
export { generate as generateCSS } from "css-tree";
|