@tbela99/css-parser 1.0.0 → 1.1.1-alpha4

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 (87) hide show
  1. package/CHANGELOG.md +269 -0
  2. package/README.md +16 -11
  3. package/dist/index-umd-web.js +3805 -1894
  4. package/dist/index.cjs +3806 -1895
  5. package/dist/index.d.ts +184 -57
  6. package/dist/lib/ast/expand.js +2 -1
  7. package/dist/lib/ast/features/calc.js +12 -1
  8. package/dist/lib/ast/features/inlinecssvariables.js +47 -24
  9. package/dist/lib/ast/features/prefix.js +117 -86
  10. package/dist/lib/ast/features/shorthand.js +29 -6
  11. package/dist/lib/ast/features/transform.js +10 -3
  12. package/dist/lib/ast/features/type.js +7 -0
  13. package/dist/lib/ast/math/expression.js +7 -1
  14. package/dist/lib/ast/math/math.js +6 -0
  15. package/dist/lib/ast/minify.js +165 -77
  16. package/dist/lib/ast/transform/compute.js +1 -0
  17. package/dist/lib/ast/transform/matrix.js +1 -0
  18. package/dist/lib/ast/types.js +26 -15
  19. package/dist/lib/ast/utils/utils.js +104 -0
  20. package/dist/lib/ast/walk.js +33 -7
  21. package/dist/lib/fs/resolve.js +10 -0
  22. package/dist/lib/parser/declaration/list.js +48 -45
  23. package/dist/lib/parser/declaration/map.js +1 -0
  24. package/dist/lib/parser/declaration/set.js +2 -1
  25. package/dist/lib/parser/parse.js +350 -279
  26. package/dist/lib/parser/tokenize.js +147 -72
  27. package/dist/lib/parser/utils/declaration.js +4 -3
  28. package/dist/lib/parser/utils/type.js +2 -1
  29. package/dist/lib/renderer/color/a98rgb.js +2 -1
  30. package/dist/lib/renderer/color/color-mix.js +10 -7
  31. package/dist/lib/renderer/color/color.js +171 -153
  32. package/dist/lib/renderer/color/hex.js +2 -1
  33. package/dist/lib/renderer/color/hsl.js +2 -1
  34. package/dist/lib/renderer/color/hwb.js +2 -1
  35. package/dist/lib/renderer/color/lab.js +2 -1
  36. package/dist/lib/renderer/color/lch.js +2 -1
  37. package/dist/lib/renderer/color/oklab.js +2 -1
  38. package/dist/lib/renderer/color/oklch.js +2 -1
  39. package/dist/lib/renderer/color/p3.js +2 -1
  40. package/dist/lib/renderer/color/rec2020.js +2 -1
  41. package/dist/lib/renderer/color/relativecolor.js +17 -11
  42. package/dist/lib/renderer/color/rgb.js +4 -3
  43. package/dist/lib/renderer/color/srgb.js +18 -17
  44. package/dist/lib/renderer/color/utils/components.js +6 -5
  45. package/dist/lib/renderer/color/utils/constants.js +47 -3
  46. package/dist/lib/renderer/color/xyz.js +2 -1
  47. package/dist/lib/renderer/color/xyzd50.js +2 -1
  48. package/dist/lib/renderer/render.js +48 -20
  49. package/dist/lib/syntax/syntax.js +257 -140
  50. package/dist/lib/validation/at-rules/container.js +75 -97
  51. package/dist/lib/validation/at-rules/counter-style.js +9 -8
  52. package/dist/lib/validation/at-rules/custom-media.js +13 -15
  53. package/dist/lib/validation/at-rules/document.js +22 -27
  54. package/dist/lib/validation/at-rules/font-feature-values.js +8 -8
  55. package/dist/lib/validation/at-rules/import.js +30 -81
  56. package/dist/lib/validation/at-rules/keyframes.js +18 -22
  57. package/dist/lib/validation/at-rules/layer.js +5 -5
  58. package/dist/lib/validation/at-rules/media.js +42 -52
  59. package/dist/lib/validation/at-rules/namespace.js +19 -23
  60. package/dist/lib/validation/at-rules/page-margin-box.js +15 -18
  61. package/dist/lib/validation/at-rules/page.js +8 -7
  62. package/dist/lib/validation/at-rules/supports.js +73 -82
  63. package/dist/lib/validation/at-rules/when.js +32 -36
  64. package/dist/lib/validation/atrule.js +15 -14
  65. package/dist/lib/validation/config.js +24 -1
  66. package/dist/lib/validation/config.json.js +611 -111
  67. package/dist/lib/validation/parser/parse.js +206 -212
  68. package/dist/lib/validation/parser/types.js +1 -1
  69. package/dist/lib/validation/selector.js +3 -3
  70. package/dist/lib/validation/syntax.js +984 -0
  71. package/dist/lib/validation/syntaxes/complex-selector-list.js +10 -11
  72. package/dist/lib/validation/syntaxes/complex-selector.js +10 -11
  73. package/dist/lib/validation/syntaxes/compound-selector.js +40 -50
  74. package/dist/lib/validation/syntaxes/family-name.js +9 -8
  75. package/dist/lib/validation/syntaxes/keyframe-block-list.js +4 -3
  76. package/dist/lib/validation/syntaxes/keyframe-selector.js +15 -18
  77. package/dist/lib/validation/syntaxes/layer-name.js +6 -5
  78. package/dist/lib/validation/syntaxes/relative-selector-list.js +7 -6
  79. package/dist/lib/validation/syntaxes/relative-selector.js +2 -1
  80. package/dist/lib/validation/syntaxes/url.js +18 -22
  81. package/dist/lib/validation/utils/list.js +2 -1
  82. package/dist/lib/validation/utils/whitespace.js +2 -1
  83. package/dist/node/index.js +4 -2
  84. package/dist/node/load.js +5 -0
  85. package/dist/web/index.js +4 -2
  86. package/dist/web/load.js +5 -0
  87. package/package.json +14 -13
@@ -1,121 +1,152 @@
1
- import { EnumToken } from '../types.js';
1
+ import { EnumToken, SyntaxValidationResult } from '../types.js';
2
2
  import { getSyntaxConfig } from '../../validation/config.js';
3
- import { ValidationTokenEnum } from '../../validation/parser/types.js';
3
+ import '../../validation/parser/types.js';
4
4
  import '../../validation/parser/parse.js';
5
- import '../minify.js';
5
+ import { splitRule, definedPropertySettings } from '../minify.js';
6
6
  import { walkValues } from '../walk.js';
7
- import '../../parser/parse.js';
8
- import '../../renderer/color/utils/constants.js';
9
- import '../../renderer/sourcemap/lib/encode.js';
7
+ import { parseAtRulePrelude, parseString } from '../../parser/parse.js';
8
+ import '../../parser/tokenize.js';
10
9
  import '../../parser/utils/config.js';
10
+ import { pseudoAliasMap } from '../../syntax/syntax.js';
11
+ import { renderToken } from '../../renderer/render.js';
12
+ import { funcLike } from '../../renderer/color/utils/constants.js';
11
13
  import '../../validation/syntaxes/complex-selector.js';
14
+ import { evaluateSyntax } from '../../validation/syntax.js';
12
15
 
13
16
  const config = getSyntaxConfig();
17
+ function replacePseudo(tokens) {
18
+ return tokens.map((raw) => raw.map(r => {
19
+ if (r.includes('(')) {
20
+ const index = r.indexOf('(');
21
+ const name = r.slice(0, index) + '()';
22
+ if (name in pseudoAliasMap) {
23
+ return pseudoAliasMap[name] + r.slice(index);
24
+ }
25
+ return r;
26
+ }
27
+ return r in pseudoAliasMap && pseudoAliasMap[r] in config["selectors" /* ValidationSyntaxGroupEnum.Selectors */] ? pseudoAliasMap[r] : r;
28
+ }));
29
+ }
30
+ function replaceAstNodes(tokens, root) {
31
+ let result = false;
32
+ for (const { value, parent } of walkValues(tokens, root)) {
33
+ if (value.typ == EnumToken.IdenTokenType || value.typ == EnumToken.PseudoClassFuncTokenType || value.typ == EnumToken.PseudoClassTokenType || value.typ == EnumToken.PseudoElementTokenType) {
34
+ let key = value.val + (value.typ == EnumToken.PseudoClassFuncTokenType ? '()' : '');
35
+ if (key in pseudoAliasMap) {
36
+ const isPseudClass = pseudoAliasMap[key].startsWith('::');
37
+ value.val = pseudoAliasMap[key];
38
+ if (value.typ == EnumToken.IdenTokenType &&
39
+ ['min-resolution', 'max-resolution'].includes(value.val) &&
40
+ parent?.typ == EnumToken.MediaQueryConditionTokenType &&
41
+ parent.r?.[0]?.typ == EnumToken.NumberTokenType) {
42
+ Object.assign(parent.r?.[0], {
43
+ typ: EnumToken.ResolutionTokenType,
44
+ unit: 'x',
45
+ });
46
+ }
47
+ else if (isPseudClass && value.typ == EnumToken.PseudoElementTokenType) {
48
+ // @ts-ignore
49
+ value.typ = EnumToken.PseudoClassTokenType;
50
+ }
51
+ result = true;
52
+ }
53
+ }
54
+ }
55
+ return result;
56
+ }
14
57
  class ComputePrefixFeature {
15
- static get ordering() {
58
+ get ordering() {
16
59
  return 2;
17
60
  }
61
+ get preProcess() {
62
+ return true;
63
+ }
64
+ get postProcess() {
65
+ return false;
66
+ }
18
67
  static register(options) {
19
68
  if (options.removePrefix) {
20
69
  // @ts-ignore
21
70
  options.features.push(new ComputePrefixFeature(options));
22
71
  }
23
72
  }
24
- run(ast) {
25
- // @ts-ignore
26
- const j = ast.chi.length;
27
- let k = 0;
28
- // @ts-ignore
29
- for (; k < j; k++) {
30
- // @ts-ignore
31
- const node = ast.chi[k];
32
- if (node.typ == EnumToken.DeclarationNodeType) {
33
- if (node.nam.charAt(0) == '-') {
34
- const match = node.nam.match(/^-([^-]+)-(.+)$/);
35
- if (match != null) {
36
- const nam = match[2];
37
- if (nam.toLowerCase() in config.declarations) {
38
- node.nam = nam;
73
+ run(node) {
74
+ if (node.typ == EnumToken.RuleNodeType) {
75
+ node.sel = replacePseudo(splitRule(node.sel)).reduce((acc, curr, index) => acc + (index > 0 ? ',' : '') + curr.join(''), '');
76
+ if (node.raw != null) {
77
+ node.raw = replacePseudo(node.raw);
78
+ }
79
+ if (node.optimized != null) {
80
+ node.optimized.selector = replacePseudo(node.optimized.selector);
81
+ }
82
+ if (node.tokens != null) {
83
+ replaceAstNodes(node.tokens);
84
+ }
85
+ }
86
+ else if (node.typ == EnumToken.DeclarationNodeType) {
87
+ if (node.nam.charAt(0) == '-') {
88
+ const match = node.nam.match(/^-([^-]+)-(.+)$/);
89
+ if (match != null) {
90
+ let nam = match[2];
91
+ if (!(nam in config.declarations)) {
92
+ if (node.nam in pseudoAliasMap) {
93
+ nam = pseudoAliasMap[node.nam];
39
94
  }
40
95
  }
41
- }
42
- if (node.nam.toLowerCase() in config.declarations) {
43
- for (const { value } of walkValues(node.val)) {
44
- if (value.typ == EnumToken.IdenTokenType && value.val.charAt(0) == '-' && value.val.charAt(1) != '-') {
45
- // @ts-ignore
46
- const values = config.declarations[node.nam].ast?.slice?.();
47
- const match = value.val.match(/^-(.*?)-(.*)$/);
48
- if (values != null && match != null) {
49
- const val = matchToken({ ...value, val: match[2] }, values);
50
- if (val != null) {
51
- // @ts-ignore
52
- value.val = val.val;
53
- }
54
- }
55
- }
96
+ if (nam in config.declarations) {
97
+ node.nam = nam;
56
98
  }
57
99
  }
58
100
  }
59
- }
60
- return ast;
61
- }
62
- }
63
- function matchToken(token, matches) {
64
- let result;
65
- for (let i = 0; i < matches.length; i++) {
66
- switch (matches[i].typ) {
67
- case ValidationTokenEnum.Whitespace:
68
- case ValidationTokenEnum.Comma:
69
- break;
70
- case ValidationTokenEnum.Keyword:
71
- if (token.typ == EnumToken.IdenTokenType && token.val == matches[i].val) {
72
- return token;
73
- }
74
- break;
75
- case ValidationTokenEnum.PropertyType:
76
- if (['ident', 'custom-ident'].includes(matches[i].val)) {
77
- if (token.typ == EnumToken.IdenTokenType && token.val == matches[i].val) {
78
- return token;
101
+ let hasPrefix = false;
102
+ for (const { value } of walkValues(node.val)) {
103
+ if ((value.typ == EnumToken.IdenTokenType || (value.typ != EnumToken.ParensTokenType && funcLike.includes(value.typ))) && value.val.match(/^-([^-]+)-(.+)$/) != null) {
104
+ if (value.val.endsWith('-gradient')) {
105
+ // not supported yet
106
+ break;
79
107
  }
108
+ hasPrefix = true;
109
+ break;
80
110
  }
81
- else {
82
- const val = matches[i].val;
83
- if (val in config.declarations || val in config.syntaxes) {
84
- // @ts-ignore
85
- result = matchToken(token, (config.syntaxes[val] ?? config.declarations[val]).ast.slice());
86
- if (result != null) {
87
- return result;
111
+ }
112
+ if (hasPrefix) {
113
+ const nodes = structuredClone(node.val);
114
+ for (const { value } of walkValues(nodes)) {
115
+ if ((value.typ == EnumToken.IdenTokenType || funcLike.includes(value.typ))) {
116
+ const match = value.val.match(/^-([^-]+)-(.+)$/);
117
+ if (match == null) {
118
+ continue;
88
119
  }
120
+ value.val = match[2];
89
121
  }
90
122
  }
91
- break;
92
- case ValidationTokenEnum.PipeToken:
93
- for (let j = 0; j < matches[i].chi.length; j++) {
94
- result = matchToken(token, matches[i].chi[j]);
95
- if (result != null) {
96
- return result;
97
- }
123
+ if (SyntaxValidationResult.Valid == evaluateSyntax({ ...node, val: nodes }, {}).valid) {
124
+ node.val = nodes;
98
125
  }
99
- break;
100
- case ValidationTokenEnum.ColumnToken:
101
- case ValidationTokenEnum.AmpersandToken:
102
- result = matchToken(token, matches[i].l);
103
- if (result == null) {
104
- result = matchToken(token, matches[i].r);
126
+ }
127
+ }
128
+ else if (node.typ == EnumToken.AtRuleNodeType || node.typ == EnumToken.KeyframeAtRuleNodeType) {
129
+ if (node.nam.startsWith('-')) {
130
+ const match = node.nam.match(/^-([^-]+)-(.+)$/);
131
+ if (match != null && '@' + match[2] in config.atRules) {
132
+ node.nam = match[2];
105
133
  }
106
- if (result != null) {
107
- return result;
134
+ }
135
+ if (node.typ == EnumToken.AtRuleNodeType && node.val !== '') {
136
+ if (node.tokens == null) {
137
+ Object.defineProperty(node, 'tokens', {
138
+ // @ts-ignore
139
+ ...definedPropertySettings,
140
+ value: parseAtRulePrelude(parseString(node.val), node),
141
+ });
108
142
  }
109
- break;
110
- case ValidationTokenEnum.Bracket:
111
- result = matchToken(token, matches[i].chi);
112
- if (result != null) {
113
- return result;
143
+ if (replaceAstNodes(node.tokens)) {
144
+ node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr), '');
114
145
  }
115
- break;
146
+ }
116
147
  }
148
+ return node;
117
149
  }
118
- return null;
119
150
  }
120
151
 
121
152
  export { ComputePrefixFeature };
@@ -3,14 +3,21 @@ import { EnumToken } from '../types.js';
3
3
  import '../minify.js';
4
4
  import '../walk.js';
5
5
  import '../../parser/parse.js';
6
+ import '../../parser/tokenize.js';
7
+ import '../../parser/utils/config.js';
6
8
  import '../../renderer/color/utils/constants.js';
7
9
  import '../../renderer/sourcemap/lib/encode.js';
8
- import '../../parser/utils/config.js';
9
10
 
10
11
  class ComputeShorthandFeature {
11
- static get ordering() {
12
+ get ordering() {
12
13
  return 3;
13
14
  }
15
+ get preProcess() {
16
+ return false;
17
+ }
18
+ get postProcess() {
19
+ return true;
20
+ }
14
21
  static register(options) {
15
22
  if (options.computeShorthand) {
16
23
  // @ts-ignore
@@ -18,21 +25,37 @@ class ComputeShorthandFeature {
18
25
  }
19
26
  }
20
27
  run(ast, options = {}, parent, context) {
28
+ if (!('chi' in ast)) {
29
+ return ast;
30
+ }
21
31
  // @ts-ignore
22
32
  const j = ast.chi.length;
23
33
  let k = 0;
34
+ let l;
24
35
  let properties = new PropertyList(options);
25
36
  const rules = [];
26
37
  // @ts-ignore
27
38
  for (; k < j; k++) {
39
+ l = k;
40
+ // capture comments with the next token
41
+ while (l + 1 < j) {
42
+ // @ts-ignore
43
+ const node = ast.chi[l];
44
+ if (node.typ == EnumToken.CommentNodeType) {
45
+ l++;
46
+ continue;
47
+ }
48
+ break;
49
+ }
28
50
  // @ts-ignore
29
- const node = ast.chi[k];
30
- if (node.typ == EnumToken.CommentNodeType || node.typ == EnumToken.DeclarationNodeType) {
31
- properties.add(node);
51
+ const node = ast.chi[l];
52
+ if (node.typ == EnumToken.DeclarationNodeType) {
53
+ properties.add(...ast.chi.slice(k, l + 1));
32
54
  }
33
55
  else {
34
- rules.push(node);
56
+ rules.push(...ast.chi.slice(k, l + 1));
35
57
  }
58
+ k = l;
36
59
  }
37
60
  // @ts-ignore
38
61
  ast.chi = [...properties, ...rules];
@@ -3,16 +3,23 @@ import { consumeWhitespace } from '../../validation/utils/whitespace.js';
3
3
  import '../minify.js';
4
4
  import '../walk.js';
5
5
  import '../../parser/parse.js';
6
+ import '../../parser/tokenize.js';
7
+ import '../../parser/utils/config.js';
6
8
  import { filterValues, renderToken } from '../../renderer/render.js';
7
9
  import '../../renderer/color/utils/constants.js';
8
- import '../../parser/utils/config.js';
9
10
  import { compute } from '../transform/compute.js';
10
11
  import { eqMatrix } from '../transform/minify.js';
11
12
 
12
13
  class TransformCssFeature {
13
- static get ordering() {
14
+ get ordering() {
14
15
  return 4;
15
16
  }
17
+ get preProcess() {
18
+ return false;
19
+ }
20
+ get postProcess() {
21
+ return true;
22
+ }
16
23
  static register(options) {
17
24
  // @ts-ignore
18
25
  if (options.computeTransform) {
@@ -37,7 +44,7 @@ class TransformCssFeature {
37
44
  consumeWhitespace(children);
38
45
  let { matrix, cumulative, minified } = compute(children) ?? {};
39
46
  if (matrix == null || cumulative == null || minified == null) {
40
- return;
47
+ continue;
41
48
  }
42
49
  let r = [filterValues(node.val.slice())];
43
50
  if (eqMatrix(matrix, cumulative)) {
@@ -0,0 +1,7 @@
1
+ var FeatureWalkMode;
2
+ (function (FeatureWalkMode) {
3
+ FeatureWalkMode[FeatureWalkMode["Pre"] = 0] = "Pre";
4
+ FeatureWalkMode[FeatureWalkMode["Post"] = 1] = "Post";
5
+ })(FeatureWalkMode || (FeatureWalkMode = {}));
6
+
7
+ export { FeatureWalkMode };
@@ -1,6 +1,12 @@
1
1
  import { EnumToken } from '../types.js';
2
2
  import { rem, compute } from './math.js';
3
3
  import { reduceNumber } from '../../renderer/render.js';
4
+ import '../../renderer/color/utils/constants.js';
5
+ import '../minify.js';
6
+ import '../walk.js';
7
+ import '../../parser/parse.js';
8
+ import '../../parser/tokenize.js';
9
+ import '../../parser/utils/config.js';
4
10
  import { mathFuncs } from '../../syntax/syntax.js';
5
11
 
6
12
  /**
@@ -517,4 +523,4 @@ function factor(tokens, ops) {
517
523
  return tokens;
518
524
  }
519
525
 
520
- export { evaluate, evaluateFunc, inlineExpression };
526
+ export { buildExpression, evaluate, evaluateFunc, inlineExpression };
@@ -1,5 +1,11 @@
1
1
  import { EnumToken } from '../types.js';
2
2
  import { reduceNumber } from '../../renderer/render.js';
3
+ import '../../renderer/color/utils/constants.js';
4
+ import '../minify.js';
5
+ import '../walk.js';
6
+ import '../../parser/parse.js';
7
+ import '../../parser/tokenize.js';
8
+ import '../../parser/utils/config.js';
3
9
 
4
10
  function gcd(x, y) {
5
11
  x = Math.abs(x);