@markuplint/selector 3.0.0-dev.25 → 3.0.0-dev.290
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/lib/compare-specificity.d.ts +1 -1
- package/lib/compare-specificity.js +1 -5
- package/lib/create-selector.d.ts +2 -2
- package/lib/create-selector.js +12 -14
- package/lib/debug.js +9 -14
- package/lib/extended-selector/aria-pseudo-class.d.ts +1 -1
- package/lib/extended-selector/aria-pseudo-class.js +11 -10
- package/lib/extended-selector/aria-role-pseudo-class.d.ts +1 -1
- package/lib/extended-selector/aria-role-pseudo-class.js +12 -12
- package/lib/extended-selector/content-model-pseudo-class.d.ts +1 -1
- package/lib/extended-selector/content-model-pseudo-class.js +9 -11
- package/lib/index.d.ts +5 -4
- package/lib/index.js +5 -11
- package/lib/invalid-selector-error.d.ts +2 -0
- package/lib/invalid-selector-error.js +4 -7
- package/lib/is.js +9 -9
- package/lib/match-selector.d.ts +6 -6
- package/lib/match-selector.js +33 -27
- package/lib/regex-selector-matches.js +2 -6
- package/lib/selector.d.ts +2 -2
- package/lib/selector.js +133 -87
- package/lib/types.d.ts +13 -13
- package/lib/types.js +1 -2
- package/package.json +18 -9
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
package/lib/selector.js
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var _Selector_ruleset, _Ruleset_selectorGroup, _StructuredSelector_edge, _StructuredSelector_selector, _SelectorTarget_combinedFrom, _SelectorTarget_extended, _SelectorTarget_isAdded;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
const resLog = debug_1.log.extend('result');
|
|
14
|
-
class Selector {
|
|
2
|
+
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
3
|
+
import { resolveNamespace } from '@markuplint/ml-spec';
|
|
4
|
+
import parser from 'postcss-selector-parser';
|
|
5
|
+
import { compareSpecificity } from './compare-specificity.js';
|
|
6
|
+
import { log as coreLog } from './debug.js';
|
|
7
|
+
import { InvalidSelectorError } from './invalid-selector-error.js';
|
|
8
|
+
import { isElement, isNonDocumentTypeChildNode, isPureHTMLElement } from './is.js';
|
|
9
|
+
const selLog = coreLog.extend('selector');
|
|
10
|
+
const resLog = coreLog.extend('result');
|
|
11
|
+
export class Selector {
|
|
15
12
|
constructor(selector, extended = {}) {
|
|
16
13
|
_Selector_ruleset.set(this, void 0);
|
|
17
|
-
|
|
14
|
+
__classPrivateFieldSet(this, _Selector_ruleset, Ruleset.parse(selector, extended), "f");
|
|
18
15
|
}
|
|
19
|
-
match(
|
|
16
|
+
match(
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
18
|
+
el,
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
20
|
+
scope) {
|
|
21
|
+
scope = isElement(el) ? el : null;
|
|
20
22
|
const results = this.search(el, scope);
|
|
21
23
|
for (const result of results) {
|
|
22
24
|
if (result.matched) {
|
|
@@ -25,23 +27,27 @@ class Selector {
|
|
|
25
27
|
}
|
|
26
28
|
return false;
|
|
27
29
|
}
|
|
28
|
-
search(
|
|
29
|
-
|
|
30
|
+
search(
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
32
|
+
el,
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
34
|
+
scope) {
|
|
35
|
+
scope = isElement(el) ? el : null;
|
|
36
|
+
return __classPrivateFieldGet(this, _Selector_ruleset, "f").match(el, scope);
|
|
30
37
|
}
|
|
31
38
|
}
|
|
32
|
-
exports.Selector = Selector;
|
|
33
39
|
_Selector_ruleset = new WeakMap();
|
|
34
40
|
class Ruleset {
|
|
35
41
|
static parse(selector, extended) {
|
|
36
42
|
const selectors = [];
|
|
37
43
|
try {
|
|
38
|
-
(
|
|
44
|
+
parser(root => {
|
|
39
45
|
selectors.push(...root.nodes);
|
|
40
46
|
}).processSync(selector);
|
|
41
47
|
}
|
|
42
48
|
catch (e) {
|
|
43
49
|
if (e instanceof Error) {
|
|
44
|
-
throw new
|
|
50
|
+
throw new InvalidSelectorError(selector);
|
|
45
51
|
}
|
|
46
52
|
throw e;
|
|
47
53
|
}
|
|
@@ -49,21 +55,28 @@ class Ruleset {
|
|
|
49
55
|
}
|
|
50
56
|
constructor(selectors, extended, depth) {
|
|
51
57
|
_Ruleset_selectorGroup.set(this, []);
|
|
52
|
-
|
|
53
|
-
const head =
|
|
54
|
-
this.headCombinator =
|
|
58
|
+
__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f").push(...selectors.map(selector => new StructuredSelector(selector, depth, extended)));
|
|
59
|
+
const head = __classPrivateFieldGet(this, _Ruleset_selectorGroup, "f")[0];
|
|
60
|
+
this.headCombinator = head?.headCombinator ?? null;
|
|
55
61
|
if (this.headCombinator) {
|
|
56
62
|
if (depth <= 0) {
|
|
57
|
-
|
|
63
|
+
if (__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f")[0]?.selector) {
|
|
64
|
+
throw new InvalidSelectorError(__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f")[0]?.selector);
|
|
65
|
+
}
|
|
66
|
+
throw new Error('Combinated selector depth is not expected');
|
|
58
67
|
}
|
|
59
68
|
}
|
|
60
69
|
}
|
|
61
|
-
match(
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
match(
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
72
|
+
el,
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
74
|
+
scope) {
|
|
75
|
+
coreLog('<%s> (%s)', isElement(el) ? el.localName : el.nodeName, scope ? (isElement(scope) ? scope.localName : scope.nodeName) : null);
|
|
76
|
+
return __classPrivateFieldGet(this, _Ruleset_selectorGroup, "f").map(selector => {
|
|
64
77
|
selLog('"%s"', selector.selector);
|
|
65
78
|
const res = selector.match(el, scope);
|
|
66
|
-
resLog('%s "%s" => %o',
|
|
79
|
+
resLog('%s "%s" => %o', isElement(el) ? el.localName : el.nodeName, selector.selector, res);
|
|
67
80
|
return res;
|
|
68
81
|
});
|
|
69
82
|
}
|
|
@@ -73,19 +86,21 @@ class StructuredSelector {
|
|
|
73
86
|
constructor(selector, depth, extended) {
|
|
74
87
|
_StructuredSelector_edge.set(this, void 0);
|
|
75
88
|
_StructuredSelector_selector.set(this, void 0);
|
|
76
|
-
|
|
77
|
-
|
|
89
|
+
__classPrivateFieldSet(this, _StructuredSelector_selector, selector, "f");
|
|
90
|
+
__classPrivateFieldSet(this, _StructuredSelector_edge, new SelectorTarget(extended, depth), "f");
|
|
78
91
|
this.headCombinator =
|
|
79
|
-
|
|
92
|
+
__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes[0]?.type === 'combinator' ? __classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes[0].value ?? null : null;
|
|
93
|
+
const nodes = __classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes.slice();
|
|
80
94
|
if (0 < depth && this.headCombinator) {
|
|
81
|
-
|
|
95
|
+
// eslint-disable-next-line import/no-named-as-default-member
|
|
96
|
+
nodes.unshift(parser.pseudo({ value: ':scope' }));
|
|
82
97
|
}
|
|
83
|
-
|
|
98
|
+
nodes.forEach(node => {
|
|
84
99
|
switch (node.type) {
|
|
85
100
|
case 'combinator': {
|
|
86
101
|
const combinedTarget = new SelectorTarget(extended, depth);
|
|
87
|
-
combinedTarget.from(
|
|
88
|
-
|
|
102
|
+
combinedTarget.from(__classPrivateFieldGet(this, _StructuredSelector_edge, "f"), node);
|
|
103
|
+
__classPrivateFieldSet(this, _StructuredSelector_edge, combinedTarget, "f");
|
|
89
104
|
break;
|
|
90
105
|
}
|
|
91
106
|
case 'root':
|
|
@@ -99,16 +114,20 @@ class StructuredSelector {
|
|
|
99
114
|
throw new Error(`Unsupported comment in selector: ${selector.toString()}`);
|
|
100
115
|
}
|
|
101
116
|
default: {
|
|
102
|
-
|
|
117
|
+
__classPrivateFieldGet(this, _StructuredSelector_edge, "f").add(node);
|
|
103
118
|
}
|
|
104
119
|
}
|
|
105
120
|
});
|
|
106
121
|
}
|
|
107
122
|
get selector() {
|
|
108
|
-
return
|
|
123
|
+
return __classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes.join('');
|
|
109
124
|
}
|
|
110
|
-
match(
|
|
111
|
-
|
|
125
|
+
match(
|
|
126
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
127
|
+
el,
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
129
|
+
scope) {
|
|
130
|
+
return __classPrivateFieldGet(this, _StructuredSelector_edge, "f").match(el, scope, 0);
|
|
112
131
|
}
|
|
113
132
|
}
|
|
114
133
|
_StructuredSelector_edge = new WeakMap(), _StructuredSelector_selector = new WeakMap();
|
|
@@ -122,11 +141,11 @@ class SelectorTarget {
|
|
|
122
141
|
_SelectorTarget_isAdded.set(this, false);
|
|
123
142
|
this.pseudo = [];
|
|
124
143
|
this.tag = null;
|
|
125
|
-
|
|
144
|
+
__classPrivateFieldSet(this, _SelectorTarget_extended, extended, "f");
|
|
126
145
|
this.depth = depth;
|
|
127
146
|
}
|
|
128
147
|
add(selector) {
|
|
129
|
-
|
|
148
|
+
__classPrivateFieldSet(this, _SelectorTarget_isAdded, true, "f");
|
|
130
149
|
switch (selector.type) {
|
|
131
150
|
case 'tag':
|
|
132
151
|
case 'universal': {
|
|
@@ -152,45 +171,51 @@ class SelectorTarget {
|
|
|
152
171
|
}
|
|
153
172
|
}
|
|
154
173
|
from(target, combinator) {
|
|
155
|
-
|
|
174
|
+
__classPrivateFieldSet(this, _SelectorTarget_combinedFrom, { target, combinator }, "f");
|
|
156
175
|
}
|
|
157
|
-
match(
|
|
158
|
-
|
|
176
|
+
match(
|
|
177
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
178
|
+
el,
|
|
179
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
180
|
+
scope, count) {
|
|
159
181
|
const result = this._match(el, scope, count);
|
|
160
182
|
if (selLog.enabled) {
|
|
161
183
|
const nodeName = el.nodeName;
|
|
162
|
-
const selector =
|
|
184
|
+
const selector = __classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f")?.target.toString() ?? this.toString();
|
|
163
185
|
const combinator = result.combinator ? ` ${result.combinator}` : '';
|
|
164
186
|
selLog('The %s element by "%s" => %s (%d)', nodeName, `${selector}${combinator}`, result.matched, count);
|
|
165
187
|
if (selector === ':scope') {
|
|
166
|
-
selLog(`† Scope is the ${
|
|
188
|
+
selLog(`† Scope is the ${scope?.nodeName ?? null}`);
|
|
167
189
|
}
|
|
168
190
|
}
|
|
169
191
|
delete result.combinator;
|
|
170
192
|
return result;
|
|
171
193
|
}
|
|
172
194
|
toString() {
|
|
173
|
-
var _a, _b;
|
|
174
195
|
return [
|
|
175
|
-
|
|
196
|
+
this.tag?.toString() ?? '',
|
|
176
197
|
this.id.map(id => `#${id.value}`).join(''),
|
|
177
198
|
this.class.map(c => `.${c.value}`).join(''),
|
|
178
199
|
this.attr.map(attr => `[${attr.toString()}]`).join(''),
|
|
179
200
|
this.pseudo.map(pseudo => pseudo.value).join(''),
|
|
180
201
|
].join('');
|
|
181
202
|
}
|
|
182
|
-
_match(
|
|
203
|
+
_match(
|
|
204
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
205
|
+
el,
|
|
206
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
207
|
+
scope, count) {
|
|
183
208
|
const unitCheck = this._matchWithoutCombineChecking(el, scope);
|
|
184
209
|
if (!unitCheck.matched) {
|
|
185
210
|
return unitCheck;
|
|
186
211
|
}
|
|
187
|
-
if (!
|
|
212
|
+
if (!__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f")) {
|
|
188
213
|
return unitCheck;
|
|
189
214
|
}
|
|
190
|
-
if (!
|
|
215
|
+
if (!isNonDocumentTypeChildNode(el)) {
|
|
191
216
|
return unitCheck;
|
|
192
217
|
}
|
|
193
|
-
const { target, combinator } =
|
|
218
|
+
const { target, combinator } = __classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f");
|
|
194
219
|
switch (combinator.value) {
|
|
195
220
|
// Descendant combinator
|
|
196
221
|
case ' ': {
|
|
@@ -198,7 +223,7 @@ class SelectorTarget {
|
|
|
198
223
|
const has = [];
|
|
199
224
|
const not = [];
|
|
200
225
|
let ancestor = el.parentElement;
|
|
201
|
-
let specificity;
|
|
226
|
+
let specificity = undefined;
|
|
202
227
|
while (ancestor) {
|
|
203
228
|
const res = target.match(ancestor, scope, count + 1);
|
|
204
229
|
if (!specificity) {
|
|
@@ -227,7 +252,7 @@ class SelectorTarget {
|
|
|
227
252
|
unitCheck.specificity[2] + res.specificity[2],
|
|
228
253
|
];
|
|
229
254
|
}
|
|
230
|
-
if (matchedNodes.length) {
|
|
255
|
+
if (matchedNodes.length > 0) {
|
|
231
256
|
return {
|
|
232
257
|
combinator: '␣',
|
|
233
258
|
specificity,
|
|
@@ -248,7 +273,7 @@ class SelectorTarget {
|
|
|
248
273
|
const matchedNodes = [];
|
|
249
274
|
const has = [];
|
|
250
275
|
const not = [];
|
|
251
|
-
const specificity = unitCheck.specificity;
|
|
276
|
+
const specificity = [...unitCheck.specificity];
|
|
252
277
|
const parentNode = el.parentElement;
|
|
253
278
|
if (parentNode) {
|
|
254
279
|
const res = target.match(parentNode, scope, count + 1);
|
|
@@ -271,7 +296,7 @@ class SelectorTarget {
|
|
|
271
296
|
specificity[1] += res.specificity[1];
|
|
272
297
|
specificity[2] += res.specificity[2];
|
|
273
298
|
}
|
|
274
|
-
if (matchedNodes.length) {
|
|
299
|
+
if (matchedNodes.length > 0) {
|
|
275
300
|
return {
|
|
276
301
|
combinator: '>',
|
|
277
302
|
specificity,
|
|
@@ -292,7 +317,7 @@ class SelectorTarget {
|
|
|
292
317
|
const matchedNodes = [];
|
|
293
318
|
const has = [];
|
|
294
319
|
const not = [];
|
|
295
|
-
const specificity = unitCheck.specificity;
|
|
320
|
+
const specificity = [...unitCheck.specificity];
|
|
296
321
|
if (el.previousElementSibling) {
|
|
297
322
|
const res = target.match(el.previousElementSibling, scope, count + 1);
|
|
298
323
|
specificity[0] += res.specificity[0];
|
|
@@ -314,7 +339,7 @@ class SelectorTarget {
|
|
|
314
339
|
specificity[1] += res.specificity[1];
|
|
315
340
|
specificity[2] += res.specificity[2];
|
|
316
341
|
}
|
|
317
|
-
if (matchedNodes.length) {
|
|
342
|
+
if (matchedNodes.length > 0) {
|
|
318
343
|
return {
|
|
319
344
|
combinator: '+',
|
|
320
345
|
specificity,
|
|
@@ -336,7 +361,7 @@ class SelectorTarget {
|
|
|
336
361
|
const has = [];
|
|
337
362
|
const not = [];
|
|
338
363
|
let prev = el.previousElementSibling;
|
|
339
|
-
let specificity;
|
|
364
|
+
let specificity = undefined;
|
|
340
365
|
while (prev) {
|
|
341
366
|
const res = target.match(prev, scope, count + 1);
|
|
342
367
|
if (!specificity) {
|
|
@@ -365,7 +390,7 @@ class SelectorTarget {
|
|
|
365
390
|
unitCheck.specificity[2] + res.specificity[2],
|
|
366
391
|
];
|
|
367
392
|
}
|
|
368
|
-
if (matchedNodes.length) {
|
|
393
|
+
if (matchedNodes.length > 0) {
|
|
369
394
|
return {
|
|
370
395
|
combinator: '~',
|
|
371
396
|
specificity,
|
|
@@ -386,14 +411,17 @@ class SelectorTarget {
|
|
|
386
411
|
throw new Error('Unsupported column combinator yet. If you want it, please request it as the issue (https://github.com/markuplint/markuplint/issues/new).');
|
|
387
412
|
}
|
|
388
413
|
default: {
|
|
389
|
-
throw new Error(`Unsupported ${
|
|
414
|
+
throw new Error(`Unsupported ${__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f").combinator.value} combinator in selector`);
|
|
390
415
|
}
|
|
391
416
|
}
|
|
392
417
|
}
|
|
393
|
-
_matchWithoutCombineChecking(
|
|
394
|
-
|
|
418
|
+
_matchWithoutCombineChecking(
|
|
419
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
420
|
+
el,
|
|
421
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
422
|
+
scope) {
|
|
395
423
|
const specificity = [0, 0, 0];
|
|
396
|
-
if (!
|
|
424
|
+
if (!isElement(el)) {
|
|
397
425
|
return {
|
|
398
426
|
specificity,
|
|
399
427
|
matched: false,
|
|
@@ -420,12 +448,12 @@ class SelectorTarget {
|
|
|
420
448
|
break;
|
|
421
449
|
}
|
|
422
450
|
default: {
|
|
423
|
-
throw new
|
|
451
|
+
throw new InvalidSelectorError(`The ${namespace} namespace is not supported`);
|
|
424
452
|
}
|
|
425
453
|
}
|
|
426
454
|
}
|
|
427
455
|
let matched = true;
|
|
428
|
-
if (!
|
|
456
|
+
if (!__classPrivateFieldGet(this, _SelectorTarget_isAdded, "f") && !isScope(el, scope)) {
|
|
429
457
|
matched = false;
|
|
430
458
|
}
|
|
431
459
|
if (!this.id.every(id => id.value === el.id)) {
|
|
@@ -441,7 +469,7 @@ class SelectorTarget {
|
|
|
441
469
|
}
|
|
442
470
|
specificity[1] += this.attr.length;
|
|
443
471
|
for (const pseudo of this.pseudo) {
|
|
444
|
-
const pseudoRes = pseudoMatch(pseudo, el, scope,
|
|
472
|
+
const pseudoRes = pseudoMatch(pseudo, el, scope, __classPrivateFieldGet(this, _SelectorTarget_extended, "f"), this.depth);
|
|
445
473
|
specificity[0] += pseudoRes.specificity[0];
|
|
446
474
|
specificity[1] += pseudoRes.specificity[1];
|
|
447
475
|
specificity[2] += pseudoRes.specificity[2];
|
|
@@ -449,7 +477,7 @@ class SelectorTarget {
|
|
|
449
477
|
has.push(...pseudoRes.has);
|
|
450
478
|
}
|
|
451
479
|
else {
|
|
452
|
-
not.push(...(
|
|
480
|
+
not.push(...(pseudoRes.not ?? []));
|
|
453
481
|
matched = false;
|
|
454
482
|
}
|
|
455
483
|
}
|
|
@@ -457,7 +485,7 @@ class SelectorTarget {
|
|
|
457
485
|
specificity[2] += 1;
|
|
458
486
|
let a = this.tag.value;
|
|
459
487
|
let b = el.localName;
|
|
460
|
-
if (
|
|
488
|
+
if (isPureHTMLElement(el)) {
|
|
461
489
|
a = a.toLowerCase();
|
|
462
490
|
b = b.toLowerCase();
|
|
463
491
|
}
|
|
@@ -481,13 +509,15 @@ class SelectorTarget {
|
|
|
481
509
|
}
|
|
482
510
|
}
|
|
483
511
|
_SelectorTarget_combinedFrom = new WeakMap(), _SelectorTarget_extended = new WeakMap(), _SelectorTarget_isAdded = new WeakMap();
|
|
484
|
-
function attrMatch(attr,
|
|
512
|
+
function attrMatch(attr,
|
|
513
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
514
|
+
el) {
|
|
485
515
|
return Array.from(el.attributes).some(attrOfEl => {
|
|
486
516
|
if (attr.attribute !== attrOfEl.localName) {
|
|
487
517
|
return false;
|
|
488
518
|
}
|
|
489
519
|
if (attr.namespace != null && attr.namespace !== true && attr.namespace !== '*') {
|
|
490
|
-
const ns =
|
|
520
|
+
const ns = resolveNamespace(attrOfEl.localName, attrOfEl.namespaceURI);
|
|
491
521
|
if (attr.namespace !== ns.namespace) {
|
|
492
522
|
return false;
|
|
493
523
|
}
|
|
@@ -519,7 +549,7 @@ function attrMatch(attr, el) {
|
|
|
519
549
|
break;
|
|
520
550
|
}
|
|
521
551
|
case '*=': {
|
|
522
|
-
if (valueOfEl.
|
|
552
|
+
if (!valueOfEl.includes(value)) {
|
|
523
553
|
return false;
|
|
524
554
|
}
|
|
525
555
|
break;
|
|
@@ -541,7 +571,11 @@ function attrMatch(attr, el) {
|
|
|
541
571
|
return true;
|
|
542
572
|
});
|
|
543
573
|
}
|
|
544
|
-
function pseudoMatch(pseudo,
|
|
574
|
+
function pseudoMatch(pseudo,
|
|
575
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
576
|
+
el,
|
|
577
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
578
|
+
scope, extended, depth) {
|
|
545
579
|
switch (pseudo.value) {
|
|
546
580
|
//
|
|
547
581
|
/**
|
|
@@ -553,7 +587,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
553
587
|
let parent = el.parentElement;
|
|
554
588
|
while (parent) {
|
|
555
589
|
const matched = ruleset.match(parent, scope).filter((r) => r.matched);
|
|
556
|
-
if (matched.length) {
|
|
590
|
+
if (matched.length > 0) {
|
|
557
591
|
return {
|
|
558
592
|
specificity,
|
|
559
593
|
matched: true,
|
|
@@ -597,7 +631,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
597
631
|
const matched = resList.filter((r) => r.matched);
|
|
598
632
|
return {
|
|
599
633
|
specificity,
|
|
600
|
-
matched:
|
|
634
|
+
matched: matched.length > 0,
|
|
601
635
|
nodes: matched.map(m => m.nodes).flat(),
|
|
602
636
|
has: matched.map(m => m.has).flat(),
|
|
603
637
|
};
|
|
@@ -611,7 +645,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
611
645
|
const has = getSiblings(el)
|
|
612
646
|
.map(sib => ruleset.match(sib, el).filter((m) => m.matched))
|
|
613
647
|
.flat();
|
|
614
|
-
if (has.length) {
|
|
648
|
+
if (has.length > 0) {
|
|
615
649
|
return {
|
|
616
650
|
specificity,
|
|
617
651
|
matched: true,
|
|
@@ -628,7 +662,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
628
662
|
const has = getDescendants(el)
|
|
629
663
|
.map(sib => ruleset.match(sib, el).filter((m) => m.matched))
|
|
630
664
|
.flat();
|
|
631
|
-
if (has.length) {
|
|
665
|
+
if (has.length > 0) {
|
|
632
666
|
return {
|
|
633
667
|
specificity,
|
|
634
668
|
matched: true,
|
|
@@ -649,7 +683,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
649
683
|
const matched = resList.filter((r) => r.matched);
|
|
650
684
|
return {
|
|
651
685
|
specificity: [0, 0, 0],
|
|
652
|
-
matched:
|
|
686
|
+
matched: matched.length > 0,
|
|
653
687
|
nodes: matched.map(m => m.nodes).flat(),
|
|
654
688
|
has: matched.map(m => m.has).flat(),
|
|
655
689
|
};
|
|
@@ -738,6 +772,9 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
738
772
|
}
|
|
739
773
|
const content = pseudo.nodes.map(node => node.toString()).join('');
|
|
740
774
|
const hook = extended[ext];
|
|
775
|
+
if (!hook) {
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
741
778
|
const matcher = hook(content);
|
|
742
779
|
return matcher(el);
|
|
743
780
|
}
|
|
@@ -745,10 +782,16 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
745
782
|
}
|
|
746
783
|
}
|
|
747
784
|
}
|
|
748
|
-
function isScope(
|
|
749
|
-
|
|
785
|
+
function isScope(
|
|
786
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
787
|
+
el,
|
|
788
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
789
|
+
scope) {
|
|
790
|
+
return el === scope ?? el.parentNode === null;
|
|
750
791
|
}
|
|
751
|
-
function getDescendants(
|
|
792
|
+
function getDescendants(
|
|
793
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
794
|
+
el, includeSelf = false) {
|
|
752
795
|
return [
|
|
753
796
|
...Array.from(el.children)
|
|
754
797
|
.map(child => getDescendants(child, true))
|
|
@@ -756,15 +799,18 @@ function getDescendants(el, includeSelf = false) {
|
|
|
756
799
|
...(includeSelf ? [el] : []),
|
|
757
800
|
];
|
|
758
801
|
}
|
|
759
|
-
function getSiblings(
|
|
760
|
-
|
|
761
|
-
|
|
802
|
+
function getSiblings(
|
|
803
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
804
|
+
el) {
|
|
805
|
+
return Array.from(el.parentElement?.children ?? []);
|
|
762
806
|
}
|
|
763
|
-
function getSpecificity(
|
|
764
|
-
|
|
807
|
+
function getSpecificity(
|
|
808
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
809
|
+
results) {
|
|
810
|
+
let specificity = undefined;
|
|
765
811
|
for (const result of results) {
|
|
766
812
|
if (specificity) {
|
|
767
|
-
const order =
|
|
813
|
+
const order = compareSpecificity(specificity, result.specificity);
|
|
768
814
|
if (order === -1) {
|
|
769
815
|
specificity = result.specificity;
|
|
770
816
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
export type Specificity = [number, number, number];
|
|
1
|
+
export type Specificity = readonly [number, number, number];
|
|
2
2
|
export type SelectorResult = SelectorMatchedResult | SelectorUnmatchedResult;
|
|
3
3
|
export type SelectorMatchedResult = {
|
|
4
|
-
specificity: Specificity;
|
|
5
|
-
matched: true;
|
|
6
|
-
nodes: (Element | Text)[];
|
|
7
|
-
has: SelectorMatchedResult[];
|
|
4
|
+
readonly specificity: Specificity;
|
|
5
|
+
readonly matched: true;
|
|
6
|
+
readonly nodes: readonly (Element | Text)[];
|
|
7
|
+
readonly has: readonly SelectorMatchedResult[];
|
|
8
8
|
};
|
|
9
9
|
export type SelectorUnmatchedResult = {
|
|
10
|
-
specificity: Specificity;
|
|
11
|
-
matched: false;
|
|
12
|
-
not?: SelectorMatchedResult[];
|
|
10
|
+
readonly specificity: Specificity;
|
|
11
|
+
readonly matched: false;
|
|
12
|
+
readonly not?: readonly SelectorMatchedResult[];
|
|
13
13
|
};
|
|
14
14
|
export type RegexSelector = RegexSelectorWithoutCombination & {
|
|
15
|
-
combination?: {
|
|
16
|
-
combinator: RegexSelectorCombinator;
|
|
15
|
+
readonly combination?: {
|
|
16
|
+
readonly combinator: RegexSelectorCombinator;
|
|
17
17
|
} & RegexSelector;
|
|
18
18
|
};
|
|
19
19
|
export type RegexSelectorCombinator = ' ' | '>' | '+' | '~' | ':has(+)' | ':has(~)';
|
|
20
20
|
export type RegexSelectorWithoutCombination = {
|
|
21
|
-
nodeName?: string;
|
|
22
|
-
attrName?: string;
|
|
23
|
-
attrValue?: string;
|
|
21
|
+
readonly nodeName?: string;
|
|
22
|
+
readonly attrName?: string;
|
|
23
|
+
readonly attrValue?: string;
|
|
24
24
|
};
|
package/lib/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,31 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/selector",
|
|
3
|
-
"version": "3.0.0-dev.
|
|
3
|
+
"version": "3.0.0-dev.290+af676442",
|
|
4
4
|
"description": "Extended W3C Selectors matcher",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"private": false,
|
|
9
|
-
"
|
|
9
|
+
"type": "module",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./lib/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
10
15
|
"types": "lib/index.d.ts",
|
|
11
16
|
"publishConfig": {
|
|
12
17
|
"access": "public"
|
|
13
18
|
},
|
|
19
|
+
"typedoc": {
|
|
20
|
+
"entryPoint": "./src/index.ts"
|
|
21
|
+
},
|
|
14
22
|
"scripts": {
|
|
15
23
|
"build": "tsc",
|
|
16
24
|
"dev": "tsc --build --watch",
|
|
17
25
|
"clean": "tsc --build --clean"
|
|
18
26
|
},
|
|
19
27
|
"dependencies": {
|
|
28
|
+
"@markuplint/ml-spec": "3.0.0-dev.290+af676442",
|
|
29
|
+
"@types/debug": "^4.1.9",
|
|
20
30
|
"debug": "^4.3.4",
|
|
21
|
-
"postcss-selector-parser": "^6.0.
|
|
22
|
-
"tslib": "^2.
|
|
31
|
+
"postcss-selector-parser": "^6.0.13",
|
|
32
|
+
"tslib": "^2.6.2",
|
|
33
|
+
"type-fest": "^4.3.1"
|
|
23
34
|
},
|
|
24
35
|
"devDependencies": {
|
|
25
|
-
"@
|
|
26
|
-
"
|
|
27
|
-
"@types/jsdom": "16",
|
|
28
|
-
"jsdom": "19"
|
|
36
|
+
"@types/jsdom": "21.1.3",
|
|
37
|
+
"jsdom": "22.1.0"
|
|
29
38
|
},
|
|
30
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "af6764422feecb56d1d84659028f53daf685bb78"
|
|
31
40
|
}
|
package/tsconfig.test.json
DELETED