@markuplint/selector 4.0.0-alpha.1 → 4.0.0-alpha.10

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017-2019 Yusuke Hirao
3
+ Copyright (c) 2017-2024 Yusuke Hirao
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -7,7 +7,7 @@ export function contentModelPseudoClass(specs) {
7
7
  category = category.trim().toLowerCase();
8
8
  const selectors = contentModelCategoryToTagNames(`#${category}`, specs.def);
9
9
  const matched = selectors
10
- .map(selector => {
10
+ .flatMap(selector => {
11
11
  if (selector === '#custom') {
12
12
  // @ts-ignore
13
13
  if (el.isCustomElement) {
@@ -37,14 +37,13 @@ export function contentModelPseudoClass(specs) {
37
37
  }
38
38
  return createSelector(selector, specs).search(el);
39
39
  })
40
- .flat()
41
40
  .filter((m) => m.matched);
42
41
  if (matched.length > 0) {
43
42
  return {
44
43
  specificity: [0, 1, 0],
45
44
  matched: true,
46
- nodes: matched.map(m => (m.matched ? m.nodes : [])).flat(),
47
- has: matched.map(m => (m.matched ? m.has : [])).flat(),
45
+ nodes: matched.flatMap(m => (m.matched ? m.nodes : [])),
46
+ has: matched.flatMap(m => (m.matched ? m.has : [])),
48
47
  };
49
48
  }
50
49
  return {
@@ -1,5 +1,15 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
1
12
  var _SelectorTarget_combinedFrom, _SelectorTarget_selector;
2
- import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
3
13
  import { isElement, isNonDocumentTypeChildNode, isPureHTMLElement } from './is.js';
4
14
  import { regexSelectorMatches } from './regex-selector-matches.js';
5
15
  import { Selector } from './selector.js';
@@ -176,46 +186,38 @@ el, selector) {
176
186
  tagSelector = el.localName;
177
187
  specificity[2] = 1;
178
188
  }
179
- if (selector.attrName) {
180
- const selectorAttrName = selector.attrName;
181
- const matchedAttrNameList = Array.from(el.attributes).map(attr => {
182
- const attrName = attr.name;
183
- const matchedAttrName = regexSelectorMatches(selectorAttrName, attrName, isPureHTMLElement(el));
189
+ const isPure = isPureHTMLElement(el);
190
+ if (selector.attrName || selector.attrValue) {
191
+ const matchedAttrList = [...el.attributes]
192
+ .map(attr => {
193
+ const matchedAttrName = regexSelectorMatches(selector.attrName, attr.name, isPure);
194
+ if (selector.attrName && !matchedAttrName) {
195
+ return null;
196
+ }
197
+ const matchedAttrValue = regexSelectorMatches(selector.attrValue, attr.value, isPure);
198
+ if (selector.attrValue && !matchedAttrValue) {
199
+ return null;
200
+ }
184
201
  if (matchedAttrName) {
185
202
  delete matchedAttrName.$0;
186
- data = {
187
- ...data,
188
- ...matchedAttrName,
189
- };
190
- specifiedAttr.set(attrName, '');
191
203
  }
192
- return matchedAttrName;
193
- });
194
- if (!matchedAttrNameList.some(_ => !!_)) {
195
- matched = false;
196
- }
197
- }
198
- if (selector.attrValue) {
199
- const selectorAttrValue = selector.attrValue;
200
- const matchedAttrValueList = Array.from(el.attributes).map(attr => {
201
- const attrName = attr.name;
202
- const attrValue = attr.value;
203
- const matchedAttrValue = regexSelectorMatches(selectorAttrValue, attrValue, isPureHTMLElement(el));
204
204
  if (matchedAttrValue) {
205
205
  delete matchedAttrValue.$0;
206
- data = {
207
- ...data,
208
- ...matchedAttrValue,
209
- };
210
- specifiedAttr.set(attrName, attrValue);
211
206
  }
212
- return matchedAttrValue;
213
- });
214
- if (!matchedAttrValueList.some(_ => !!_)) {
207
+ data = {
208
+ ...data,
209
+ ...matchedAttrName,
210
+ ...matchedAttrValue,
211
+ };
212
+ specifiedAttr.set(attr.name, matchedAttrValue ? attr.value : '');
213
+ return matchedAttrValue ?? matchedAttrName ?? null;
214
+ })
215
+ .filter((a) => !!a);
216
+ if (matchedAttrList.length === 0) {
215
217
  matched = false;
216
218
  }
217
219
  }
218
- const attrSelector = Array.from(specifiedAttr.entries())
220
+ const attrSelector = [...specifiedAttr.entries()]
219
221
  .map(([name, value]) => {
220
222
  return `[${name}${value ? `="${value}"` : ''}]`;
221
223
  })
@@ -1,3 +1,3 @@
1
- export declare function regexSelectorMatches(reg: string, raw: string, ignoreCase: boolean): {
1
+ export declare function regexSelectorMatches(reg: string | undefined, raw: string, ignoreCase: boolean): {
2
2
  [x: string]: string;
3
3
  } | null;
@@ -1,4 +1,7 @@
1
1
  export function regexSelectorMatches(reg, raw, ignoreCase) {
2
+ if (!reg) {
3
+ return null;
4
+ }
2
5
  const res = {};
3
6
  const pattern = toRegexp(reg);
4
7
  const regex = new RegExp(pattern instanceof RegExp ? pattern : `^${pattern.trim()}$`, ignoreCase ? 'i' : undefined);
@@ -6,14 +9,15 @@ export function regexSelectorMatches(reg, raw, ignoreCase) {
6
9
  if (!matched) {
7
10
  return null;
8
11
  }
9
- matched.forEach((val, i) => (res[`$${i}`] = val));
12
+ for (const [i, val] of matched.entries())
13
+ res[`$${i}`] = val;
10
14
  return {
11
15
  ...res,
12
16
  ...matched.groups,
13
17
  };
14
18
  }
15
19
  function toRegexp(pattern) {
16
- const matched = pattern.match(/^\/(.+)\/([ig]*)$/i);
20
+ const matched = pattern.match(/^\/(.+)\/([gi]*)$/i);
17
21
  if (matched && matched[1]) {
18
22
  return new RegExp(matched[1], matched[2]);
19
23
  }
package/lib/selector.js CHANGED
@@ -1,5 +1,15 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
1
12
  var _Selector_ruleset, _Ruleset_selectorGroup, _StructuredSelector_edge, _StructuredSelector_selector, _SelectorTarget_combinedFrom, _SelectorTarget_extended, _SelectorTarget_isAdded;
2
- import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
3
13
  import { resolveNamespace } from '@markuplint/ml-spec';
4
14
  import parser from 'postcss-selector-parser';
5
15
  import { compareSpecificity } from './compare-specificity.js';
@@ -45,11 +55,11 @@ class Ruleset {
45
55
  selectors.push(...root.nodes);
46
56
  }).processSync(selector);
47
57
  }
48
- catch (e) {
49
- if (e instanceof Error) {
58
+ catch (error) {
59
+ if (error instanceof Error) {
50
60
  throw new InvalidSelectorError(selector);
51
61
  }
52
- throw e;
62
+ throw error;
53
63
  }
54
64
  return new Ruleset(selectors, extended, 0);
55
65
  }
@@ -58,13 +68,11 @@ class Ruleset {
58
68
  __classPrivateFieldGet(this, _Ruleset_selectorGroup, "f").push(...selectors.map(selector => new StructuredSelector(selector, depth, extended)));
59
69
  const head = __classPrivateFieldGet(this, _Ruleset_selectorGroup, "f")[0];
60
70
  this.headCombinator = head?.headCombinator ?? null;
61
- if (this.headCombinator) {
62
- if (depth <= 0) {
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');
71
+ if (this.headCombinator && depth <= 0) {
72
+ if (__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f")[0]?.selector) {
73
+ throw new InvalidSelectorError(__classPrivateFieldGet(this, _Ruleset_selectorGroup, "f")[0]?.selector);
67
74
  }
75
+ throw new Error('Combinated selector depth is not expected');
68
76
  }
69
77
  }
70
78
  match(
@@ -90,12 +98,12 @@ class StructuredSelector {
90
98
  __classPrivateFieldSet(this, _StructuredSelector_edge, new SelectorTarget(extended, depth), "f");
91
99
  this.headCombinator =
92
100
  __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();
101
+ const nodes = [...__classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes];
94
102
  if (0 < depth && this.headCombinator) {
95
103
  // eslint-disable-next-line import/no-named-as-default-member
96
104
  nodes.unshift(parser.pseudo({ value: ':scope' }));
97
105
  }
98
- nodes.forEach(node => {
106
+ for (const node of nodes) {
99
107
  switch (node.type) {
100
108
  case 'combinator': {
101
109
  const combinedTarget = new SelectorTarget(extended, depth);
@@ -117,7 +125,7 @@ class StructuredSelector {
117
125
  __classPrivateFieldGet(this, _StructuredSelector_edge, "f").add(node);
118
126
  }
119
127
  }
120
- });
128
+ }
121
129
  }
122
130
  get selector() {
123
131
  return __classPrivateFieldGet(this, _StructuredSelector_selector, "f").nodes.join('');
@@ -512,7 +520,7 @@ _SelectorTarget_combinedFrom = new WeakMap(), _SelectorTarget_extended = new Wea
512
520
  function attrMatch(attr,
513
521
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
514
522
  el) {
515
- return Array.from(el.attributes).some(attrOfEl => {
523
+ return [...el.attributes].some(attrOfEl => {
516
524
  if (attr.attribute !== attrOfEl.localName) {
517
525
  return false;
518
526
  }
@@ -632,8 +640,8 @@ scope, extended, depth) {
632
640
  return {
633
641
  specificity,
634
642
  matched: matched.length > 0,
635
- nodes: matched.map(m => m.nodes).flat(),
636
- has: matched.map(m => m.has).flat(),
643
+ nodes: matched.flatMap(m => m.nodes),
644
+ has: matched.flatMap(m => m.has),
637
645
  };
638
646
  }
639
647
  case ':has': {
@@ -642,9 +650,7 @@ scope, extended, depth) {
642
650
  switch (ruleset.headCombinator) {
643
651
  case '+':
644
652
  case '~': {
645
- const has = getSiblings(el)
646
- .map(sib => ruleset.match(sib, el).filter((m) => m.matched))
647
- .flat();
653
+ const has = getSiblings(el).flatMap(sib => ruleset.match(sib, el).filter((m) => m.matched));
648
654
  if (has.length > 0) {
649
655
  return {
650
656
  specificity,
@@ -659,9 +665,7 @@ scope, extended, depth) {
659
665
  };
660
666
  }
661
667
  default: {
662
- const has = getDescendants(el)
663
- .map(sib => ruleset.match(sib, el).filter((m) => m.matched))
664
- .flat();
668
+ const has = getDescendants(el).flatMap(sib => ruleset.match(sib, el).filter((m) => m.matched));
665
669
  if (has.length > 0) {
666
670
  return {
667
671
  specificity,
@@ -684,8 +688,8 @@ scope, extended, depth) {
684
688
  return {
685
689
  specificity: [0, 0, 0],
686
690
  matched: matched.length > 0,
687
- nodes: matched.map(m => m.nodes).flat(),
688
- has: matched.map(m => m.has).flat(),
691
+ nodes: matched.flatMap(m => m.nodes),
692
+ has: matched.flatMap(m => m.has),
689
693
  };
690
694
  }
691
695
  case ':scope': {
@@ -747,6 +751,7 @@ scope, extended, depth) {
747
751
  case ':nth-col': {
748
752
  throw new Error(`Unsupported pseudo ${pseudo.toString()} selector yet. If you want it, please request it as the issue (https://github.com/markuplint/markuplint/issues/new).`);
749
753
  }
754
+ /* eslint-disable unicorn/no-useless-switch-case */
750
755
  case ':dir':
751
756
  case ':lang':
752
757
  case ':any-link':
@@ -780,6 +785,7 @@ scope, extended, depth) {
780
785
  }
781
786
  throw new Error(`Unsupported pseudo ${pseudo.toString()} selector.`);
782
787
  }
788
+ /* eslint-enable unicorn/no-useless-switch-case */
783
789
  }
784
790
  }
785
791
  function isScope(
@@ -792,22 +798,17 @@ scope) {
792
798
  function getDescendants(
793
799
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
794
800
  el, includeSelf = false) {
795
- return [
796
- ...Array.from(el.children)
797
- .map(child => getDescendants(child, true))
798
- .flat(),
799
- ...(includeSelf ? [el] : []),
800
- ];
801
+ return [...[...el.children].flatMap(child => getDescendants(child, true)), ...(includeSelf ? [el] : [])];
801
802
  }
802
803
  function getSiblings(
803
804
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
804
805
  el) {
805
- return Array.from(el.parentElement?.children ?? []);
806
+ return [...(el.parentElement?.children ?? [])];
806
807
  }
807
808
  function getSpecificity(
808
809
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
809
810
  results) {
810
- let specificity = undefined;
811
+ let specificity;
811
812
  for (const result of results) {
812
813
  if (specificity) {
813
814
  const order = compareSpecificity(specificity, result.specificity);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/selector",
3
- "version": "4.0.0-alpha.1",
3
+ "version": "4.0.0-alpha.10",
4
4
  "description": "Extended W3C Selectors matcher",
5
5
  "repository": "git@github.com:markuplint/markuplint.git",
6
6
  "author": "Yusuke Hirao <yusukehirao@me.com>",
@@ -25,16 +25,15 @@
25
25
  "clean": "tsc --build --clean"
26
26
  },
27
27
  "dependencies": {
28
- "@markuplint/ml-spec": "4.0.0-alpha.1",
29
- "@types/debug": "^4.1.8",
28
+ "@markuplint/ml-spec": "4.0.0-alpha.10",
29
+ "@types/debug": "^4.1.12",
30
30
  "debug": "^4.3.4",
31
- "postcss-selector-parser": "^6.0.13",
32
- "tslib": "^2.6.1",
33
- "type-fest": "^4.1.0"
31
+ "postcss-selector-parser": "^6.0.15",
32
+ "type-fest": "^4.10.1"
34
33
  },
35
34
  "devDependencies": {
36
- "@types/jsdom": "21.1.1",
37
- "jsdom": "22.1.0"
35
+ "@types/jsdom": "21.1.6",
36
+ "jsdom": "24.0.0"
38
37
  },
39
- "gitHead": "22502ee22a378ae766033d687dbc0443e5ed35dc"
38
+ "gitHead": "b41153ea665aa8f091daf6114a06047f4ccb8350"
40
39
  }