@vltpkg/dss-parser 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,9 +27,11 @@ const ast = parse(':root > *')
27
27
  - dangling combinators, e.g. `:root >`, `> >`
28
28
  - bare words, strings, empty ids / attributes, e.g. `foo`, `.dev`,
29
29
  `"foo"`, `#`, `[]`
30
+ - a part selector (`:skill()`) with an empty argument, not ending a
31
+ top-level selector, or inside `:not()`/`:is()`/`:has()`
30
32
 
31
- `:is()` arguments are a forgiving list: only the last group above is
32
- rejected there.
33
+ `:is()` arguments are a forgiving list: only the bare words group and
34
+ the part selector rule apply there.
33
35
 
34
36
  Pass `{ loose: true }` to skip the DSS checks (malformed syntax still
35
37
  throws):
@@ -38,5 +40,5 @@ throws):
38
40
  parse('#a, :unknown', { loose: true }) // no throw
39
41
  ```
40
42
 
41
- Supported names are exported as `pseudoClassNames`, `combinatorNames`
42
- and `attributeOperatorNames`.
43
+ Supported names are exported as `pseudoClassNames`, `combinatorNames`,
44
+ `attributeOperatorNames` and `partPseudoNames`.
package/dist/grammar.d.ts CHANGED
@@ -1,8 +1,15 @@
1
1
  /**
2
2
  * Pseudo-class names supported by DSS, without the leading `:`.
3
3
  */
4
- export declare const pseudoClassNames: readonly ["abandoned", "attr", "built", "confused", "cve", "cwe", "debug", "deprecated", "dev", "diff", "dist", "dynamic", "empty", "entropic", "env", "eval", "fs", "has", "host", "hostname", "is", "license", "link", "malware", "minified", "missing", "native", "network", "not", "obfuscated", "optional", "outdated", "overridden", "path", "peer", "prerelease", "private", "prod", "project", "published", "registry", "root", "scanned", "scope", "score", "scripts", "semver", "sev", "severity", "shell", "shrinkwrap", "spec", "squat", "suspicious", "tracker", "trivial", "type", "undesirable", "unknown", "unmaintained", "unpopular", "unstable", "v", "vuln", "vulnerable", "workspace"];
4
+ export declare const pseudoClassNames: readonly ["abandoned", "attr", "built", "confused", "cve", "cwe", "debug", "deprecated", "dev", "diff", "dist", "dynamic", "empty", "entropic", "env", "eval", "fs", "has", "host", "hostname", "is", "license", "link", "malware", "minified", "missing", "native", "network", "not", "obfuscated", "optional", "outdated", "overridden", "path", "peer", "prerelease", "private", "prod", "project", "published", "registry", "root", "scanned", "scope", "score", "scripts", "semver", "sev", "severity", "shell", "shrinkwrap", "skill", "skills", "spec", "squat", "suspicious", "tracker", "trivial", "type", "undesirable", "unknown", "unmaintained", "unpopular", "unstable", "v", "vuln", "vulnerable", "workspace"];
5
5
  export type PseudoClassName = (typeof pseudoClassNames)[number];
6
+ /**
7
+ * Part selectors: pseudo-classes that pick a part of the packages
8
+ * their selector matched, e.g. `:skill()`. They must end a top-level
9
+ * selector.
10
+ */
11
+ export declare const partPseudoNames: readonly ["skill"];
12
+ export type PartPseudoName = (typeof partPseudoNames)[number];
6
13
  /**
7
14
  * Combinators supported by DSS.
8
15
  */
package/dist/grammar.js CHANGED
@@ -53,6 +53,8 @@ export const pseudoClassNames = [
53
53
  'severity',
54
54
  'shell',
55
55
  'shrinkwrap',
56
+ 'skill',
57
+ 'skills',
56
58
  'spec',
57
59
  'squat',
58
60
  'suspicious',
@@ -69,6 +71,12 @@ export const pseudoClassNames = [
69
71
  'vulnerable',
70
72
  'workspace',
71
73
  ];
74
+ /**
75
+ * Part selectors: pseudo-classes that pick a part of the packages
76
+ * their selector matched, e.g. `:skill()`. They must end a top-level
77
+ * selector.
78
+ */
79
+ export const partPseudoNames = ['skill'];
72
80
  /**
73
81
  * Combinators supported by DSS.
74
82
  */
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import postcssSelectorParser from 'postcss-selector-parser';
2
2
  import { syntaxError } from '@vltpkg/error-cause';
3
- import { attributeOperatorNames, combinatorNames, pseudoClassNames, } from "./grammar.js";
3
+ import { attributeOperatorNames, combinatorNames, partPseudoNames, pseudoClassNames, } from "./grammar.js";
4
4
  import { asSelectorNode, isAttributeNode, isCombinatorNode, isPseudoNode, isStringNode, isTagNode, } from "./types.js";
5
5
  export * from "./types.js";
6
6
  export * from "./grammar.js";
@@ -25,6 +25,7 @@ const pseudoCleanUpNeeded = new Set([
25
25
  ]);
26
26
  const hasParamsToEscape = (node) => pseudoCleanUpNeeded.has(node.value);
27
27
  const pseudoClasses = new Set(pseudoClassNames);
28
+ const partPseudos = new Set(partPseudoNames);
28
29
  const combinators = new Set(combinatorNames);
29
30
  const attributeOperators = new Set(attributeOperatorNames);
30
31
  // pseudo-classes taking selector args, all others take strings
@@ -33,9 +34,10 @@ const invalid = (message, found) => syntaxError(message, { code: 'EQUERY', found
33
34
  /**
34
35
  * Checks a parsed selector against the DSS grammar.
35
36
  * `forgiving`: inside `:is()`, only bare words / strings / empty
36
- * `#` `[]` are rejected.
37
+ * `#` `[]` and part selectors are rejected.
38
+ * `nested`: inside `:not()`/`:is()`/`:has()` (part selectors rejected).
37
39
  */
38
- const validate = (selector, query, forgiving = false) => {
40
+ const validate = (selector, query, forgiving = false, nested = false) => {
39
41
  const nodes = selector.nodes.filter(n => n.type !== 'comment');
40
42
  if (!nodes.length && !forgiving) {
41
43
  throw invalid('Empty selector', query);
@@ -68,9 +70,19 @@ const validate = (selector, query, forgiving = false) => {
68
70
  return;
69
71
  throw invalid(`Unsupported pseudo-class: ${node.value}`, node.value);
70
72
  }
73
+ if (partPseudos.has(name)) {
74
+ if (nested || i < nodes.length - 1) {
75
+ throw invalid(`:${name}() must end a top-level selector`, node.value);
76
+ }
77
+ // `:skill`, `:skill()`, `:skill(a,)`
78
+ if (!node.nodes.length ||
79
+ node.nodes.some(s => s.nodes.every(n => n.type === 'comment'))) {
80
+ throw invalid(`Missing ${name} name in :${name}()`, node.value);
81
+ }
82
+ }
71
83
  if (selectorPseudos.has(name)) {
72
84
  for (const n of node.nodes) {
73
- validate(asSelectorNode(n), query, forgiving || name === 'is');
85
+ validate(asSelectorNode(n), query, forgiving || name === 'is', true);
74
86
  }
75
87
  }
76
88
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vltpkg/dss-parser",
3
3
  "description": "The Dependency Selector Syntax (DSS) parser",
4
- "version": "1.4.0",
4
+ "version": "1.6.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/vltpkg/vltpkg.git",
@@ -13,7 +13,7 @@
13
13
  "url": "http://vlt.sh"
14
14
  },
15
15
  "dependencies": {
16
- "@vltpkg/error-cause": "1.4.0",
16
+ "@vltpkg/error-cause": "1.6.0",
17
17
  "postcss-selector-parser": "^7.1.1"
18
18
  },
19
19
  "devDependencies": {