@tbela99/css-parser 0.8.0 → 0.9.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.
Files changed (59) hide show
  1. package/.editorconfig +484 -0
  2. package/README.md +5 -3
  3. package/dist/index-umd-web.js +3272 -1898
  4. package/dist/index.cjs +3272 -1898
  5. package/dist/index.d.ts +48 -11
  6. package/dist/lib/ast/expand.js +14 -2
  7. package/dist/lib/ast/math/expression.js +1 -1
  8. package/dist/lib/ast/minify.js +30 -16
  9. package/dist/lib/ast/types.js +1 -0
  10. package/dist/lib/ast/walk.js +12 -0
  11. package/dist/lib/parser/declaration/map.js +59 -52
  12. package/dist/lib/parser/declaration/set.js +0 -12
  13. package/dist/lib/parser/parse.js +140 -101
  14. package/dist/lib/parser/tokenize.js +15 -3
  15. package/dist/lib/renderer/color/hex.js +1 -1
  16. package/dist/lib/renderer/color/hsl.js +1 -1
  17. package/dist/lib/renderer/color/hwb.js +2 -2
  18. package/dist/lib/renderer/color/lab.js +1 -1
  19. package/dist/lib/renderer/color/lch.js +1 -1
  20. package/dist/lib/renderer/color/oklab.js +2 -2
  21. package/dist/lib/renderer/color/oklch.js +1 -1
  22. package/dist/lib/renderer/color/p3.js +1 -1
  23. package/dist/lib/renderer/color/prophotoRgb.js +1 -1
  24. package/dist/lib/renderer/color/prophotorgb.js +1 -1
  25. package/dist/lib/renderer/color/rgb.js +1 -1
  26. package/dist/lib/renderer/color/srgb.js +2 -2
  27. package/dist/lib/renderer/color/utils/constants.js +1 -1
  28. package/dist/lib/renderer/color/xyz.js +1 -1
  29. package/dist/lib/renderer/render.js +34 -6
  30. package/dist/lib/syntax/syntax.js +336 -1
  31. package/dist/lib/validation/at-rules/container.js +353 -0
  32. package/dist/lib/validation/at-rules/counter-style.js +2 -2
  33. package/dist/lib/validation/at-rules/custom-media.js +52 -0
  34. package/dist/lib/validation/at-rules/else.js +5 -0
  35. package/dist/lib/validation/at-rules/font-feature-values.js +3 -0
  36. package/dist/lib/validation/at-rules/import.js +3 -0
  37. package/dist/lib/validation/at-rules/layer.js +3 -0
  38. package/dist/lib/validation/at-rules/media.js +117 -29
  39. package/dist/lib/validation/at-rules/supports.js +11 -11
  40. package/dist/lib/validation/at-rules/when.js +178 -0
  41. package/dist/lib/validation/atrule.js +25 -10
  42. package/dist/lib/validation/config.js +20 -15
  43. package/dist/lib/validation/config.json.js +162 -42
  44. package/dist/lib/validation/declaration.js +39 -9
  45. package/dist/lib/validation/parser/parse.js +91 -13
  46. package/dist/lib/validation/parser/types.js +1 -0
  47. package/dist/lib/validation/selector.js +6 -3
  48. package/dist/lib/validation/syntax.js +50 -4
  49. package/dist/lib/validation/syntaxes/complex-selector-list.js +16 -12
  50. package/dist/lib/validation/syntaxes/complex-selector.js +17 -247
  51. package/dist/lib/validation/syntaxes/compound-selector.js +226 -0
  52. package/dist/lib/validation/syntaxes/image.js +29 -0
  53. package/dist/lib/validation/syntaxes/keyframe-block-list.js +1 -1
  54. package/dist/lib/validation/syntaxes/keyframe-selector.js +1 -1
  55. package/dist/lib/validation/syntaxes/relative-selector-list.js +43 -13
  56. package/dist/lib/validation/utils/list.js +2 -2
  57. package/dist/node/index.js +1 -1
  58. package/dist/web/index.js +1 -1
  59. package/package.json +7 -7
@@ -0,0 +1,226 @@
1
+ import { ValidationLevel, EnumToken } from '../../ast/types.js';
2
+ import '../../ast/minify.js';
3
+ import '../../ast/walk.js';
4
+ import '../../parser/parse.js';
5
+ import { mozExtensions, webkitExtensions } from '../../syntax/syntax.js';
6
+ import '../../parser/utils/config.js';
7
+ import '../../renderer/color/utils/constants.js';
8
+ import '../../renderer/sourcemap/lib/encode.js';
9
+ import { consumeWhitespace } from '../utils/whitespace.js';
10
+ import { getSyntaxConfig } from '../config.js';
11
+
12
+ function validateCompoundSelector(tokens, root, options) {
13
+ if (tokens.length == 0) {
14
+ // @ts-ignore
15
+ return {
16
+ valid: ValidationLevel.Drop,
17
+ matches: [],
18
+ // @ts-ignore
19
+ node: root,
20
+ // @ts-ignore
21
+ syntax: null,
22
+ error: 'expected selector',
23
+ tokens
24
+ };
25
+ }
26
+ tokens = tokens.slice();
27
+ consumeWhitespace(tokens);
28
+ const config = getSyntaxConfig();
29
+ let match = 0;
30
+ let length = tokens.length;
31
+ while (tokens.length > 0) {
32
+ while (tokens.length > 0 && tokens[0].typ == EnumToken.NestingSelectorTokenType) {
33
+ if (!options?.nestedSelector) {
34
+ // @ts-ignore
35
+ return {
36
+ valid: ValidationLevel.Drop,
37
+ matches: [],
38
+ // @ts-ignore
39
+ node: tokens[0],
40
+ syntax: null,
41
+ error: 'nested selector not allowed',
42
+ tokens
43
+ };
44
+ }
45
+ match++;
46
+ tokens.shift();
47
+ consumeWhitespace(tokens);
48
+ }
49
+ // <type-selector>
50
+ while (tokens.length > 0 &&
51
+ [
52
+ EnumToken.IdenTokenType,
53
+ EnumToken.NameSpaceAttributeTokenType,
54
+ EnumToken.ClassSelectorTokenType,
55
+ EnumToken.HashTokenType,
56
+ EnumToken.UniversalSelectorTokenType
57
+ ].includes(tokens[0].typ)) {
58
+ match++;
59
+ tokens.shift();
60
+ consumeWhitespace(tokens);
61
+ }
62
+ while (tokens.length > 0 && tokens[0].typ == EnumToken.PseudoClassFuncTokenType) {
63
+ if (!mozExtensions.has(tokens[0].val + '()') &&
64
+ !webkitExtensions.has(tokens[0].val + '()') &&
65
+ !((tokens[0].val + '()') in config.selectors)) {
66
+ if (!options?.lenient || /^(:?)-webkit-/.test(tokens[0].val)) {
67
+ // @ts-ignore
68
+ return {
69
+ valid: ValidationLevel.Drop,
70
+ matches: [],
71
+ // @ts-ignore
72
+ node: tokens[0],
73
+ syntax: null,
74
+ error: 'unknown pseudo-class: ' + tokens[0].val + '()',
75
+ tokens
76
+ };
77
+ }
78
+ }
79
+ match++;
80
+ tokens.shift();
81
+ consumeWhitespace(tokens);
82
+ }
83
+ while (tokens.length > 0 && tokens[0].typ == EnumToken.PseudoClassTokenType) {
84
+ const isPseudoElement = tokens[0].val.startsWith('::');
85
+ if (
86
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/WebKit_Extensions#pseudo-elements
87
+ !(isPseudoElement && tokens[0].val.startsWith('::-webkit-')) &&
88
+ !mozExtensions.has(tokens[0].val) &&
89
+ !webkitExtensions.has(tokens[0].val) &&
90
+ !(tokens[0].val in config.selectors) &&
91
+ !(!isPseudoElement &&
92
+ (':' + tokens[0].val) in config.selectors)) {
93
+ if (!options?.lenient || /^(:?)-webkit-/.test(tokens[0].val)) {
94
+ // @ts-ignore
95
+ return {
96
+ valid: ValidationLevel.Drop,
97
+ matches: [],
98
+ // @ts-ignore
99
+ node: tokens[0],
100
+ syntax: null,
101
+ error: 'unknown pseudo-class: ' + tokens[0].val,
102
+ tokens
103
+ };
104
+ }
105
+ }
106
+ match++;
107
+ tokens.shift();
108
+ consumeWhitespace(tokens);
109
+ }
110
+ while (tokens.length > 0 && tokens[0].typ == EnumToken.AttrTokenType) {
111
+ const children = tokens[0].chi.slice();
112
+ consumeWhitespace(children);
113
+ if (children.length == 0) {
114
+ // @ts-ignore
115
+ return {
116
+ valid: ValidationLevel.Drop,
117
+ matches: [],
118
+ node: tokens[0],
119
+ syntax: null,
120
+ error: 'invalid attribute selector',
121
+ tokens
122
+ };
123
+ }
124
+ if (![
125
+ EnumToken.IdenTokenType,
126
+ EnumToken.NameSpaceAttributeTokenType,
127
+ EnumToken.MatchExpressionTokenType
128
+ ].includes(children[0].typ)) {
129
+ // @ts-ignore
130
+ return {
131
+ valid: ValidationLevel.Drop,
132
+ matches: [],
133
+ node: tokens[0],
134
+ syntax: null,
135
+ error: 'invalid attribute selector',
136
+ tokens
137
+ };
138
+ }
139
+ if (children[0].typ == EnumToken.MatchExpressionTokenType) {
140
+ if (children.length != 1) {
141
+ return {
142
+ valid: ValidationLevel.Drop,
143
+ matches: [],
144
+ node: tokens[0],
145
+ syntax: null,
146
+ error: 'invalid <attribute-selector>',
147
+ tokens
148
+ };
149
+ }
150
+ if (![
151
+ EnumToken.IdenTokenType,
152
+ EnumToken.NameSpaceAttributeTokenType
153
+ ].includes(children[0].l.typ) ||
154
+ ![
155
+ EnumToken.EqualMatchTokenType, EnumToken.DashMatchTokenType,
156
+ EnumToken.StartMatchTokenType, EnumToken.ContainMatchTokenType,
157
+ EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType
158
+ ].includes(children[0].op.typ) ||
159
+ ![
160
+ EnumToken.StringTokenType,
161
+ EnumToken.IdenTokenType
162
+ ].includes(children[0].r.typ)) {
163
+ // @ts-ignore
164
+ return {
165
+ valid: ValidationLevel.Drop,
166
+ matches: [],
167
+ node: tokens[0],
168
+ syntax: null,
169
+ error: 'invalid attribute selector',
170
+ tokens
171
+ };
172
+ }
173
+ if (children[0].attr != null && !['i', 's'].includes(children[0].attr)) {
174
+ // @ts-ignore
175
+ return {
176
+ valid: ValidationLevel.Drop,
177
+ matches: [],
178
+ node: tokens[0],
179
+ syntax: null,
180
+ error: 'invalid attribute selector',
181
+ tokens
182
+ };
183
+ }
184
+ }
185
+ match++;
186
+ tokens.shift();
187
+ consumeWhitespace(tokens);
188
+ }
189
+ if (length == tokens.length) {
190
+ return {
191
+ valid: ValidationLevel.Drop,
192
+ matches: [],
193
+ // @ts-ignore
194
+ node: tokens[0],
195
+ // @ts-ignore
196
+ syntax: null,
197
+ error: 'expected compound selector',
198
+ tokens
199
+ };
200
+ }
201
+ length = tokens.length;
202
+ }
203
+ return match == 0 ? {
204
+ valid: ValidationLevel.Drop,
205
+ matches: [],
206
+ // @ts-ignore
207
+ node: root,
208
+ // @ts-ignore
209
+ syntax: null,
210
+ error: 'expected compound selector',
211
+ tokens
212
+ } :
213
+ // @ts-ignore
214
+ {
215
+ valid: ValidationLevel.Valid,
216
+ matches: [],
217
+ // @ts-ignore
218
+ node: root,
219
+ // @ts-ignore
220
+ syntax: null,
221
+ error: null,
222
+ tokens
223
+ };
224
+ }
225
+
226
+ export { validateCompoundSelector };
@@ -0,0 +1,29 @@
1
+ import { EnumToken, ValidationLevel } from '../../ast/types.js';
2
+ import '../../ast/minify.js';
3
+ import '../../ast/walk.js';
4
+ import '../../parser/parse.js';
5
+ import '../../renderer/color/utils/constants.js';
6
+ import '../../renderer/sourcemap/lib/encode.js';
7
+ import '../../parser/utils/config.js';
8
+ import { validateSyntax } from '../syntax.js';
9
+ import { getParsedSyntax } from '../config.js';
10
+ import { validateURL } from './url.js';
11
+
12
+ function validateImage(token) {
13
+ if (token.typ == EnumToken.UrlFunctionTokenType) {
14
+ return validateURL(token);
15
+ }
16
+ if (token.typ == EnumToken.ImageFunctionTokenType) {
17
+ return validateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, token.val + '()'), token.chi);
18
+ }
19
+ return {
20
+ valid: ValidationLevel.Drop,
21
+ matches: [],
22
+ node: token,
23
+ syntax: 'image()',
24
+ error: 'expected <image> or <url>',
25
+ tokens: []
26
+ };
27
+ }
28
+
29
+ export { validateImage };
@@ -7,7 +7,7 @@ import '../../renderer/sourcemap/lib/encode.js';
7
7
  import '../../parser/utils/config.js';
8
8
  import { validateKeyframeSelector } from './keyframe-selector.js';
9
9
 
10
- function validateKeyframeBlockList(tokens, atRule) {
10
+ function validateKeyframeBlockList(tokens, atRule, options) {
11
11
  let i = 0;
12
12
  let j = 0;
13
13
  let result = null;
@@ -7,7 +7,7 @@ import '../../renderer/color/utils/constants.js';
7
7
  import '../../renderer/sourcemap/lib/encode.js';
8
8
  import '../../parser/utils/config.js';
9
9
 
10
- function validateKeyframeSelector(tokens, atRule) {
10
+ function validateKeyframeSelector(tokens, atRule, options) {
11
11
  consumeWhitespace(tokens);
12
12
  if (tokens.length == 0) {
13
13
  // @ts-ignore
@@ -1,4 +1,4 @@
1
- import { EnumToken, ValidationLevel } from '../../ast/types.js';
1
+ import { ValidationLevel } from '../../ast/types.js';
2
2
  import '../../ast/minify.js';
3
3
  import '../../ast/walk.js';
4
4
  import '../../parser/parse.js';
@@ -6,22 +6,52 @@ import '../../renderer/color/utils/constants.js';
6
6
  import '../../renderer/sourcemap/lib/encode.js';
7
7
  import '../../parser/utils/config.js';
8
8
  import { validateRelativeSelector } from './relative-selector.js';
9
+ import { consumeWhitespace } from '../utils/whitespace.js';
10
+ import { splitTokenList } from '../utils/list.js';
9
11
 
10
12
  function validateRelativeSelectorList(tokens, root, options) {
11
- let i = 0;
12
- let j = 0;
13
- let result = null;
14
- while (i + 1 < tokens.length) {
15
- if (tokens[++i].typ == EnumToken.CommaTokenType) {
16
- result = validateRelativeSelector(tokens.slice(j, i), root, options);
17
- if (result.valid == ValidationLevel.Drop) {
18
- return result;
19
- }
20
- j = i + 1;
21
- i = j;
13
+ tokens = tokens.slice();
14
+ consumeWhitespace(tokens);
15
+ if (tokens.length == 0) {
16
+ return {
17
+ valid: ValidationLevel.Drop,
18
+ matches: [],
19
+ // @ts-ignore
20
+ node: root,
21
+ // @ts-ignore
22
+ syntax: null,
23
+ error: 'expecting relative selector list',
24
+ tokens
25
+ };
26
+ }
27
+ for (const t of splitTokenList(tokens)) {
28
+ if (t.length == 0) {
29
+ return {
30
+ valid: ValidationLevel.Drop,
31
+ matches: [],
32
+ // @ts-ignore
33
+ node: root,
34
+ // @ts-ignore
35
+ syntax: null,
36
+ error: 'unexpected comma',
37
+ tokens
38
+ };
39
+ }
40
+ const result = validateRelativeSelector(t, root, options);
41
+ if (result.valid == ValidationLevel.Drop) {
42
+ return result;
22
43
  }
23
44
  }
24
- return validateRelativeSelector(i == j ? tokens.slice(i) : tokens.slice(j, i + 1), root, options);
45
+ return {
46
+ valid: ValidationLevel.Valid,
47
+ matches: [],
48
+ // @ts-ignore
49
+ node: root,
50
+ // @ts-ignore
51
+ syntax: null,
52
+ error: '',
53
+ tokens
54
+ };
25
55
  }
26
56
 
27
57
  export { validateRelativeSelectorList };
@@ -6,12 +6,12 @@ import '../../renderer/color/utils/constants.js';
6
6
  import '../../renderer/sourcemap/lib/encode.js';
7
7
  import '../../parser/utils/config.js';
8
8
 
9
- function splitTokenList(tokenList) {
9
+ function splitTokenList(tokenList, split = [EnumToken.CommaTokenType]) {
10
10
  return tokenList.reduce((acc, curr) => {
11
11
  if (curr.typ == EnumToken.CommentTokenType) {
12
12
  return acc;
13
13
  }
14
- if (curr.typ == EnumToken.CommaTokenType) {
14
+ if (split.includes(curr.typ)) {
15
15
  acc.push([]);
16
16
  }
17
17
  else {
@@ -13,7 +13,7 @@ import '../lib/validation/config.js';
13
13
  import '../lib/validation/parser/types.js';
14
14
  import '../lib/validation/parser/parse.js';
15
15
  import '../lib/validation/syntaxes/complex-selector.js';
16
- import { resolve, dirname } from '../lib/fs/resolve.js';
16
+ import { dirname, resolve } from '../lib/fs/resolve.js';
17
17
  import { load } from './load.js';
18
18
 
19
19
  /**
package/dist/web/index.js CHANGED
@@ -12,7 +12,7 @@ import '../lib/validation/config.js';
12
12
  import '../lib/validation/parser/types.js';
13
13
  import '../lib/validation/parser/parse.js';
14
14
  import '../lib/validation/syntaxes/complex-selector.js';
15
- import { resolve, dirname } from '../lib/fs/resolve.js';
15
+ import { dirname, resolve } from '../lib/fs/resolve.js';
16
16
  import { load } from './load.js';
17
17
 
18
18
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tbela99/css-parser",
3
3
  "description": "CSS parser for node and the browser",
4
- "version": "0.8.0",
4
+ "version": "v0.9.0",
5
5
  "exports": {
6
6
  ".": "./dist/node/index.js",
7
7
  "./umd": "./dist/index-umd-web.js",
@@ -56,15 +56,15 @@
56
56
  "@rollup/plugin-typescript": "^12.1.2",
57
57
  "@types/chai": "^5.0.1",
58
58
  "@types/mocha": "^10.0.10",
59
- "@types/node": "^22.10.2",
60
- "@types/web": "^0.0.187",
61
- "@web/test-runner": "^0.19.0",
59
+ "@types/node": "^22.13.5",
60
+ "@types/web": "^0.0.206",
61
+ "@web/test-runner": "^0.20.0",
62
62
  "@web/test-runner-playwright": "^0.11.0",
63
63
  "c8": "^10.1.3",
64
64
  "esno": "^4.8.0",
65
- "mocha": "^11.0.1",
66
- "playwright": "^1.49.1",
67
- "rollup": "^4.29.2",
65
+ "mocha": "^11.1.0",
66
+ "playwright": "^1.50.1",
67
+ "rollup": "^4.34.8",
68
68
  "rollup-plugin-dts": "^6.1.1",
69
69
  "tslib": "^2.8.1"
70
70
  }