@tbela99/css-parser 1.2.0 → 1.3.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 (55) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +2 -2
  3. package/dist/index-umd-web.js +483 -849
  4. package/dist/index.cjs +483 -849
  5. package/dist/index.d.ts +107 -11
  6. package/dist/lib/ast/features/calc.js +1 -25
  7. package/dist/lib/ast/features/inlinecssvariables.js +0 -19
  8. package/dist/lib/ast/features/transform.js +2 -2
  9. package/dist/lib/ast/math/expression.js +26 -149
  10. package/dist/lib/ast/math/math.js +8 -8
  11. package/dist/lib/ast/transform/compute.js +4 -37
  12. package/dist/lib/ast/transform/matrix.js +33 -34
  13. package/dist/lib/ast/transform/minify.js +32 -51
  14. package/dist/lib/ast/transform/perspective.js +1 -1
  15. package/dist/lib/ast/transform/rotate.js +13 -13
  16. package/dist/lib/ast/transform/scale.js +8 -8
  17. package/dist/lib/ast/transform/skew.js +4 -4
  18. package/dist/lib/ast/transform/translate.js +8 -8
  19. package/dist/lib/ast/transform/utils.js +31 -39
  20. package/dist/lib/ast/types.js +91 -2
  21. package/dist/lib/parser/declaration/set.js +2 -2
  22. package/dist/lib/parser/parse.js +34 -12
  23. package/dist/lib/parser/tokenize.js +28 -40
  24. package/dist/lib/parser/utils/type.js +1 -1
  25. package/dist/lib/renderer/render.js +36 -27
  26. package/dist/lib/syntax/color/cmyk.js +2 -2
  27. package/dist/lib/syntax/color/color-mix.js +11 -12
  28. package/dist/lib/syntax/color/color.js +7 -7
  29. package/dist/lib/syntax/color/hsl.js +4 -4
  30. package/dist/lib/syntax/color/hwb.js +27 -8
  31. package/dist/lib/syntax/color/lab.js +4 -4
  32. package/dist/lib/syntax/color/lch.js +4 -4
  33. package/dist/lib/syntax/color/oklab.js +4 -4
  34. package/dist/lib/syntax/color/oklch.js +4 -4
  35. package/dist/lib/syntax/color/relativecolor.js +1 -1
  36. package/dist/lib/syntax/color/rgb.js +4 -4
  37. package/dist/lib/syntax/color/utils/components.js +15 -3
  38. package/dist/lib/syntax/color/utils/distance.js +11 -1
  39. package/dist/lib/syntax/syntax.js +8 -17
  40. package/dist/lib/syntax/utils.js +1 -1
  41. package/dist/lib/validation/at-rules/document.js +1 -1
  42. package/dist/lib/validation/at-rules/import.js +4 -4
  43. package/dist/lib/validation/at-rules/keyframes.js +0 -11
  44. package/dist/lib/validation/at-rules/supports.js +6 -6
  45. package/dist/lib/validation/config.js +0 -4
  46. package/dist/lib/validation/parser/parse.js +0 -8
  47. package/dist/lib/validation/selector.js +0 -9
  48. package/dist/lib/validation/syntax.js +14 -134
  49. package/dist/lib/validation/syntaxes/complex-selector-list.js +0 -11
  50. package/dist/lib/validation/syntaxes/family-name.js +0 -32
  51. package/dist/lib/validation/syntaxes/keyframe-selector.js +0 -11
  52. package/dist/lib/validation/syntaxes/relative-selector-list.js +0 -26
  53. package/dist/lib/validation/syntaxes/url.js +0 -33
  54. package/dist/lib/validation/utils/list.js +0 -8
  55. package/package.json +1 -1
@@ -74,12 +74,12 @@ function color2RgbToken(token) {
74
74
  }
75
75
  function rgb2RgbToken(values) {
76
76
  const chi = [
77
- { typ: EnumToken.NumberTokenType, val: String(values[0]) },
78
- { typ: EnumToken.NumberTokenType, val: String(values[1]) },
79
- { typ: EnumToken.NumberTokenType, val: String(values[2]) },
77
+ { typ: EnumToken.NumberTokenType, val: values[0] },
78
+ { typ: EnumToken.NumberTokenType, val: values[1] },
79
+ { typ: EnumToken.NumberTokenType, val: values[2] },
80
80
  ];
81
81
  if (values.length == 4) {
82
- chi.push({ typ: EnumToken.PercentageTokenType, val: (values[3] * 100).toFixed() });
82
+ chi.push({ typ: EnumToken.PercentageTokenType, val: values[3] * 100 });
83
83
  }
84
84
  return {
85
85
  typ: EnumToken.ColorTokenType,
@@ -1,6 +1,6 @@
1
1
  import { ColorType, EnumToken } from '../../../ast/types.js';
2
2
  import '../../../ast/minify.js';
3
- import '../../../ast/walk.js';
3
+ import { walkValues } from '../../../ast/walk.js';
4
4
  import '../../../parser/parse.js';
5
5
  import '../../../parser/tokenize.js';
6
6
  import '../../../parser/utils/config.js';
@@ -13,7 +13,7 @@ function getComponents(token) {
13
13
  const value = expandHexValue(token.kin == ColorType.LIT ? COLORS_NAMES[token.val.toLowerCase()] : token.val);
14
14
  // @ts-ignore
15
15
  return value.slice(1).match(/([a-fA-F0-9]{2})/g).map((t, index) => {
16
- return { typ: EnumToken.Number, val: (index < 3 ? parseInt(t, 16) : parseInt(t, 16) / 255).toString() };
16
+ return { typ: EnumToken.Number, val: index < 3 ? parseInt(t, 16) : parseInt(t, 16) / 255 };
17
17
  });
18
18
  }
19
19
  const result = [];
@@ -23,7 +23,19 @@ function getComponents(token) {
23
23
  ].includes(child.typ)) {
24
24
  continue;
25
25
  }
26
- if (child.typ == EnumToken.ColorTokenType && child.val.localeCompare('currentcolor', undefined, { sensitivity: 'base' }) == 0) {
26
+ if (child.typ == EnumToken.FunctionTokenType) {
27
+ if ('var' == child.val.toLowerCase()) {
28
+ return null;
29
+ }
30
+ else {
31
+ for (const { value } of walkValues(child.chi)) {
32
+ if (value.typ == EnumToken.FunctionTokenType && 'var' === value.val.toLowerCase()) {
33
+ return null;
34
+ }
35
+ }
36
+ }
37
+ }
38
+ if (child.typ == EnumToken.ColorTokenType && 'currentcolor' === child.val.toLowerCase()) {
27
39
  return null;
28
40
  }
29
41
  result.push(child);
@@ -9,13 +9,23 @@ import '../../../parser/utils/config.js';
9
9
  import './constants.js';
10
10
  import '../../../renderer/sourcemap/lib/encode.js';
11
11
 
12
+ /**
13
+ * Calculate the distance between two okLab colors.
14
+ * @param okLab1
15
+ * @param okLab2
16
+ */
12
17
  function okLabDistance(okLab1, okLab2) {
13
18
  return Math.sqrt(Math.pow(okLab1[0] - okLab2[0], 2) + Math.pow(okLab1[1] - okLab2[1], 2) + Math.pow(okLab1[2] - okLab2[2], 2));
14
19
  }
20
+ /**
21
+ * Check if two colors are close.
22
+ * @param color1
23
+ * @param color2
24
+ * @param threshold
25
+ */
15
26
  function isOkLabClose(color1, color2, threshold = .01) {
16
27
  color1 = convertColor(color1, ColorType.OKLAB);
17
28
  color2 = convertColor(color2, ColorType.OKLAB);
18
- // console.error(JSON.stringify({color1, color2}, null, 1));
19
29
  if (color1 == null || color2 == null) {
20
30
  return false;
21
31
  }
@@ -499,18 +499,18 @@ function isPolarColorspace(token) {
499
499
  }
500
500
  function isHueInterpolationMethod(token) {
501
501
  if (!Array.isArray(token)) {
502
- return token.typ == EnumToken.IdenTokenType && 'hue'.localeCompare(token.val, undefined, { sensitivity: 'base' }) == 0;
502
+ return token.typ == EnumToken.IdenTokenType && 'hue' === token.val?.toLowerCase?.();
503
503
  }
504
504
  if (token.length != 2 || token[0].typ != EnumToken.IdenTokenType || token[1].typ != EnumToken.IdenTokenType) {
505
505
  return false;
506
506
  }
507
- return ['shorter', 'longer', 'increasing', 'decreasing'].includes(token[0].val) && 'hue'.localeCompare(token[1].val, undefined, { sensitivity: 'base' }) == 0;
507
+ return ['shorter', 'longer', 'increasing', 'decreasing'].includes(token[0].val?.toLowerCase?.()) && 'hue' === token[1].val?.toLowerCase?.();
508
508
  }
509
509
  function isIdentColor(token) {
510
510
  return token.typ == EnumToken.ColorTokenType && [ColorType.SYS, ColorType.DPSYS, ColorType.LIT].includes(token.kin) && isIdent(token.val);
511
511
  }
512
512
  function isPercentageToken(token) {
513
- return token.typ == EnumToken.PercentageTokenType || (token.typ == EnumToken.NumberTokenType && token.val == '0');
513
+ return token.typ == EnumToken.PercentageTokenType || (token.typ == EnumToken.NumberTokenType && token.val == 0);
514
514
  }
515
515
  function isColor(token) {
516
516
  if (token.typ == EnumToken.ColorTokenType) {
@@ -621,7 +621,7 @@ function isColor(token) {
621
621
  if (children.length == 3) {
622
622
  if (children[0].length > 4 ||
623
623
  children[0][0].typ != EnumToken.IdenTokenType ||
624
- 'in'.localeCompare(children[0][0].val, undefined, { sensitivity: 'base' }) != 0 ||
624
+ 'in' !== children[0][0].val?.toLowerCase?.() ||
625
625
  !isColorspace(children[0][1]) ||
626
626
  (children[0].length >= 3 && !isHueInterpolationMethod(children[0].slice(2))) ||
627
627
  children[1].length > 2 ||
@@ -633,12 +633,12 @@ function isColor(token) {
633
633
  return false;
634
634
  }
635
635
  if (children[1].length == 2) {
636
- if (!(children[1][1].typ == EnumToken.PercentageTokenType || (children[1][1].typ == EnumToken.NumberTokenType && children[1][1].val == '0'))) {
636
+ if (!(children[1][1].typ == EnumToken.PercentageTokenType || (children[1][1].typ == EnumToken.NumberTokenType && children[1][1].val == 0))) {
637
637
  return false;
638
638
  }
639
639
  }
640
640
  if (children[2].length == 2) {
641
- if (!(children[2][1].typ == EnumToken.PercentageTokenType || (children[2][1].typ == EnumToken.NumberTokenType && children[2][1].val == '0'))) {
641
+ if (!(children[2][1].typ == EnumToken.PercentageTokenType || (children[2][1].typ == EnumToken.NumberTokenType && children[2][1].val == 0))) {
642
642
  return false;
643
643
  }
644
644
  }
@@ -782,15 +782,6 @@ function isIdent(name) {
782
782
  }
783
783
  return true;
784
784
  }
785
- function isNonPrintable(codepoint) {
786
- // null -> backspace
787
- return (codepoint >= 0 && codepoint <= 0x8) ||
788
- // tab
789
- codepoint == 0xb ||
790
- // delete
791
- codepoint == 0x7f ||
792
- (codepoint >= 0xe && codepoint <= 0x1f);
793
- }
794
785
  function isPseudo(name) {
795
786
  return name.charAt(0) == ':' &&
796
787
  ((name.endsWith('(') && isIdent(name.charAt(1) == ':' ? name.slice(2, -1) : name.slice(1, -1))) ||
@@ -897,7 +888,7 @@ function parseDimension(name) {
897
888
  }
898
889
  const dimension = {
899
890
  typ: EnumToken.DimensionTokenType,
900
- val: name.slice(0, index),
891
+ val: +name.slice(0, index),
901
892
  unit: name.slice(index)
902
893
  };
903
894
  if (isAngle(dimension)) {
@@ -957,4 +948,4 @@ function isWhiteSpace(codepoint) {
957
948
  codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
958
949
  }
959
950
 
960
- export { colorFontTech, fontFeaturesTech, fontFormat, isAngle, isAtKeyword, isColor, isColorspace, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isHueInterpolationMethod, isIdent, isIdentCodepoint, isIdentColor, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPercentageToken, isPolarColorspace, isPseudo, isRectangularOrthogonalColorspace, isResolution, isTime, isWhiteSpace, mathFuncs, mediaTypes, mozExtensions, parseColor, parseDimension, pseudoAliasMap, pseudoElements, transformFunctions, webkitExtensions, wildCardFuncs };
951
+ export { colorFontTech, fontFeaturesTech, fontFormat, isAngle, isAtKeyword, isColor, isColorspace, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isHueInterpolationMethod, isIdent, isIdentCodepoint, isIdentColor, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPercentageToken, isPolarColorspace, isPseudo, isRectangularOrthogonalColorspace, isResolution, isTime, isWhiteSpace, mathFuncs, mediaTypes, mozExtensions, parseColor, parseDimension, pseudoAliasMap, pseudoElements, transformFunctions, webkitExtensions, wildCardFuncs };
@@ -50,7 +50,7 @@ function length2Px(value) {
50
50
  * @param val
51
51
  */
52
52
  function minifyNumber(val) {
53
- val = String(+val);
53
+ val = String(val);
54
54
  if (val === '0') {
55
55
  return '0';
56
56
  }
@@ -45,7 +45,7 @@ function validateAtRuleDocument(atRule, options, root) {
45
45
  };
46
46
  }
47
47
  // @ts-ignore
48
- if ((t[0].typ != EnumToken.FunctionTokenType && t[0].typ != EnumToken.UrlFunctionTokenType) || !['url', 'url-prefix', 'domain', 'media-document', 'regexp'].some((f) => f.localeCompare(t[0].val, undefined, { sensitivity: 'base' }) == 0)) {
48
+ if ((t[0].typ != EnumToken.FunctionTokenType && t[0].typ != EnumToken.UrlFunctionTokenType) || !['url', 'url-prefix', 'domain', 'media-document', 'regexp'].includes(t[0].val?.toLowerCase?.())) {
49
49
  return {
50
50
  valid: SyntaxValidationResult.Drop,
51
51
  context: [],
@@ -94,8 +94,7 @@ function validateAtRuleImport(atRule, options, root) {
94
94
  if (tokens.length > 0) {
95
95
  // @ts-ignore
96
96
  if (tokens[0].typ == EnumToken.IdenTokenType) {
97
- // @ts-ignore
98
- if ('layer'.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' }) == 0) {
97
+ if ('layer' === tokens[0].val.toLowerCase()) {
99
98
  tokens.shift();
100
99
  // @ts-ignore
101
100
  if (!consumeWhitespace(tokens)) {
@@ -113,7 +112,7 @@ function validateAtRuleImport(atRule, options, root) {
113
112
  // @ts-ignore
114
113
  else if (tokens[0].typ == EnumToken.FunctionTokenType) {
115
114
  // @ts-ignore
116
- if ('layer'.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' }) == 0) {
115
+ if ('layer' === tokens[0].val.toLowerCase()) {
117
116
  const result = validateLayerName(tokens[0].chi);
118
117
  if (result.valid == SyntaxValidationResult.Drop) {
119
118
  return result;
@@ -122,8 +121,9 @@ function validateAtRuleImport(atRule, options, root) {
122
121
  // @ts-ignore
123
122
  consumeWhitespace(tokens);
124
123
  }
124
+ // tokens[0]?.val
125
125
  // @ts-ignore
126
- if ('supports'.localeCompare(tokens[0]?.val, undefined, { sensitivity: 'base' }) == 0) {
126
+ if ('supports' === tokens[0]?.val?.toLowerCase?.()) {
127
127
  const result = validateAtRuleSupportsConditions(atRule, tokens[0].chi);
128
128
  if (result.valid == SyntaxValidationResult.Drop) {
129
129
  return result;
@@ -21,17 +21,6 @@ function validateAtRuleKeyframes(atRule, options, root) {
21
21
  }
22
22
  const tokens = atRule.tokens.filter((t) => t.typ != EnumToken.CommentTokenType).slice();
23
23
  consumeWhitespace(tokens);
24
- // if (tokens.length == 0) {
25
- //
26
- // // @ts-ignore
27
- // return {
28
- // valid: SyntaxValidationResult.Drop,
29
- // context: [],
30
- // node: atRule,
31
- // syntax: '@keyframes',
32
- // error: 'expecting at-rule prelude'
33
- // } as ValidationSyntaxResult;
34
- // }
35
24
  if (tokens.length == 0 || ![EnumToken.StringTokenType, EnumToken.IdenTokenType].includes(tokens[0].typ)) {
36
25
  // @ts-ignore
37
26
  return {
@@ -166,7 +166,7 @@ function validateSupportCondition(atRule, token) {
166
166
  if (token.typ == EnumToken.MediaFeatureNotTokenType) {
167
167
  return validateSupportCondition(atRule, token.val);
168
168
  }
169
- if (token.typ == EnumToken.FunctionTokenType && token.val.localeCompare('selector', undefined, { sensitivity: 'base' }) == 0) {
169
+ if (token.typ == EnumToken.FunctionTokenType && 'selector' === token.val.toLowerCase()) {
170
170
  return {
171
171
  valid: SyntaxValidationResult.Valid,
172
172
  context: [],
@@ -223,7 +223,7 @@ function validateSupportFeature(token) {
223
223
  return validateSupportFeature(token.val);
224
224
  }
225
225
  if (token.typ == EnumToken.FunctionTokenType) {
226
- if (token.val.localeCompare('selector', undefined, { sensitivity: 'base' }) == 0) {
226
+ if ('selector' === token.val.toLowerCase()) {
227
227
  return {
228
228
  valid: SyntaxValidationResult.Valid,
229
229
  context: [],
@@ -232,10 +232,10 @@ function validateSupportFeature(token) {
232
232
  error: ''
233
233
  };
234
234
  }
235
- if (token.val.localeCompare('font-tech', undefined, { sensitivity: 'base' }) == 0) {
235
+ if ('font-tech' === token.val.toLowerCase()) {
236
236
  const chi = token.chi.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ));
237
237
  // @ts-ignore
238
- return chi.length == 1 && chi[0].typ == EnumToken.IdenTokenType && colorFontTech.concat(fontFeaturesTech).some((t) => t.localeCompare(chi[0].val, undefined, { sensitivity: 'base' }) == 0) ?
238
+ return chi.length == 1 && chi[0].typ == EnumToken.IdenTokenType && colorFontTech.concat(fontFeaturesTech).includes(chi[0].val.toLowerCase()) ?
239
239
  {
240
240
  valid: SyntaxValidationResult.Valid,
241
241
  context: [],
@@ -251,10 +251,10 @@ function validateSupportFeature(token) {
251
251
  error: 'expected font-tech'
252
252
  };
253
253
  }
254
- if (token.val.localeCompare('font-format', undefined, { sensitivity: 'base' }) == 0) {
254
+ if ('font-format' === token.val.toLowerCase()) {
255
255
  const chi = token.chi.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ));
256
256
  // @ts-ignore
257
- return chi.length == 1 && chi[0].typ == EnumToken.IdenTokenType && fontFormat.some((t) => t.localeCompare(chi[0].val, undefined, { sensitivity: 'base' }) == 0) ?
257
+ return chi.length == 1 && chi[0].typ == EnumToken.IdenTokenType && fontFormat.includes(chi[0].val, toLowerCase()) ?
258
258
  {
259
259
  valid: SyntaxValidationResult.Valid,
260
260
  context: [],
@@ -21,10 +21,6 @@ function getSyntax(group, key) {
21
21
  key = matches[1] + matches[3];
22
22
  }
23
23
  }
24
- // if (!(key in obj)) {
25
- //
26
- // return null;
27
- // }
28
24
  }
29
25
  // @ts-ignore
30
26
  obj = obj[key];
@@ -175,7 +175,6 @@ function parseSyntax(syntax) {
175
175
  typ: ValidationTokenEnum.Root,
176
176
  chi: []
177
177
  }, 'pos', { ...objectProperties, value: { ind: 0, lin: 1, col: 0 } });
178
- // return minify(doParseSyntax(syntaxes, tokenize(syntaxes), root)) as ValidationRootToken;
179
178
  return minify(doParseSyntax(syntax, tokenize(syntax), root));
180
179
  }
181
180
  function matchParens(syntax, iterator) {
@@ -351,10 +350,6 @@ function matchAtRule(syntax, iterator) {
351
350
  token.typ = ValidationTokenEnum.AtRule;
352
351
  break;
353
352
  }
354
- // if (item.value.typ != ValidationTokenEnum.Whitespace) {
355
- //
356
- // console.error('unexpected token', item.value);
357
- // }
358
353
  item = iterator.next();
359
354
  if (item.done) {
360
355
  break;
@@ -971,9 +966,6 @@ function renderSyntax(token, parent) {
971
966
  return '{' + token.chi.reduce((acc, t) => acc + renderSyntax(t), '') + '}';
972
967
  case ValidationTokenEnum.DeclarationDefinitionToken:
973
968
  return token.nam + ': ' + renderSyntax(token.val);
974
- // case ValidationTokenEnum.ColumnArrayToken:
975
- //
976
- // return (token as ValidationColumnArrayToken).chi.reduce((acc: string, curr: ValidationToken) => acc + (acc.trim().length > 0 ? '||' : '') + renderSyntax(curr), '');
977
969
  default:
978
970
  throw new Error('Unhandled token: ' + JSON.stringify({ token }, null, 1));
979
971
  }
@@ -13,15 +13,6 @@ import './config.js';
13
13
  import { validateSelectorList } from './syntaxes/selector-list.js';
14
14
 
15
15
  function validateSelector(selector, options, root) {
16
- // if (root == null) {
17
- //
18
- // return validateSelectorList(selector, root, options);
19
- // }
20
- // @ts-ignore
21
- // if (root.typ == EnumToken.AtRuleNodeType && root.nam.match(/^(-[a-z]+-)?keyframes$/)) {
22
- //
23
- // return validateKeyframeBlockList(selector, root as AstAtRule, options);
24
- // }
25
16
  let isNested = root.typ == EnumToken.RuleNodeType ? 1 : 0;
26
17
  let currentRoot = root.parent;
27
18
  while (currentRoot != null && isNested == 0) {