@markuplint/selector 3.0.0-alpha.2105 → 3.0.0-alpha.3
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 +29 -9
- package/lib/create-selector.js +5 -1
- package/lib/extended-selector/aria-pseudo-class.d.ts +4 -2
- package/lib/extended-selector/aria-pseudo-class.js +23 -25
- package/lib/extended-selector/aria-role-pseudo-class.d.ts +3 -0
- package/lib/extended-selector/aria-role-pseudo-class.js +32 -0
- package/lib/extended-selector/content-model-pseudo-class.d.ts +3 -0
- package/lib/extended-selector/content-model-pseudo-class.js +57 -0
- package/lib/match-selector.js +14 -10
- package/lib/regex-selector-matches.js +2 -2
- package/lib/selector.d.ts +1 -0
- package/lib/selector.js +211 -63
- package/lib/types.d.ts +12 -4
- package/package.json +5 -5
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/is-pure-html-element.d.ts +0 -1
- package/lib/is-pure-html-element.js +0 -7
- package/lib/utils/is-pure-html-element.d.ts +0 -1
- package/lib/utils/is-pure-html-element.js +0 -7
package/lib/selector.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var _Selector_ruleset, _Ruleset_selectorGroup, _StructuredSelector_selector,
|
|
2
|
+
var _Selector_ruleset, _Ruleset_selectorGroup, _StructuredSelector_edge, _StructuredSelector_selector, _SelectorTarget_combinedFrom, _SelectorTarget_extended, _SelectorTarget_isAdded;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.Selector = void 0;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
|
+
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
6
7
|
const postcss_selector_parser_1 = tslib_1.__importStar(require("postcss-selector-parser"));
|
|
7
8
|
const compare_specificity_1 = require("./compare-specificity");
|
|
8
9
|
const debug_1 = require("./debug");
|
|
@@ -16,7 +17,7 @@ class Selector {
|
|
|
16
17
|
tslib_1.__classPrivateFieldSet(this, _Selector_ruleset, Ruleset.parse(selector, extended), "f");
|
|
17
18
|
}
|
|
18
19
|
match(el, scope = (0, is_1.isElement)(el) ? el : null) {
|
|
19
|
-
const results =
|
|
20
|
+
const results = this.search(el, scope);
|
|
20
21
|
for (const result of results) {
|
|
21
22
|
if (result.matched) {
|
|
22
23
|
return result.specificity;
|
|
@@ -24,6 +25,9 @@ class Selector {
|
|
|
24
25
|
}
|
|
25
26
|
return false;
|
|
26
27
|
}
|
|
28
|
+
search(el, scope = (0, is_1.isElement)(el) ? el : null) {
|
|
29
|
+
return tslib_1.__classPrivateFieldGet(this, _Selector_ruleset, "f").match(el, scope);
|
|
30
|
+
}
|
|
27
31
|
}
|
|
28
32
|
exports.Selector = Selector;
|
|
29
33
|
_Selector_ruleset = new WeakMap();
|
|
@@ -41,9 +45,17 @@ class Ruleset {
|
|
|
41
45
|
}
|
|
42
46
|
static parse(selector, extended) {
|
|
43
47
|
const selectors = [];
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
try {
|
|
49
|
+
(0, postcss_selector_parser_1.default)(root => {
|
|
50
|
+
selectors.push(...root.nodes);
|
|
51
|
+
}).processSync(selector);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
if (e instanceof Error) {
|
|
55
|
+
throw new Error(`${e.message} At the selector: "${selector}"`);
|
|
56
|
+
}
|
|
57
|
+
throw e;
|
|
58
|
+
}
|
|
47
59
|
return new Ruleset(selectors, extended, 0);
|
|
48
60
|
}
|
|
49
61
|
match(el, scope) {
|
|
@@ -59,8 +71,8 @@ class Ruleset {
|
|
|
59
71
|
_Ruleset_selectorGroup = new WeakMap();
|
|
60
72
|
class StructuredSelector {
|
|
61
73
|
constructor(selector, depth, extended) {
|
|
62
|
-
_StructuredSelector_selector.set(this, void 0);
|
|
63
74
|
_StructuredSelector_edge.set(this, void 0);
|
|
75
|
+
_StructuredSelector_selector.set(this, void 0);
|
|
64
76
|
tslib_1.__classPrivateFieldSet(this, _StructuredSelector_selector, selector, "f");
|
|
65
77
|
tslib_1.__classPrivateFieldSet(this, _StructuredSelector_edge, new SelectorTarget(extended, depth), "f");
|
|
66
78
|
this.headCombinator =
|
|
@@ -71,9 +83,9 @@ class StructuredSelector {
|
|
|
71
83
|
tslib_1.__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes.forEach(node => {
|
|
72
84
|
switch (node.type) {
|
|
73
85
|
case 'combinator': {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
tslib_1.__classPrivateFieldSet(this, _StructuredSelector_edge,
|
|
86
|
+
const combinedTarget = new SelectorTarget(extended, depth);
|
|
87
|
+
combinedTarget.from(tslib_1.__classPrivateFieldGet(this, _StructuredSelector_edge, "f"), node);
|
|
88
|
+
tslib_1.__classPrivateFieldSet(this, _StructuredSelector_edge, combinedTarget, "f");
|
|
77
89
|
break;
|
|
78
90
|
}
|
|
79
91
|
case 'root':
|
|
@@ -99,15 +111,15 @@ class StructuredSelector {
|
|
|
99
111
|
return tslib_1.__classPrivateFieldGet(this, _StructuredSelector_edge, "f").match(el, scope, 0);
|
|
100
112
|
}
|
|
101
113
|
}
|
|
102
|
-
|
|
114
|
+
_StructuredSelector_edge = new WeakMap(), _StructuredSelector_selector = new WeakMap();
|
|
103
115
|
class SelectorTarget {
|
|
104
116
|
constructor(extended, depth) {
|
|
105
|
-
_SelectorTarget_extended.set(this, void 0);
|
|
106
|
-
_SelectorTarget_combinatedFrom.set(this, null);
|
|
107
|
-
_SelectorTarget_isAdded.set(this, false);
|
|
108
117
|
this.attr = [];
|
|
109
118
|
this.class = [];
|
|
119
|
+
_SelectorTarget_combinedFrom.set(this, null);
|
|
120
|
+
_SelectorTarget_extended.set(this, void 0);
|
|
110
121
|
this.id = [];
|
|
122
|
+
_SelectorTarget_isAdded.set(this, false);
|
|
111
123
|
this.pseudo = [];
|
|
112
124
|
this.tag = null;
|
|
113
125
|
tslib_1.__classPrivateFieldSet(this, _SelectorTarget_extended, extended, "f");
|
|
@@ -140,14 +152,14 @@ class SelectorTarget {
|
|
|
140
152
|
}
|
|
141
153
|
}
|
|
142
154
|
from(target, combinator) {
|
|
143
|
-
tslib_1.__classPrivateFieldSet(this,
|
|
155
|
+
tslib_1.__classPrivateFieldSet(this, _SelectorTarget_combinedFrom, { target, combinator }, "f");
|
|
144
156
|
}
|
|
145
157
|
match(el, scope, count) {
|
|
146
158
|
var _a;
|
|
147
159
|
const result = this._match(el, scope, count);
|
|
148
160
|
if (selLog.enabled) {
|
|
149
161
|
const nodeName = el.nodeName;
|
|
150
|
-
const selector = ((_a = tslib_1.__classPrivateFieldGet(this,
|
|
162
|
+
const selector = ((_a = tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f")) === null || _a === void 0 ? void 0 : _a.target.toString()) || this.toString();
|
|
151
163
|
const combinator = result.combinator ? ` ${result.combinator}` : '';
|
|
152
164
|
selLog('The %s element by "%s" => %s (%d)', nodeName, `${selector}${combinator}`, result.matched, count);
|
|
153
165
|
if (selector === ':scope') {
|
|
@@ -157,23 +169,35 @@ class SelectorTarget {
|
|
|
157
169
|
delete result.combinator;
|
|
158
170
|
return result;
|
|
159
171
|
}
|
|
172
|
+
toString() {
|
|
173
|
+
var _a, _b;
|
|
174
|
+
return [
|
|
175
|
+
(_b = (_a = this.tag) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '',
|
|
176
|
+
this.id.map(id => `#${id.value}`).join(''),
|
|
177
|
+
this.class.map(c => `.${c.value}`).join(''),
|
|
178
|
+
this.attr.map(attr => `[${attr.toString()}]`).join(''),
|
|
179
|
+
this.pseudo.map(pseudo => pseudo.value).join(''),
|
|
180
|
+
].join('');
|
|
181
|
+
}
|
|
160
182
|
_match(el, scope, count) {
|
|
161
|
-
const unitCheck = this.
|
|
183
|
+
const unitCheck = this._matchWithoutCombineChecking(el, scope);
|
|
162
184
|
if (!unitCheck.matched) {
|
|
163
185
|
return unitCheck;
|
|
164
186
|
}
|
|
165
|
-
if (!tslib_1.__classPrivateFieldGet(this,
|
|
187
|
+
if (!tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f")) {
|
|
166
188
|
return unitCheck;
|
|
167
189
|
}
|
|
168
190
|
if (!(0, is_1.isNonDocumentTypeChildNode)(el)) {
|
|
169
191
|
return unitCheck;
|
|
170
192
|
}
|
|
171
|
-
const { target, combinator } = tslib_1.__classPrivateFieldGet(this,
|
|
193
|
+
const { target, combinator } = tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f");
|
|
172
194
|
switch (combinator.value) {
|
|
173
195
|
// Descendant combinator
|
|
174
196
|
case ' ': {
|
|
197
|
+
const matchedNodes = [];
|
|
198
|
+
const has = [];
|
|
199
|
+
const not = [];
|
|
175
200
|
let ancestor = el.parentElement;
|
|
176
|
-
let matched = false;
|
|
177
201
|
let specificity;
|
|
178
202
|
while (ancestor) {
|
|
179
203
|
const res = target.match(ancestor, scope, count + 1);
|
|
@@ -185,7 +209,13 @@ class SelectorTarget {
|
|
|
185
209
|
];
|
|
186
210
|
}
|
|
187
211
|
if (res.matched) {
|
|
188
|
-
|
|
212
|
+
matchedNodes.push(...res.nodes);
|
|
213
|
+
has.push(...res.has);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
if (res.not) {
|
|
217
|
+
not.push(...res.not);
|
|
218
|
+
}
|
|
189
219
|
}
|
|
190
220
|
ancestor = ancestor.parentElement;
|
|
191
221
|
}
|
|
@@ -197,15 +227,27 @@ class SelectorTarget {
|
|
|
197
227
|
unitCheck.specificity[2] + res.specificity[2],
|
|
198
228
|
];
|
|
199
229
|
}
|
|
230
|
+
if (matchedNodes.length) {
|
|
231
|
+
return {
|
|
232
|
+
combinator: '␣',
|
|
233
|
+
specificity,
|
|
234
|
+
matched: true,
|
|
235
|
+
nodes: matchedNodes,
|
|
236
|
+
has,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
200
239
|
return {
|
|
201
240
|
combinator: '␣',
|
|
202
241
|
specificity,
|
|
203
|
-
matched,
|
|
242
|
+
matched: false,
|
|
243
|
+
not,
|
|
204
244
|
};
|
|
205
245
|
}
|
|
206
246
|
// Child combinator
|
|
207
247
|
case '>': {
|
|
208
|
-
|
|
248
|
+
const matchedNodes = [];
|
|
249
|
+
const has = [];
|
|
250
|
+
const not = [];
|
|
209
251
|
const specificity = unitCheck.specificity;
|
|
210
252
|
const parentNode = el.parentElement;
|
|
211
253
|
if (parentNode) {
|
|
@@ -213,49 +255,87 @@ class SelectorTarget {
|
|
|
213
255
|
specificity[0] += res.specificity[0];
|
|
214
256
|
specificity[1] += res.specificity[1];
|
|
215
257
|
specificity[2] += res.specificity[2];
|
|
216
|
-
|
|
258
|
+
if (res.matched) {
|
|
259
|
+
matchedNodes.push(...res.nodes);
|
|
260
|
+
has.push(...res.has);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
if (res.not) {
|
|
264
|
+
not.push(...res.not);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
217
267
|
}
|
|
218
268
|
else {
|
|
219
269
|
const res = target.match(el, scope, count + 1);
|
|
220
270
|
specificity[0] += res.specificity[0];
|
|
221
271
|
specificity[1] += res.specificity[1];
|
|
222
272
|
specificity[2] += res.specificity[2];
|
|
223
|
-
|
|
273
|
+
}
|
|
274
|
+
if (matchedNodes.length) {
|
|
275
|
+
return {
|
|
276
|
+
combinator: '>',
|
|
277
|
+
specificity,
|
|
278
|
+
matched: true,
|
|
279
|
+
nodes: matchedNodes,
|
|
280
|
+
has,
|
|
281
|
+
};
|
|
224
282
|
}
|
|
225
283
|
return {
|
|
226
284
|
combinator: '>',
|
|
227
285
|
specificity,
|
|
228
|
-
matched,
|
|
286
|
+
matched: false,
|
|
287
|
+
not,
|
|
229
288
|
};
|
|
230
289
|
}
|
|
231
290
|
// Next-sibling combinator
|
|
232
291
|
case '+': {
|
|
233
|
-
|
|
292
|
+
const matchedNodes = [];
|
|
293
|
+
const has = [];
|
|
294
|
+
const not = [];
|
|
234
295
|
const specificity = unitCheck.specificity;
|
|
235
296
|
if (el.previousElementSibling) {
|
|
236
297
|
const res = target.match(el.previousElementSibling, scope, count + 1);
|
|
237
298
|
specificity[0] += res.specificity[0];
|
|
238
299
|
specificity[1] += res.specificity[1];
|
|
239
300
|
specificity[2] += res.specificity[2];
|
|
240
|
-
|
|
301
|
+
if (res.matched) {
|
|
302
|
+
matchedNodes.push(...res.nodes);
|
|
303
|
+
has.push(...res.has);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
if (res.not) {
|
|
307
|
+
not.push(...res.not);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
241
310
|
}
|
|
242
311
|
else {
|
|
243
312
|
const res = target.match(el, scope, count + 1);
|
|
244
313
|
specificity[0] += res.specificity[0];
|
|
245
314
|
specificity[1] += res.specificity[1];
|
|
246
315
|
specificity[2] += res.specificity[2];
|
|
247
|
-
|
|
316
|
+
}
|
|
317
|
+
if (matchedNodes.length) {
|
|
318
|
+
return {
|
|
319
|
+
combinator: '+',
|
|
320
|
+
specificity,
|
|
321
|
+
matched: true,
|
|
322
|
+
nodes: matchedNodes,
|
|
323
|
+
has,
|
|
324
|
+
};
|
|
248
325
|
}
|
|
249
326
|
return {
|
|
250
327
|
combinator: '+',
|
|
251
328
|
specificity,
|
|
252
|
-
matched,
|
|
329
|
+
matched: false,
|
|
330
|
+
not,
|
|
253
331
|
};
|
|
254
332
|
}
|
|
255
333
|
// Subsequent-sibling combinator
|
|
256
334
|
case '~': {
|
|
335
|
+
const matchedNodes = [];
|
|
336
|
+
const has = [];
|
|
337
|
+
const not = [];
|
|
257
338
|
let prev = el.previousElementSibling;
|
|
258
|
-
let matched = false;
|
|
259
339
|
let specificity;
|
|
260
340
|
while (prev) {
|
|
261
341
|
const res = target.match(prev, scope, count + 1);
|
|
@@ -267,7 +347,13 @@ class SelectorTarget {
|
|
|
267
347
|
];
|
|
268
348
|
}
|
|
269
349
|
if (res.matched) {
|
|
270
|
-
|
|
350
|
+
matchedNodes.push(...res.nodes);
|
|
351
|
+
has.push(...res.has);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
if (res.not) {
|
|
355
|
+
not.push(...res.not);
|
|
356
|
+
}
|
|
271
357
|
}
|
|
272
358
|
prev = prev.previousElementSibling;
|
|
273
359
|
}
|
|
@@ -279,10 +365,20 @@ class SelectorTarget {
|
|
|
279
365
|
unitCheck.specificity[2] + res.specificity[2],
|
|
280
366
|
];
|
|
281
367
|
}
|
|
368
|
+
if (matchedNodes.length) {
|
|
369
|
+
return {
|
|
370
|
+
combinator: '~',
|
|
371
|
+
specificity,
|
|
372
|
+
matched: true,
|
|
373
|
+
nodes: matchedNodes,
|
|
374
|
+
has,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
282
377
|
return {
|
|
283
378
|
combinator: '~',
|
|
284
379
|
specificity,
|
|
285
|
-
matched,
|
|
380
|
+
matched: false,
|
|
381
|
+
not,
|
|
286
382
|
};
|
|
287
383
|
}
|
|
288
384
|
// Column combinator
|
|
@@ -290,21 +386,12 @@ class SelectorTarget {
|
|
|
290
386
|
throw new Error('Unsupported column combinator yet. If you want it, please request it as the issue (https://github.com/markuplint/markuplint/issues/new).');
|
|
291
387
|
}
|
|
292
388
|
default: {
|
|
293
|
-
throw new Error(`Unsupported ${tslib_1.__classPrivateFieldGet(this,
|
|
389
|
+
throw new Error(`Unsupported ${tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f").combinator.value} combinator in selector`);
|
|
294
390
|
}
|
|
295
391
|
}
|
|
296
392
|
}
|
|
297
|
-
|
|
298
|
-
var _a
|
|
299
|
-
return [
|
|
300
|
-
(_b = (_a = this.tag) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '',
|
|
301
|
-
this.id.map(id => `#${id.value}`).join(''),
|
|
302
|
-
this.class.map(c => `.${c.value}`).join(''),
|
|
303
|
-
this.attr.map(attr => `[${attr.toString()}]`).join(''),
|
|
304
|
-
this.pseudo.map(pseudo => pseudo.value).join(''),
|
|
305
|
-
].join('');
|
|
306
|
-
}
|
|
307
|
-
_matchWithoutCombinateChecking(el, scope) {
|
|
393
|
+
_matchWithoutCombineChecking(el, scope) {
|
|
394
|
+
var _a;
|
|
308
395
|
const specificity = [0, 0, 0];
|
|
309
396
|
if (!(0, is_1.isElement)(el)) {
|
|
310
397
|
return {
|
|
@@ -312,6 +399,8 @@ class SelectorTarget {
|
|
|
312
399
|
matched: false,
|
|
313
400
|
};
|
|
314
401
|
}
|
|
402
|
+
const has = [];
|
|
403
|
+
const not = [];
|
|
315
404
|
// @ts-ignore
|
|
316
405
|
if (this.tag && this.tag._namespace) {
|
|
317
406
|
// @ts-ignore
|
|
@@ -356,7 +445,11 @@ class SelectorTarget {
|
|
|
356
445
|
specificity[0] += pseudoRes.specificity[0];
|
|
357
446
|
specificity[1] += pseudoRes.specificity[1];
|
|
358
447
|
specificity[2] += pseudoRes.specificity[2];
|
|
359
|
-
if (
|
|
448
|
+
if (pseudoRes.matched) {
|
|
449
|
+
has.push(...pseudoRes.has);
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
not.push(...((_a = pseudoRes.not) !== null && _a !== void 0 ? _a : []));
|
|
360
453
|
matched = false;
|
|
361
454
|
}
|
|
362
455
|
}
|
|
@@ -372,18 +465,33 @@ class SelectorTarget {
|
|
|
372
465
|
matched = false;
|
|
373
466
|
}
|
|
374
467
|
}
|
|
468
|
+
if (matched) {
|
|
469
|
+
return {
|
|
470
|
+
specificity,
|
|
471
|
+
matched,
|
|
472
|
+
nodes: [el],
|
|
473
|
+
has,
|
|
474
|
+
};
|
|
475
|
+
}
|
|
375
476
|
return {
|
|
376
477
|
specificity,
|
|
377
478
|
matched,
|
|
479
|
+
not,
|
|
378
480
|
};
|
|
379
481
|
}
|
|
380
482
|
}
|
|
381
|
-
|
|
483
|
+
_SelectorTarget_combinedFrom = new WeakMap(), _SelectorTarget_extended = new WeakMap(), _SelectorTarget_isAdded = new WeakMap();
|
|
382
484
|
function attrMatch(attr, el) {
|
|
383
485
|
return Array.from(el.attributes).some(attrOfEl => {
|
|
384
|
-
if (attr.attribute !== attrOfEl.
|
|
486
|
+
if (attr.attribute !== attrOfEl.localName) {
|
|
385
487
|
return false;
|
|
386
488
|
}
|
|
489
|
+
if (attr.namespace != null && attr.namespace !== true && attr.namespace !== '*') {
|
|
490
|
+
const ns = (0, ml_spec_1.resolveNamespace)(attrOfEl.localName, attrOfEl.namespaceURI);
|
|
491
|
+
if (attr.namespace !== ns.namespace) {
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
387
495
|
if (attr.value != null) {
|
|
388
496
|
let value = attr.value;
|
|
389
497
|
let valueOfEl = attrOfEl.value;
|
|
@@ -444,10 +552,13 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
444
552
|
const specificity = getSpecificity(ruleset.match(el, scope));
|
|
445
553
|
let parent = el.parentElement;
|
|
446
554
|
while (parent) {
|
|
447
|
-
|
|
555
|
+
const matched = ruleset.match(parent, scope).filter((r) => r.matched);
|
|
556
|
+
if (matched.length) {
|
|
448
557
|
return {
|
|
449
558
|
specificity,
|
|
450
559
|
matched: true,
|
|
560
|
+
nodes: [el],
|
|
561
|
+
has: matched,
|
|
451
562
|
};
|
|
452
563
|
}
|
|
453
564
|
parent = parent.parentElement;
|
|
@@ -464,20 +575,31 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
464
575
|
const ruleset = new Ruleset(pseudo.nodes, extended, depth + 1);
|
|
465
576
|
const resList = ruleset.match(el, scope);
|
|
466
577
|
const specificity = getSpecificity(resList);
|
|
467
|
-
const
|
|
578
|
+
const not = resList.filter((r) => r.matched);
|
|
579
|
+
if (not.length === 0) {
|
|
580
|
+
return {
|
|
581
|
+
specificity,
|
|
582
|
+
matched: true,
|
|
583
|
+
nodes: [el],
|
|
584
|
+
has: [],
|
|
585
|
+
};
|
|
586
|
+
}
|
|
468
587
|
return {
|
|
469
588
|
specificity,
|
|
470
|
-
matched,
|
|
589
|
+
matched: false,
|
|
590
|
+
not,
|
|
471
591
|
};
|
|
472
592
|
}
|
|
473
593
|
case ':is': {
|
|
474
594
|
const ruleset = new Ruleset(pseudo.nodes, extended, depth + 1);
|
|
475
595
|
const resList = ruleset.match(el, scope);
|
|
476
596
|
const specificity = getSpecificity(resList);
|
|
477
|
-
const matched = resList.
|
|
597
|
+
const matched = resList.filter((r) => r.matched);
|
|
478
598
|
return {
|
|
479
599
|
specificity,
|
|
480
|
-
matched,
|
|
600
|
+
matched: !!matched.length,
|
|
601
|
+
nodes: matched.map(m => m.nodes).flat(),
|
|
602
|
+
has: matched.map(m => m.has).flat(),
|
|
481
603
|
};
|
|
482
604
|
}
|
|
483
605
|
case ':has': {
|
|
@@ -486,17 +608,37 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
486
608
|
switch (ruleset.headCombinator) {
|
|
487
609
|
case '+':
|
|
488
610
|
case '~': {
|
|
489
|
-
const
|
|
611
|
+
const has = getSiblings(el)
|
|
612
|
+
.map(sib => ruleset.match(sib, el).filter((m) => m.matched))
|
|
613
|
+
.flat();
|
|
614
|
+
if (has.length) {
|
|
615
|
+
return {
|
|
616
|
+
specificity,
|
|
617
|
+
matched: true,
|
|
618
|
+
nodes: [el],
|
|
619
|
+
has,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
490
622
|
return {
|
|
491
623
|
specificity,
|
|
492
|
-
matched,
|
|
624
|
+
matched: false,
|
|
493
625
|
};
|
|
494
626
|
}
|
|
495
627
|
default: {
|
|
496
|
-
const
|
|
628
|
+
const has = getDescendants(el)
|
|
629
|
+
.map(sib => ruleset.match(sib, el).filter((m) => m.matched))
|
|
630
|
+
.flat();
|
|
631
|
+
if (has.length) {
|
|
632
|
+
return {
|
|
633
|
+
specificity,
|
|
634
|
+
matched: true,
|
|
635
|
+
nodes: [el],
|
|
636
|
+
has,
|
|
637
|
+
};
|
|
638
|
+
}
|
|
497
639
|
return {
|
|
498
640
|
specificity,
|
|
499
|
-
matched,
|
|
641
|
+
matched: false,
|
|
500
642
|
};
|
|
501
643
|
}
|
|
502
644
|
}
|
|
@@ -504,10 +646,12 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
504
646
|
case ':where': {
|
|
505
647
|
const ruleset = new Ruleset(pseudo.nodes, extended, depth + 1);
|
|
506
648
|
const resList = ruleset.match(el, scope);
|
|
507
|
-
const matched = resList.
|
|
649
|
+
const matched = resList.filter((r) => r.matched);
|
|
508
650
|
return {
|
|
509
651
|
specificity: [0, 0, 0],
|
|
510
|
-
matched,
|
|
652
|
+
matched: !!matched.length,
|
|
653
|
+
nodes: matched.map(m => m.nodes).flat(),
|
|
654
|
+
has: matched.map(m => m.has).flat(),
|
|
511
655
|
};
|
|
512
656
|
}
|
|
513
657
|
case ':scope': {
|
|
@@ -515,6 +659,8 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
515
659
|
return {
|
|
516
660
|
specificity: [0, 1, 0],
|
|
517
661
|
matched: true,
|
|
662
|
+
nodes: [el],
|
|
663
|
+
has: [],
|
|
518
664
|
};
|
|
519
665
|
}
|
|
520
666
|
return {
|
|
@@ -527,6 +673,8 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
|
|
|
527
673
|
return {
|
|
528
674
|
specificity: [0, 1, 0],
|
|
529
675
|
matched: true,
|
|
676
|
+
nodes: [el],
|
|
677
|
+
has: [],
|
|
530
678
|
};
|
|
531
679
|
}
|
|
532
680
|
return {
|
|
@@ -612,17 +760,17 @@ function getSiblings(el) {
|
|
|
612
760
|
var _a;
|
|
613
761
|
return Array.from(((_a = el.parentElement) === null || _a === void 0 ? void 0 : _a.children) || []);
|
|
614
762
|
}
|
|
615
|
-
function getSpecificity(
|
|
763
|
+
function getSpecificity(results) {
|
|
616
764
|
let specificity;
|
|
617
|
-
for (const
|
|
765
|
+
for (const result of results) {
|
|
618
766
|
if (specificity) {
|
|
619
|
-
const order = (0, compare_specificity_1.compareSpecificity)(specificity,
|
|
767
|
+
const order = (0, compare_specificity_1.compareSpecificity)(specificity, result.specificity);
|
|
620
768
|
if (order === -1) {
|
|
621
|
-
specificity =
|
|
769
|
+
specificity = result.specificity;
|
|
622
770
|
}
|
|
623
771
|
}
|
|
624
772
|
else {
|
|
625
|
-
specificity =
|
|
773
|
+
specificity = result.specificity;
|
|
626
774
|
}
|
|
627
775
|
}
|
|
628
776
|
if (!specificity) {
|
package/lib/types.d.ts
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
export declare type Specificity = [number, number, number];
|
|
2
|
-
export declare type SelectorResult =
|
|
2
|
+
export declare type SelectorResult = SelectorMatchedResult | SelectorUnmatchedResult;
|
|
3
|
+
export declare type SelectorMatchedResult = {
|
|
3
4
|
specificity: Specificity;
|
|
4
|
-
matched:
|
|
5
|
+
matched: true;
|
|
6
|
+
nodes: (Element | Text)[];
|
|
7
|
+
has: SelectorMatchedResult[];
|
|
5
8
|
};
|
|
6
|
-
export declare type
|
|
9
|
+
export declare type SelectorUnmatchedResult = {
|
|
10
|
+
specificity: Specificity;
|
|
11
|
+
matched: false;
|
|
12
|
+
not?: SelectorMatchedResult[];
|
|
13
|
+
};
|
|
14
|
+
export declare type RegexSelector = RegexSelectorWithoutCombination & {
|
|
7
15
|
combination?: {
|
|
8
16
|
combinator: RegexSelectorCombinator;
|
|
9
17
|
} & RegexSelector;
|
|
10
18
|
};
|
|
11
19
|
export declare type RegexSelectorCombinator = ' ' | '>' | '+' | '~' | ':has(+)' | ':has(~)';
|
|
12
|
-
export declare type
|
|
20
|
+
export declare type RegexSelectorWithoutCombination = {
|
|
13
21
|
nodeName?: string;
|
|
14
22
|
attrName?: string;
|
|
15
23
|
attrValue?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/selector",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.3",
|
|
4
4
|
"description": "W3C Selector and Regex selector",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"tslib": "^2.4.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@markuplint/ml-spec": "3.0.0-alpha.
|
|
25
|
+
"@markuplint/ml-spec": "3.0.0-alpha.3",
|
|
26
26
|
"@types/debug": "^4.1.7",
|
|
27
|
-
"@types/jsdom": "
|
|
28
|
-
"jsdom": "
|
|
27
|
+
"@types/jsdom": "16",
|
|
28
|
+
"jsdom": "19"
|
|
29
29
|
},
|
|
30
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "884b1a6a7385e86cca7796b0b927a886ee90140e"
|
|
31
31
|
}
|