@markuplint/selector 3.0.0-alpha.6 → 3.0.0-dev.176

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 CHANGED
@@ -1,18 +1,8 @@
1
1
  # @markuplint/selector
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40markuplint%2Fselector.svg)](https://www.npmjs.com/package/@markuplint/selector)
4
- [![Build Status](https://travis-ci.org/markuplint/markuplint.svg?branch=main)](https://travis-ci.org/markuplint/markuplint)
5
- [![Coverage Status](https://coveralls.io/repos/github/markuplint/markuplint/badge.svg?branch=main)](https://coveralls.io/github/markuplint/markuplint?branch=main)
6
4
 
7
- ## Install
8
-
9
- ```sh
10
- $ npm install @markuplint/selector
11
-
12
- $ yarn add @markuplint/selector
13
- ```
14
-
15
- ## [W3C Selectors](https://www.w3.org/TR/selectors-4/) matcher
5
+ **Extended [W3C Selectors](https://www.w3.org/TR/selectors-4/) matcher**
16
6
 
17
7
  Supported selectors and operators:
18
8
 
@@ -120,3 +110,18 @@ For example, `:role(interactive)` matches `<a>`(with `href` attr), `<button>`, a
120
110
  "attrValue": "/^[a-z]+$/"
121
111
  }
122
112
  ```
113
+
114
+ ## Install
115
+
116
+ [`markuplint`](https://www.npmjs.com/package/markuplint) package includes this package.
117
+
118
+ <details>
119
+ <summary>If you are installing purposely, how below:</summary>
120
+
121
+ ```shell
122
+ $ npm install @markuplint/selector
123
+
124
+ $ yarn add @markuplint/selector
125
+ ```
126
+
127
+ </details>
@@ -6,7 +6,9 @@ const ml_spec_1 = require("@markuplint/ml-spec");
6
6
  * Version Syntax is not support yet.
7
7
  */
8
8
  function ariaPseudoClass() {
9
- return (content) => (el) => {
9
+ return (content) => (
10
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
11
+ el) => {
10
12
  const aria = ariaPseudoClassParser(content);
11
13
  const name = (0, ml_spec_1.getAccname)(el);
12
14
  switch (aria.type) {
@@ -44,8 +46,11 @@ function ariaPseudoClass() {
44
46
  exports.ariaPseudoClass = ariaPseudoClass;
45
47
  function ariaPseudoClassParser(syntax) {
46
48
  const [_query, _version] = syntax.split('|');
47
- const query = _query.replace(/\s+/g, '').toLowerCase();
48
- const version = _version === '1.1' ? '1.1' : '1.2';
49
+ const query = _query === null || _query === void 0 ? void 0 : _query.replace(/\s+/g, '').toLowerCase();
50
+ const version = _version !== null && _version !== void 0 ? _version : ml_spec_1.ARIA_RECOMMENDED_VERSION;
51
+ if (!(0, ml_spec_1.validateAriaVersion)(version)) {
52
+ throw new SyntaxError(`Unsupported ARIA version: ${version}`);
53
+ }
49
54
  switch (query) {
50
55
  case 'hasname': {
51
56
  return {
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ariaRolePseudoClass = void 0;
4
4
  const ml_spec_1 = require("@markuplint/ml-spec");
5
5
  function ariaRolePseudoClass(specs) {
6
- return (content) => (el) => {
6
+ return (content) => (
7
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
8
+ el) => {
7
9
  var _a, _b;
8
10
  const aria = ariaPseudoClassParser(content);
9
- const computed = (0, ml_spec_1.getComputedRole)(specs, el, (_a = aria.version) !== null && _a !== void 0 ? _a : '1.2');
11
+ const computed = (0, ml_spec_1.getComputedRole)(specs, el, (_a = aria.version) !== null && _a !== void 0 ? _a : ml_spec_1.ARIA_RECOMMENDED_VERSION);
10
12
  if (((_b = computed.role) === null || _b === void 0 ? void 0 : _b.name) === aria.role) {
11
13
  return {
12
14
  specificity: [0, 1, 0],
@@ -23,10 +25,14 @@ function ariaRolePseudoClass(specs) {
23
25
  }
24
26
  exports.ariaRolePseudoClass = ariaRolePseudoClass;
25
27
  function ariaPseudoClassParser(syntax) {
28
+ var _a;
26
29
  const [roleName, _version] = syntax.split('|');
27
- const version = _version === '1.1' ? '1.1' : '1.2';
30
+ const version = _version !== null && _version !== void 0 ? _version : ml_spec_1.ARIA_RECOMMENDED_VERSION;
31
+ if (!(0, ml_spec_1.validateAriaVersion)(version)) {
32
+ throw new SyntaxError(`Unsupported ARIA version: ${version}`);
33
+ }
28
34
  return {
29
- role: roleName.trim().toLowerCase(),
35
+ role: (_a = roleName === null || roleName === void 0 ? void 0 : roleName.trim().toLowerCase()) !== null && _a !== void 0 ? _a : syntax.trim().toLowerCase(),
30
36
  version,
31
37
  };
32
38
  }
@@ -4,7 +4,9 @@ exports.contentModelPseudoClass = void 0;
4
4
  const ml_spec_1 = require("@markuplint/ml-spec");
5
5
  const create_selector_1 = require("../create-selector");
6
6
  function contentModelPseudoClass(specs) {
7
- return (category) => (el) => {
7
+ return (category) => (
8
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
9
+ el) => {
8
10
  category = category.trim().toLowerCase();
9
11
  const selectors = (0, ml_spec_1.contentModelCategoryToTagNames)(`#${category}`, specs.def);
10
12
  const matched = selectors
@@ -40,7 +42,7 @@ function contentModelPseudoClass(specs) {
40
42
  })
41
43
  .flat()
42
44
  .filter((m) => m.matched);
43
- if (matched.length) {
45
+ if (matched.length > 0) {
44
46
  return {
45
47
  specificity: [0, 1, 0],
46
48
  matched: true,
package/lib/is.js CHANGED
@@ -1,15 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isPureHTMLElement = exports.isNonDocumentTypeChildNode = exports.isElement = void 0;
4
- function isElement(node) {
4
+ function isElement(
5
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
6
+ node) {
5
7
  return node.nodeType === node.ELEMENT_NODE;
6
8
  }
7
9
  exports.isElement = isElement;
8
- function isNonDocumentTypeChildNode(node) {
10
+ function isNonDocumentTypeChildNode(
11
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
12
+ node) {
9
13
  return 'previousElementSibling' in node && 'nextElementSibling' in node;
10
14
  }
11
15
  exports.isNonDocumentTypeChildNode = isNonDocumentTypeChildNode;
12
- function isPureHTMLElement(el) {
16
+ function isPureHTMLElement(
17
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
18
+ el) {
13
19
  return el.localName !== el.nodeName;
14
20
  }
15
21
  exports.isPureHTMLElement = isPureHTMLElement;
@@ -1,13 +1,13 @@
1
1
  import type { Specificity, RegexSelector } from './types';
2
2
  export type SelectorMatches = SelectorMatched | SelectorUnmatched;
3
3
  type SelectorMatched = {
4
- matched: true;
5
- selector: string;
6
- specificity: Specificity;
7
- data?: Record<string, string>;
4
+ readonly matched: true;
5
+ readonly selector: string;
6
+ readonly specificity: Specificity;
7
+ readonly data?: Readonly<Record<string, string>>;
8
8
  };
9
9
  type SelectorUnmatched = {
10
- matched: false;
10
+ readonly matched: false;
11
11
  };
12
12
  export declare function matchSelector(el: Node, selector: string | RegexSelector | undefined): SelectorMatches;
13
13
  export {};
@@ -6,8 +6,10 @@ const tslib_1 = require("tslib");
6
6
  const is_1 = require("./is");
7
7
  const regex_selector_matches_1 = require("./regex-selector-matches");
8
8
  const selector_1 = require("./selector");
9
- function matchSelector(el, selector) {
10
- if (!selector) {
9
+ function matchSelector(
10
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
11
+ el, selector) {
12
+ if (selector == null || selector === '') {
11
13
  return {
12
14
  matched: false,
13
15
  };
@@ -15,7 +17,7 @@ function matchSelector(el, selector) {
15
17
  if (typeof selector === 'string') {
16
18
  const sel = new selector_1.Selector(selector);
17
19
  const specificity = sel.match(el);
18
- if (specificity) {
20
+ if (specificity !== false) {
19
21
  return {
20
22
  matched: true,
21
23
  selector,
@@ -29,7 +31,9 @@ function matchSelector(el, selector) {
29
31
  return regexSelect(el, selector);
30
32
  }
31
33
  exports.matchSelector = matchSelector;
32
- function regexSelect(el, selector) {
34
+ function regexSelect(
35
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
36
+ el, selector) {
33
37
  let edge = new SelectorTarget(selector);
34
38
  let edgeSelector = selector.combination;
35
39
  while (edgeSelector) {
@@ -49,7 +53,9 @@ class SelectorTarget {
49
53
  from(target, combinator) {
50
54
  tslib_1.__classPrivateFieldSet(this, _SelectorTarget_combinedFrom, { target, combinator }, "f");
51
55
  }
52
- match(el) {
56
+ match(
57
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
58
+ el) {
53
59
  const unitCheck = this._matchWithoutCombineChecking(el);
54
60
  if (!unitCheck.matched) {
55
61
  return unitCheck;
@@ -139,12 +145,16 @@ class SelectorTarget {
139
145
  }
140
146
  }
141
147
  }
142
- _matchWithoutCombineChecking(el) {
148
+ _matchWithoutCombineChecking(
149
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
150
+ el) {
143
151
  return uncombinedRegexSelect(el, tslib_1.__classPrivateFieldGet(this, _SelectorTarget_selector, "f"));
144
152
  }
145
153
  }
146
154
  _SelectorTarget_combinedFrom = new WeakMap(), _SelectorTarget_selector = new WeakMap();
147
- function uncombinedRegexSelect(el, selector) {
155
+ function uncombinedRegexSelect(
156
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
157
+ el, selector) {
148
158
  if (!(0, is_1.isElement)(el)) {
149
159
  return {
150
160
  matched: false,
@@ -18,7 +18,7 @@ function regexSelectorMatches(reg, raw, ignoreCase) {
18
18
  exports.regexSelectorMatches = regexSelectorMatches;
19
19
  function toRegexp(pattern) {
20
20
  const matched = pattern.match(/^\/(.+)\/([ig]*)$/i);
21
- if (matched) {
21
+ if (matched && matched[1]) {
22
22
  return new RegExp(matched[1], matched[2]);
23
23
  }
24
24
  return pattern;
package/lib/selector.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { SelectorResult, Specificity } from './types';
2
- type ExtendedPseudoClass = Record<string, (content: string) => (el: Element) => SelectorResult>;
2
+ type ExtendedPseudoClass = Readonly<Record<string, (content: string) => (el: Element) => SelectorResult>>;
3
3
  export declare class Selector {
4
4
  #private;
5
5
  constructor(selector: string, extended?: ExtendedPseudoClass);
package/lib/selector.js CHANGED
@@ -16,7 +16,12 @@ class Selector {
16
16
  _Selector_ruleset.set(this, void 0);
17
17
  tslib_1.__classPrivateFieldSet(this, _Selector_ruleset, Ruleset.parse(selector, extended), "f");
18
18
  }
19
- match(el, scope = (0, is_1.isElement)(el) ? el : null) {
19
+ match(
20
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
21
+ el,
22
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
23
+ scope) {
24
+ scope = (0, is_1.isElement)(el) ? el : null;
20
25
  const results = this.search(el, scope);
21
26
  for (const result of results) {
22
27
  if (result.matched) {
@@ -25,7 +30,12 @@ class Selector {
25
30
  }
26
31
  return false;
27
32
  }
28
- search(el, scope = (0, is_1.isElement)(el) ? el : null) {
33
+ search(
34
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
35
+ el,
36
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
37
+ scope) {
38
+ scope = (0, is_1.isElement)(el) ? el : null;
29
39
  return tslib_1.__classPrivateFieldGet(this, _Selector_ruleset, "f").match(el, scope);
30
40
  }
31
41
  }
@@ -48,17 +58,22 @@ class Ruleset {
48
58
  return new Ruleset(selectors, extended, 0);
49
59
  }
50
60
  constructor(selectors, extended, depth) {
61
+ var _a, _b;
51
62
  _Ruleset_selectorGroup.set(this, []);
52
63
  tslib_1.__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f").push(...selectors.map(selector => new StructuredSelector(selector, depth, extended)));
53
64
  const head = tslib_1.__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f")[0];
54
- this.headCombinator = (head === null || head === void 0 ? void 0 : head.headCombinator) || null;
65
+ this.headCombinator = (_a = head === null || head === void 0 ? void 0 : head.headCombinator) !== null && _a !== void 0 ? _a : null;
55
66
  if (this.headCombinator) {
56
67
  if (depth <= 0) {
57
- throw new invalid_selector_error_1.InvalidSelectorError(`'${tslib_1.__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f")[0].selector}' is not a valid selector`);
68
+ throw new invalid_selector_error_1.InvalidSelectorError(`'${(_b = tslib_1.__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f")[0]) === null || _b === void 0 ? void 0 : _b.selector}' is not a valid selector`);
58
69
  }
59
70
  }
60
71
  }
61
- match(el, scope) {
72
+ match(
73
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
74
+ el,
75
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
76
+ scope) {
62
77
  (0, debug_1.log)('<%s> (%s)', (0, is_1.isElement)(el) ? el.localName : el.nodeName, scope ? ((0, is_1.isElement)(scope) ? scope.localName : scope.nodeName) : null);
63
78
  return tslib_1.__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f").map(selector => {
64
79
  selLog('"%s"', selector.selector);
@@ -71,16 +86,18 @@ class Ruleset {
71
86
  _Ruleset_selectorGroup = new WeakMap();
72
87
  class StructuredSelector {
73
88
  constructor(selector, depth, extended) {
89
+ var _a, _b;
74
90
  _StructuredSelector_edge.set(this, void 0);
75
91
  _StructuredSelector_selector.set(this, void 0);
76
92
  tslib_1.__classPrivateFieldSet(this, _StructuredSelector_selector, selector, "f");
77
93
  tslib_1.__classPrivateFieldSet(this, _StructuredSelector_edge, new SelectorTarget(extended, depth), "f");
78
94
  this.headCombinator =
79
- tslib_1.__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes[0].type === 'combinator' ? tslib_1.__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes[0].value || null : null;
95
+ ((_a = tslib_1.__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes[0]) === null || _a === void 0 ? void 0 : _a.type) === 'combinator' ? (_b = tslib_1.__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes[0].value) !== null && _b !== void 0 ? _b : null : null;
96
+ const nodes = tslib_1.__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes.slice();
80
97
  if (0 < depth && this.headCombinator) {
81
- tslib_1.__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes.unshift((0, postcss_selector_parser_1.pseudo)({ value: ':scope' }));
98
+ nodes.unshift((0, postcss_selector_parser_1.pseudo)({ value: ':scope' }));
82
99
  }
83
- tslib_1.__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes.forEach(node => {
100
+ nodes.forEach(node => {
84
101
  switch (node.type) {
85
102
  case 'combinator': {
86
103
  const combinedTarget = new SelectorTarget(extended, depth);
@@ -107,7 +124,11 @@ class StructuredSelector {
107
124
  get selector() {
108
125
  return tslib_1.__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes.join('');
109
126
  }
110
- match(el, scope) {
127
+ match(
128
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
129
+ el,
130
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
131
+ scope) {
111
132
  return tslib_1.__classPrivateFieldGet(this, _StructuredSelector_edge, "f").match(el, scope, 0);
112
133
  }
113
134
  }
@@ -154,16 +175,20 @@ class SelectorTarget {
154
175
  from(target, combinator) {
155
176
  tslib_1.__classPrivateFieldSet(this, _SelectorTarget_combinedFrom, { target, combinator }, "f");
156
177
  }
157
- match(el, scope, count) {
158
- var _a;
178
+ match(
179
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
180
+ el,
181
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
182
+ scope, count) {
183
+ var _a, _b, _c;
159
184
  const result = this._match(el, scope, count);
160
185
  if (selLog.enabled) {
161
186
  const nodeName = el.nodeName;
162
- const selector = ((_a = tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f")) === null || _a === void 0 ? void 0 : _a.target.toString()) || this.toString();
187
+ const selector = (_b = (_a = tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f")) === null || _a === void 0 ? void 0 : _a.target.toString()) !== null && _b !== void 0 ? _b : this.toString();
163
188
  const combinator = result.combinator ? ` ${result.combinator}` : '';
164
189
  selLog('The %s element by "%s" => %s (%d)', nodeName, `${selector}${combinator}`, result.matched, count);
165
190
  if (selector === ':scope') {
166
- selLog(`† Scope is the ${(scope === null || scope === void 0 ? void 0 : scope.nodeName) || null}`);
191
+ selLog(`† Scope is the ${(_c = scope === null || scope === void 0 ? void 0 : scope.nodeName) !== null && _c !== void 0 ? _c : null}`);
167
192
  }
168
193
  }
169
194
  delete result.combinator;
@@ -179,7 +204,11 @@ class SelectorTarget {
179
204
  this.pseudo.map(pseudo => pseudo.value).join(''),
180
205
  ].join('');
181
206
  }
182
- _match(el, scope, count) {
207
+ _match(
208
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
209
+ el,
210
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
211
+ scope, count) {
183
212
  const unitCheck = this._matchWithoutCombineChecking(el, scope);
184
213
  if (!unitCheck.matched) {
185
214
  return unitCheck;
@@ -227,7 +256,7 @@ class SelectorTarget {
227
256
  unitCheck.specificity[2] + res.specificity[2],
228
257
  ];
229
258
  }
230
- if (matchedNodes.length) {
259
+ if (matchedNodes.length > 0) {
231
260
  return {
232
261
  combinator: '␣',
233
262
  specificity,
@@ -248,7 +277,7 @@ class SelectorTarget {
248
277
  const matchedNodes = [];
249
278
  const has = [];
250
279
  const not = [];
251
- const specificity = unitCheck.specificity;
280
+ const specificity = [...unitCheck.specificity];
252
281
  const parentNode = el.parentElement;
253
282
  if (parentNode) {
254
283
  const res = target.match(parentNode, scope, count + 1);
@@ -271,7 +300,7 @@ class SelectorTarget {
271
300
  specificity[1] += res.specificity[1];
272
301
  specificity[2] += res.specificity[2];
273
302
  }
274
- if (matchedNodes.length) {
303
+ if (matchedNodes.length > 0) {
275
304
  return {
276
305
  combinator: '>',
277
306
  specificity,
@@ -292,7 +321,7 @@ class SelectorTarget {
292
321
  const matchedNodes = [];
293
322
  const has = [];
294
323
  const not = [];
295
- const specificity = unitCheck.specificity;
324
+ const specificity = [...unitCheck.specificity];
296
325
  if (el.previousElementSibling) {
297
326
  const res = target.match(el.previousElementSibling, scope, count + 1);
298
327
  specificity[0] += res.specificity[0];
@@ -314,7 +343,7 @@ class SelectorTarget {
314
343
  specificity[1] += res.specificity[1];
315
344
  specificity[2] += res.specificity[2];
316
345
  }
317
- if (matchedNodes.length) {
346
+ if (matchedNodes.length > 0) {
318
347
  return {
319
348
  combinator: '+',
320
349
  specificity,
@@ -365,7 +394,7 @@ class SelectorTarget {
365
394
  unitCheck.specificity[2] + res.specificity[2],
366
395
  ];
367
396
  }
368
- if (matchedNodes.length) {
397
+ if (matchedNodes.length > 0) {
369
398
  return {
370
399
  combinator: '~',
371
400
  specificity,
@@ -390,7 +419,11 @@ class SelectorTarget {
390
419
  }
391
420
  }
392
421
  }
393
- _matchWithoutCombineChecking(el, scope) {
422
+ _matchWithoutCombineChecking(
423
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
424
+ el,
425
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
426
+ scope) {
394
427
  var _a;
395
428
  const specificity = [0, 0, 0];
396
429
  if (!(0, is_1.isElement)(el)) {
@@ -481,7 +514,9 @@ class SelectorTarget {
481
514
  }
482
515
  }
483
516
  _SelectorTarget_combinedFrom = new WeakMap(), _SelectorTarget_extended = new WeakMap(), _SelectorTarget_isAdded = new WeakMap();
484
- function attrMatch(attr, el) {
517
+ function attrMatch(attr,
518
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
519
+ el) {
485
520
  return Array.from(el.attributes).some(attrOfEl => {
486
521
  if (attr.attribute !== attrOfEl.localName) {
487
522
  return false;
@@ -519,7 +554,7 @@ function attrMatch(attr, el) {
519
554
  break;
520
555
  }
521
556
  case '*=': {
522
- if (valueOfEl.indexOf(value) === -1) {
557
+ if (!valueOfEl.includes(value)) {
523
558
  return false;
524
559
  }
525
560
  break;
@@ -541,7 +576,11 @@ function attrMatch(attr, el) {
541
576
  return true;
542
577
  });
543
578
  }
544
- function pseudoMatch(pseudo, el, scope, extended, depth) {
579
+ function pseudoMatch(pseudo,
580
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
581
+ el,
582
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
583
+ scope, extended, depth) {
545
584
  switch (pseudo.value) {
546
585
  //
547
586
  /**
@@ -553,7 +592,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
553
592
  let parent = el.parentElement;
554
593
  while (parent) {
555
594
  const matched = ruleset.match(parent, scope).filter((r) => r.matched);
556
- if (matched.length) {
595
+ if (matched.length > 0) {
557
596
  return {
558
597
  specificity,
559
598
  matched: true,
@@ -597,7 +636,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
597
636
  const matched = resList.filter((r) => r.matched);
598
637
  return {
599
638
  specificity,
600
- matched: !!matched.length,
639
+ matched: matched.length > 0,
601
640
  nodes: matched.map(m => m.nodes).flat(),
602
641
  has: matched.map(m => m.has).flat(),
603
642
  };
@@ -611,7 +650,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
611
650
  const has = getSiblings(el)
612
651
  .map(sib => ruleset.match(sib, el).filter((m) => m.matched))
613
652
  .flat();
614
- if (has.length) {
653
+ if (has.length > 0) {
615
654
  return {
616
655
  specificity,
617
656
  matched: true,
@@ -628,7 +667,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
628
667
  const has = getDescendants(el)
629
668
  .map(sib => ruleset.match(sib, el).filter((m) => m.matched))
630
669
  .flat();
631
- if (has.length) {
670
+ if (has.length > 0) {
632
671
  return {
633
672
  specificity,
634
673
  matched: true,
@@ -649,7 +688,7 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
649
688
  const matched = resList.filter((r) => r.matched);
650
689
  return {
651
690
  specificity: [0, 0, 0],
652
- matched: !!matched.length,
691
+ matched: matched.length > 0,
653
692
  nodes: matched.map(m => m.nodes).flat(),
654
693
  has: matched.map(m => m.has).flat(),
655
694
  };
@@ -738,6 +777,9 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
738
777
  }
739
778
  const content = pseudo.nodes.map(node => node.toString()).join('');
740
779
  const hook = extended[ext];
780
+ if (!hook) {
781
+ continue;
782
+ }
741
783
  const matcher = hook(content);
742
784
  return matcher(el);
743
785
  }
@@ -745,10 +787,17 @@ function pseudoMatch(pseudo, el, scope, extended, depth) {
745
787
  }
746
788
  }
747
789
  }
748
- function isScope(el, scope) {
749
- return el === scope || el.parentNode === null;
790
+ function isScope(
791
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
792
+ el,
793
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
794
+ scope) {
795
+ var _a;
796
+ return (_a = el === scope) !== null && _a !== void 0 ? _a : el.parentNode === null;
750
797
  }
751
- function getDescendants(el, includeSelf = false) {
798
+ function getDescendants(
799
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
800
+ el, includeSelf = false) {
752
801
  return [
753
802
  ...Array.from(el.children)
754
803
  .map(child => getDescendants(child, true))
@@ -756,11 +805,15 @@ function getDescendants(el, includeSelf = false) {
756
805
  ...(includeSelf ? [el] : []),
757
806
  ];
758
807
  }
759
- function getSiblings(el) {
760
- var _a;
761
- return Array.from(((_a = el.parentElement) === null || _a === void 0 ? void 0 : _a.children) || []);
808
+ function getSiblings(
809
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
810
+ el) {
811
+ var _a, _b;
812
+ return Array.from((_b = (_a = el.parentElement) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : []);
762
813
  }
763
- function getSpecificity(results) {
814
+ function getSpecificity(
815
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
816
+ results) {
764
817
  let specificity;
765
818
  for (const result of results) {
766
819
  if (specificity) {
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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@markuplint/selector",
3
- "version": "3.0.0-alpha.6",
4
- "description": "W3C Selector and Regex selector",
3
+ "version": "3.0.0-dev.176+f6ad62e9",
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",
@@ -11,21 +11,25 @@
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
14
+ "typedoc": {
15
+ "entryPoint": "./src/index.ts"
16
+ },
14
17
  "scripts": {
15
18
  "build": "tsc",
16
19
  "dev": "tsc --build --watch",
17
20
  "clean": "tsc --build --clean"
18
21
  },
19
22
  "dependencies": {
23
+ "@markuplint/ml-spec": "3.0.0-dev.176+f6ad62e9",
24
+ "@types/debug": "^4.1.7",
20
25
  "debug": "^4.3.4",
21
- "postcss-selector-parser": "^6.0.10",
22
- "tslib": "^2.4.0"
26
+ "postcss-selector-parser": "^6.0.11",
27
+ "tslib": "^2.4.1",
28
+ "type-fest": "^3.8.0"
23
29
  },
24
30
  "devDependencies": {
25
- "@markuplint/ml-spec": "3.0.0-alpha.6",
26
- "@types/debug": "^4.1.7",
27
- "@types/jsdom": "16",
28
- "jsdom": "19"
31
+ "@types/jsdom": "21.1.1",
32
+ "jsdom": "21.1.1"
29
33
  },
30
- "gitHead": "b185a06d4ea09a1bf32458f7be4abe510eb57b89"
34
+ "gitHead": "f6ad62e992e1569be4067f1e90d2d6017a658f57"
31
35
  }