@tbela99/css-parser 0.9.0 → 1.0.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 (70) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +22 -12
  3. package/dist/index-umd-web.js +2678 -2838
  4. package/dist/index.cjs +2468 -2628
  5. package/dist/index.d.ts +71 -26
  6. package/dist/lib/ast/expand.js +15 -2
  7. package/dist/lib/ast/features/calc.js +7 -10
  8. package/dist/lib/ast/features/index.js +1 -0
  9. package/dist/lib/ast/features/inlinecssvariables.js +0 -5
  10. package/dist/lib/ast/features/prefix.js +2 -7
  11. package/dist/lib/ast/features/shorthand.js +6 -9
  12. package/dist/lib/ast/features/transform.js +60 -0
  13. package/dist/lib/ast/math/expression.js +14 -10
  14. package/dist/lib/ast/math/math.js +14 -2
  15. package/dist/lib/ast/minify.js +47 -6
  16. package/dist/lib/ast/transform/compute.js +336 -0
  17. package/dist/lib/ast/transform/convert.js +33 -0
  18. package/dist/lib/ast/transform/matrix.js +111 -0
  19. package/dist/lib/ast/transform/minify.js +296 -0
  20. package/dist/lib/ast/transform/perspective.js +10 -0
  21. package/dist/lib/ast/transform/rotate.js +40 -0
  22. package/dist/lib/ast/transform/scale.js +32 -0
  23. package/dist/lib/ast/transform/skew.js +23 -0
  24. package/dist/lib/ast/transform/translate.js +32 -0
  25. package/dist/lib/ast/transform/utils.js +198 -0
  26. package/dist/lib/ast/types.js +2 -0
  27. package/dist/lib/ast/walk.js +23 -17
  28. package/dist/lib/parser/parse.js +174 -127
  29. package/dist/lib/parser/utils/declaration.js +1 -1
  30. package/dist/lib/renderer/color/{colormix.js → color-mix.js} +6 -0
  31. package/dist/lib/renderer/color/color.js +96 -20
  32. package/dist/lib/renderer/color/hex.js +17 -7
  33. package/dist/lib/renderer/color/hsl.js +7 -2
  34. package/dist/lib/renderer/color/lab.js +10 -1
  35. package/dist/lib/renderer/color/lch.js +8 -0
  36. package/dist/lib/renderer/color/oklab.js +8 -0
  37. package/dist/lib/renderer/color/oklch.js +8 -0
  38. package/dist/lib/renderer/color/prophotorgb.js +2 -2
  39. package/dist/lib/renderer/color/relativecolor.js +10 -21
  40. package/dist/lib/renderer/color/rgb.js +10 -7
  41. package/dist/lib/renderer/color/srgb.js +30 -6
  42. package/dist/lib/renderer/color/utils/components.js +13 -2
  43. package/dist/lib/renderer/color/xyz.js +2 -18
  44. package/dist/lib/renderer/color/xyzd50.js +20 -2
  45. package/dist/lib/renderer/render.js +70 -32
  46. package/dist/lib/renderer/sourcemap/sourcemap.js +1 -1
  47. package/dist/lib/syntax/syntax.js +75 -56
  48. package/dist/lib/validation/at-rules/container.js +6 -6
  49. package/dist/lib/validation/at-rules/document.js +40 -60
  50. package/dist/lib/validation/at-rules/import.js +61 -59
  51. package/dist/lib/validation/at-rules/keyframes.js +1 -1
  52. package/dist/lib/validation/at-rules/media.js +1 -1
  53. package/dist/lib/validation/at-rules/supports.js +40 -9
  54. package/dist/lib/validation/atrule.js +0 -4
  55. package/dist/lib/validation/config.json.js +83 -35
  56. package/dist/lib/validation/parser/parse.js +1 -95
  57. package/dist/lib/validation/parser/types.js +1 -2
  58. package/dist/lib/validation/selector.js +5 -2
  59. package/dist/lib/validation/syntaxes/compound-selector.js +2 -2
  60. package/dist/lib/validation/syntaxes/keyframe-block-list.js +2 -2
  61. package/dist/lib/validation/syntaxes/keyframe-selector.js +11 -90
  62. package/dist/lib/validation/syntaxes/layer-name.js +5 -16
  63. package/dist/lib/validation/syntaxes/relative-selector.js +15 -14
  64. package/dist/lib/validation/utils/list.js +18 -1
  65. package/dist/node/load.js +1 -1
  66. package/package.json +13 -12
  67. package/dist/lib/renderer/color/prophotoRgb.js +0 -56
  68. package/dist/lib/validation/declaration.js +0 -102
  69. package/dist/lib/validation/syntax.js +0 -1475
  70. package/dist/lib/validation/syntaxes/image.js +0 -29
package/dist/index.d.ts CHANGED
@@ -91,6 +91,8 @@ declare enum EnumToken {
91
91
  MediaFeatureAndTokenType = 89,
92
92
  MediaFeatureOrTokenType = 90,
93
93
  PseudoPageTokenType = 91,
94
+ PseudoElementTokenType = 92,
95
+ KeyframeAtRuleNodeType = 93,
94
96
  Time = 25,
95
97
  Iden = 7,
96
98
  EOF = 48,
@@ -129,10 +131,16 @@ declare enum EnumToken {
129
131
  * @param nestingContent
130
132
  * @param context
131
133
  */
132
- declare function minify(ast: AstNode, options?: ParserOptions | MinifyOptions, recursive?: boolean, errors?: ErrorDescription[], nestingContent?: boolean, context?: {
134
+ declare function minify(ast: AstNode, options?: ParserOptions | MinifyFeatureOptions, recursive?: boolean, errors?: ErrorDescription[], nestingContent?: boolean, context?: {
133
135
  [key: string]: any;
134
136
  }): AstNode;
135
137
 
138
+ declare enum WalkerOptionEnum {
139
+ Ignore = 0,
140
+ Stop = 1,
141
+ Children = 2,
142
+ IgnoreChildren = 3
143
+ }
136
144
  declare enum WalkerValueEvent {
137
145
  Enter = 0,
138
146
  Leave = 1
@@ -151,7 +159,7 @@ declare function walk(node: AstNode, filter?: WalkerFilter): Generator<WalkResul
151
159
  * @param reverse
152
160
  */
153
161
  declare function walkValues(values: Token[], root?: AstNode | Token | null, filter?: WalkerValueFilter | {
154
- event: WalkerValueEvent;
162
+ event?: WalkerValueEvent;
155
163
  fn?: WalkerValueFilter;
156
164
  type?: EnumToken | EnumToken[] | ((token: Token) => boolean);
157
165
  }, reverse?: boolean): Generator<WalkAttributesResult>;
@@ -517,6 +525,12 @@ export declare interface PseudoClassToken extends BaseToken {
517
525
  val: string;
518
526
  }
519
527
 
528
+ export declare interface PseudoElementToken extends BaseToken {
529
+
530
+ typ: EnumToken.PseudoElementTokenType;
531
+ val: string;
532
+ }
533
+
520
534
  export declare interface PseudoPageToken extends BaseToken {
521
535
 
522
536
  typ: EnumToken.PseudoPageTokenType;
@@ -812,6 +826,7 @@ export declare type Token =
812
826
  ListToken
813
827
  | PseudoClassToken
814
828
  | PseudoPageToken
829
+ | PseudoElementToken
815
830
  | PseudoClassFunctionToken
816
831
  | DelimToken
817
832
  | BinaryExpressionToken
@@ -865,7 +880,6 @@ export declare interface AstDeclaration extends BaseToken {
865
880
  typ: EnumToken.DeclarationNodeType
866
881
  }
867
882
 
868
-
869
883
  export declare interface AstRule extends BaseToken {
870
884
 
871
885
  typ: EnumToken.RuleNodeType;
@@ -879,7 +893,7 @@ export declare interface AstInvalidRule extends BaseToken {
879
893
 
880
894
  typ: EnumToken.InvalidRuleTokenType;
881
895
  sel: string;
882
- chi: Array<AstDeclaration | AstComment | AstRuleList>;
896
+ chi: Array<AstNode>;
883
897
  }
884
898
 
885
899
  export declare interface AstInvalidAtRule extends BaseToken {
@@ -889,8 +903,6 @@ export declare interface AstInvalidAtRule extends BaseToken {
889
903
  chi?: Array<AstNode>;
890
904
  }
891
905
 
892
-
893
-
894
906
  export declare interface AstKeyFrameRule extends BaseToken {
895
907
 
896
908
  typ: EnumToken.KeyFrameRuleNodeType;
@@ -918,14 +930,31 @@ export declare interface AstAtRule extends BaseToken {
918
930
  chi?: Array<AstDeclaration | AstComment> | Array<AstRule | AstComment>
919
931
  }
920
932
 
933
+ export declare interface AstKeyframeRule extends BaseToken {
934
+
935
+ typ: EnumToken.KeyFrameRuleNodeType;
936
+ sel: string;
937
+ chi: Array<AstDeclaration | AstComment | AstRuleList>;
938
+ optimized?: OptimizedSelector;
939
+ raw?: RawSelectorTokens;
940
+ }
941
+
942
+ export declare interface AstKeyframAtRule extends BaseToken {
943
+
944
+ typ: EnumToken.KeyframeAtRuleNodeType,
945
+ nam: string;
946
+ val: string;
947
+ chi: Array<AstKeyframeRule | AstComment>;
948
+ }
949
+
921
950
  export declare interface AstRuleList extends BaseToken {
922
951
 
923
- typ: EnumToken.StyleSheetNodeType | EnumToken.RuleNodeType | EnumToken.AtRuleNodeType,
952
+ typ: EnumToken.StyleSheetNodeType | EnumToken.RuleNodeType | EnumToken.AtRuleNodeType | EnumToken.KeyframeAtRuleNodeType | EnumToken.KeyFrameRuleNodeType,
924
953
  chi: Array<BaseToken | AstComment>;
925
954
  }
926
955
 
927
956
  export declare interface AstRuleStyleSheet extends AstRuleList {
928
- typ: EnumToken.StyleSheetNodeType,
957
+ typ: EnumToken.StyleSheetNodeType,
929
958
  chi: Array<AstRuleList | AstComment>
930
959
  }
931
960
 
@@ -936,6 +965,7 @@ export declare type AstNode =
936
965
  | AstAtRule
937
966
  | AstRule
938
967
  | AstDeclaration
968
+ | AstKeyframAtRule
939
969
  | AstKeyFrameRule
940
970
  | AstInvalidRule
941
971
  | AstInvalidAtRule;
@@ -982,13 +1012,13 @@ export declare interface PropertyListOptions {
982
1012
  computeShorthand?: boolean;
983
1013
  }
984
1014
 
985
- export declare type WalkerOption = 'ignore' | 'stop' | 'children' | 'ignore-children' | Token | null;
1015
+ export declare type WalkerOption = WalkerOptionEnum | Token | null;
986
1016
  /**
987
1017
  * returned value:
988
- * - 'ignore': ignore this node and its children
989
- * - 'stop': stop walking the tree
990
- * - 'children': walk the children and ignore the node itself
991
- * - 'ignore-children': walk the node and ignore children
1018
+ * - WalkerOptionEnum.Ignore: ignore this node and its children
1019
+ * - WalkerOptionEnum.Stop: stop walking the tree
1020
+ * - WalkerOptionEnum.Children: walk the children and ignore the node itself
1021
+ * - WalkerOptionEnum.IgnoreChildren: walk the node and ignore children
992
1022
  */
993
1023
  export declare type WalkerFilter = (node: AstNode) => WalkerOption;
994
1024
 
@@ -999,7 +1029,7 @@ export declare type WalkerFilter = (node: AstNode) => WalkerOption;
999
1029
  * - 'children': walk the children and ignore the node itself
1000
1030
  * - 'ignore-children': walk the node and ignore children
1001
1031
  */
1002
- export declare type WalkerValueFilter = (node: AstNode | Token, parent: FunctionToken | ParensToken | BinaryExpressionToken, event?: WalkerValueEvent) => WalkerOption | null;
1032
+ export declare type WalkerValueFilter = (node: AstNode | Token, parent?: FunctionToken | ParensToken | BinaryExpressionToken, event?: WalkerValueEvent) => WalkerOption | null;
1003
1033
 
1004
1034
  export declare interface WalkResult {
1005
1035
  node: AstNode;
@@ -1027,6 +1057,7 @@ export declare interface ErrorDescription {
1027
1057
  col: number;
1028
1058
  };
1029
1059
  error?: Error;
1060
+ rawTokens?: TokenizeResult[];
1030
1061
  }
1031
1062
 
1032
1063
  interface ValidationOptions {
@@ -1035,24 +1066,30 @@ interface ValidationOptions {
1035
1066
  lenient?: boolean;
1036
1067
  }
1037
1068
 
1038
- export declare interface ParserOptions extends ValidationOptions, PropertyListOptions {
1069
+ interface MinifyOptions {
1039
1070
 
1040
1071
  minify?: boolean;
1041
- src?: string;
1042
- sourcemap?: boolean;
1043
1072
  nestingRules?: boolean;
1044
1073
  expandNestingRules?: boolean;
1045
- removeCharset?: boolean;
1074
+ removeDuplicateDeclarations?: boolean;
1075
+ computeShorthand?: boolean;
1076
+ computeTransform?: boolean;
1077
+ computeCalcExpression?: boolean;
1078
+ inlineCssVariables?: boolean;
1046
1079
  removeEmpty?: boolean;
1080
+ pass?: number;
1081
+ }
1082
+
1083
+ export declare interface ParserOptions extends MinifyOptions, ValidationOptions, PropertyListOptions {
1084
+
1085
+ src?: string;
1086
+ sourcemap?: boolean;
1087
+ removeCharset?: boolean;
1047
1088
  resolveUrls?: boolean;
1048
1089
  resolveImport?: boolean;
1049
1090
  cwd?: string;
1050
1091
  parseColor?: boolean;
1051
- removeDuplicateDeclarations?: boolean;
1052
- computeShorthand?: boolean;
1053
1092
  removePrefix?: boolean;
1054
- inlineCssVariables?: boolean;
1055
- computeCalcExpression?: boolean;
1056
1093
  load?: (url: string, currentUrl: string) => Promise<string>;
1057
1094
  dirname?: (path: string) => string;
1058
1095
  resolve?: (url: string, currentUrl: string, currentWorkingDirectory?: string) => {
@@ -1064,7 +1101,7 @@ export declare interface ParserOptions extends ValidationOptions, PropertyListOp
1064
1101
  setParent?: boolean;
1065
1102
  }
1066
1103
 
1067
- export declare interface MinifyOptions extends ParserOptions {
1104
+ export declare interface MinifyFeatureOptions extends ParserOptions {
1068
1105
 
1069
1106
  features: MinifyFeature[];
1070
1107
  }
@@ -1073,7 +1110,7 @@ export declare interface MinifyFeature {
1073
1110
 
1074
1111
  ordering: number;
1075
1112
 
1076
- register(options: MinifyOptions | ParserOptions): void;
1113
+ register(options: MinifyFeatureOptions | ParserOptions): void;
1077
1114
 
1078
1115
  // run(ast: AstRule | AstAtRule, options: ParserOptions = {}, parent: AstRule | AstAtRule | AstRuleStyleSheet, context: { [key: string]: any }): void;
1079
1116
 
@@ -1083,7 +1120,7 @@ export declare interface MinifyFeature {
1083
1120
  export declare interface MinifyFeature {
1084
1121
 
1085
1122
  ordering: number;
1086
- register: (options: MinifyOptions | ParserOptions) => void;
1123
+ register: (options: MinifyFeatureOptions | ParserOptions) => void;
1087
1124
  run: (ast: AstRule | AstAtRule, options: ParserOptions, parent: AstRule | AstAtRule | AstRuleStyleSheet, context: {
1088
1125
  [key: string]: any
1089
1126
  }) => void;
@@ -1152,6 +1189,14 @@ export declare interface TransformResult extends ParseResult, RenderResult {
1152
1189
  export declare interface ParseTokenOptions extends ParserOptions {
1153
1190
  }
1154
1191
 
1192
+ export declare interface TokenizeResult {
1193
+ token: string;
1194
+ len: number;
1195
+ hint?: EnumToken;
1196
+ position: Position;
1197
+ bytesIn: number;
1198
+ }
1199
+
1155
1200
  export declare interface SourceMapObject {
1156
1201
  version: number;
1157
1202
  file?: string;
@@ -1168,7 +1213,7 @@ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
1168
1213
  relative: string;
1169
1214
  };
1170
1215
 
1171
- declare function load(url: string, currentFile: string): Promise<string>;
1216
+ declare function load(url: string, currentFile?: string): Promise<string>;
1172
1217
 
1173
1218
  /**
1174
1219
  * render ast node
@@ -69,7 +69,14 @@ function expandRule(node) {
69
69
  rule.sel = splitRule(ast.sel).reduce((a, b) => a.concat([b.join('') + r]), []).join(',');
70
70
  }
71
71
  else {
72
- selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(ast.sel) : arr.unshift(ast.sel, ' '));
72
+ // selRule = splitRule(selRule.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.join(''), ''));
73
+ const arSelf = splitRule(ast.sel).filter((r) => r.every((t) => t != ':before' && t != ':after' && !t.startsWith('::'))).reduce((acc, curr) => acc.concat([curr.join('')]), []).join(',');
74
+ if (arSelf.length == 0) {
75
+ ast.chi.splice(i--, 1);
76
+ continue;
77
+ }
78
+ //
79
+ selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(arSelf) : arr.unshift(arSelf, ' '));
73
80
  rule.sel = selRule.reduce((acc, curr) => {
74
81
  acc.push(curr.join(''));
75
82
  return acc;
@@ -80,8 +87,14 @@ function expandRule(node) {
80
87
  let childSelectorCompound = [];
81
88
  let withCompound = [];
82
89
  let withoutCompound = [];
83
- const rules = splitRule(ast.sel);
90
+ // pseudo elements cannot be used with '&'
91
+ // https://www.w3.org/TR/css-nesting-1/#example-7145ff1e
92
+ const rules = splitRule(ast.sel).filter((r) => r.every((t) => t != ':before' && t != ':after' && !t.startsWith('::')));
84
93
  const parentSelector = !node.sel.includes('&');
94
+ if (rules.length == 0) {
95
+ ast.chi.splice(i--, 1);
96
+ continue;
97
+ }
85
98
  for (const sel of (rule.raw ?? splitRule(rule.sel))) {
86
99
  const s = sel.join('');
87
100
  if (s.includes('&') || parentSelector) {
@@ -1,5 +1,5 @@
1
1
  import { EnumToken } from '../types.js';
2
- import { walkValues, WalkerValueEvent } from '../walk.js';
2
+ import { walkValues, WalkerValueEvent, WalkerOptionEnum } from '../walk.js';
3
3
  import { evaluate } from '../math/expression.js';
4
4
  import { renderToken } from '../../renderer/render.js';
5
5
  import { mathFuncs } from '../../syntax/syntax.js';
@@ -10,11 +10,6 @@ class ComputeCalcExpressionFeature {
10
10
  }
11
11
  static register(options) {
12
12
  if (options.computeCalcExpression) {
13
- for (const feature of options.features) {
14
- if (feature instanceof ComputeCalcExpressionFeature) {
15
- return;
16
- }
17
- }
18
13
  // @ts-ignore
19
14
  options.features.push(new ComputeCalcExpressionFeature());
20
15
  }
@@ -23,7 +18,6 @@ class ComputeCalcExpressionFeature {
23
18
  if (!('chi' in ast)) {
24
19
  return;
25
20
  }
26
- // @ts-ignore
27
21
  for (const node of ast.chi) {
28
22
  if (node.typ != EnumToken.DeclarationNodeType) {
29
23
  continue;
@@ -31,15 +25,18 @@ class ComputeCalcExpressionFeature {
31
25
  const set = new Set;
32
26
  for (const { value, parent } of walkValues(node.val, node, {
33
27
  event: WalkerValueEvent.Enter,
34
- fn(node, parent, event) {
28
+ // @ts-ignore
29
+ fn(node, parent) {
35
30
  if (parent != null &&
31
+ // @ts-ignore
36
32
  parent.typ == EnumToken.DeclarationNodeType &&
33
+ // @ts-ignore
37
34
  parent.val.length == 1 &&
38
35
  node.typ == EnumToken.FunctionTokenType &&
39
36
  mathFuncs.includes(node.val) &&
40
37
  node.chi.length == 1 &&
41
38
  node.chi[0].typ == EnumToken.IdenTokenType) {
42
- return 'ignore';
39
+ return WalkerOptionEnum.Ignore;
43
40
  }
44
41
  if ((node.typ == EnumToken.FunctionTokenType && node.val == 'var') || (!mathFuncs.includes(parent.val) && [EnumToken.ColorTokenType, EnumToken.DeclarationNodeType, EnumToken.RuleNodeType, EnumToken.AtRuleNodeType, EnumToken.StyleSheetNodeType].includes(parent?.typ))) {
45
42
  return null;
@@ -61,7 +58,7 @@ class ComputeCalcExpressionFeature {
61
58
  // @ts-ignore
62
59
  node[key] = values;
63
60
  }
64
- return 'ignore';
61
+ return WalkerOptionEnum.Ignore;
65
62
  }
66
63
  return null;
67
64
  }
@@ -2,3 +2,4 @@ export { ComputePrefixFeature } from './prefix.js';
2
2
  export { InlineCssVariablesFeature } from './inlinecssvariables.js';
3
3
  export { ComputeShorthandFeature } from './shorthand.js';
4
4
  export { ComputeCalcExpressionFeature } from './calc.js';
5
+ export { TransformCssFeature } from './transform.js';
@@ -31,11 +31,6 @@ class InlineCssVariablesFeature {
31
31
  }
32
32
  static register(options) {
33
33
  if (options.inlineCssVariables) {
34
- for (const feature of options.features) {
35
- if (feature instanceof InlineCssVariablesFeature) {
36
- return;
37
- }
38
- }
39
34
  // @ts-ignore
40
35
  options.features.push(new InlineCssVariablesFeature());
41
36
  }
@@ -17,11 +17,6 @@ class ComputePrefixFeature {
17
17
  }
18
18
  static register(options) {
19
19
  if (options.removePrefix) {
20
- for (const feature of options.features) {
21
- if (feature instanceof ComputePrefixFeature) {
22
- return;
23
- }
24
- }
25
20
  // @ts-ignore
26
21
  options.features.push(new ComputePrefixFeature(options));
27
22
  }
@@ -48,9 +43,9 @@ class ComputePrefixFeature {
48
43
  for (const { value } of walkValues(node.val)) {
49
44
  if (value.typ == EnumToken.IdenTokenType && value.val.charAt(0) == '-' && value.val.charAt(1) != '-') {
50
45
  // @ts-ignore
51
- const values = config.declarations[node.nam].ast.slice();
46
+ const values = config.declarations[node.nam].ast?.slice?.();
52
47
  const match = value.val.match(/^-(.*?)-(.*)$/);
53
- if (match != null) {
48
+ if (values != null && match != null) {
54
49
  const val = matchToken({ ...value, val: match[2] }, values);
55
50
  if (val != null) {
56
51
  // @ts-ignore
@@ -9,15 +9,10 @@ import '../../parser/utils/config.js';
9
9
 
10
10
  class ComputeShorthandFeature {
11
11
  static get ordering() {
12
- return 2;
12
+ return 3;
13
13
  }
14
14
  static register(options) {
15
15
  if (options.computeShorthand) {
16
- for (const feature of options.features) {
17
- if (feature instanceof ComputeShorthandFeature) {
18
- return;
19
- }
20
- }
21
16
  // @ts-ignore
22
17
  options.features.push(new ComputeShorthandFeature(options));
23
18
  }
@@ -27,18 +22,20 @@ class ComputeShorthandFeature {
27
22
  const j = ast.chi.length;
28
23
  let k = 0;
29
24
  let properties = new PropertyList(options);
25
+ const rules = [];
30
26
  // @ts-ignore
31
27
  for (; k < j; k++) {
32
28
  // @ts-ignore
33
29
  const node = ast.chi[k];
34
30
  if (node.typ == EnumToken.CommentNodeType || node.typ == EnumToken.DeclarationNodeType) {
35
31
  properties.add(node);
36
- continue;
37
32
  }
38
- break;
33
+ else {
34
+ rules.push(node);
35
+ }
39
36
  }
40
37
  // @ts-ignore
41
- ast.chi = [...properties].concat(ast.chi.slice(k));
38
+ ast.chi = [...properties, ...rules];
42
39
  return ast;
43
40
  }
44
41
  }
@@ -0,0 +1,60 @@
1
+ import { EnumToken } from '../types.js';
2
+ import { consumeWhitespace } from '../../validation/utils/whitespace.js';
3
+ import '../minify.js';
4
+ import '../walk.js';
5
+ import '../../parser/parse.js';
6
+ import { filterValues, renderToken } from '../../renderer/render.js';
7
+ import '../../renderer/color/utils/constants.js';
8
+ import '../../parser/utils/config.js';
9
+ import { compute } from '../transform/compute.js';
10
+ import { eqMatrix } from '../transform/minify.js';
11
+
12
+ class TransformCssFeature {
13
+ static get ordering() {
14
+ return 4;
15
+ }
16
+ static register(options) {
17
+ // @ts-ignore
18
+ if (options.computeTransform) {
19
+ // @ts-ignore
20
+ options.features.push(new TransformCssFeature());
21
+ }
22
+ }
23
+ run(ast) {
24
+ if (!('chi' in ast)) {
25
+ return;
26
+ }
27
+ let i = 0;
28
+ let node;
29
+ // @ts-ignore
30
+ for (; i < ast.chi.length; i++) {
31
+ // @ts-ignore
32
+ node = ast.chi[i];
33
+ if (node.typ != EnumToken.DeclarationNodeType || !node.nam.match(/^(-[a-z]+-)?transform$/)) {
34
+ continue;
35
+ }
36
+ const children = node.val.slice();
37
+ consumeWhitespace(children);
38
+ let { matrix, cumulative, minified } = compute(children) ?? {};
39
+ if (matrix == null || cumulative == null || minified == null) {
40
+ return;
41
+ }
42
+ let r = [filterValues(node.val.slice())];
43
+ if (eqMatrix(matrix, cumulative)) {
44
+ r.push(cumulative);
45
+ }
46
+ if (eqMatrix(matrix, minified)) {
47
+ r.push(minified);
48
+ }
49
+ const l = renderToken(matrix).length;
50
+ node.val = r.reduce((acc, curr) => {
51
+ if (curr.reduce((acc, t) => acc + renderToken(t), '').length < l) {
52
+ return curr;
53
+ }
54
+ return acc;
55
+ }, [matrix]);
56
+ }
57
+ }
58
+ }
59
+
60
+ export { TransformCssFeature };
@@ -39,14 +39,19 @@ function evaluate(tokens) {
39
39
  return tokens;
40
40
  }
41
41
  if (nodes.length <= 1) {
42
- // @ts-ignore
43
- if (nodes.length == 1 && nodes[0].typ == EnumToken.IdenTokenType && typeof Math[nodes[0].val.toUpperCase()] == 'number') {
44
- return [{
45
- ...nodes[0],
46
- // @ts-ignore
47
- val: '' + Math[nodes[0].val.toUpperCase()],
48
- typ: EnumToken.NumberTokenType
49
- }];
42
+ if (nodes.length == 1) {
43
+ if (nodes[0].typ == EnumToken.BinaryExpressionTokenType) {
44
+ return inlineExpression(nodes[0]);
45
+ }
46
+ // @ts-ignore
47
+ if (nodes[0].typ == EnumToken.IdenTokenType && typeof Math[nodes[0].val.toUpperCase()] == 'number') {
48
+ return [{
49
+ ...nodes[0],
50
+ // @ts-ignore
51
+ val: '' + Math[nodes[0].val.toUpperCase()],
52
+ typ: EnumToken.NumberTokenType
53
+ }];
54
+ }
50
55
  }
51
56
  return nodes;
52
57
  }
@@ -167,7 +172,6 @@ function doEvaluate(l, r, op) {
167
172
  }
168
173
  // @ts-ignore
169
174
  const val = compute(v1, v2, op);
170
- // typ = typeof val == 'number' ? EnumToken.NumberTokenType : EnumToken.FractionTokenType;
171
175
  const token = {
172
176
  ...(l.typ == EnumToken.NumberTokenType ? r : l),
173
177
  typ,
@@ -513,4 +517,4 @@ function factor(tokens, ops) {
513
517
  return tokens;
514
518
  }
515
519
 
516
- export { evaluate, evaluateFunc };
520
+ export { evaluate, evaluateFunc, inlineExpression };
@@ -4,9 +4,20 @@ import { reduceNumber } from '../../renderer/render.js';
4
4
  function gcd(x, y) {
5
5
  x = Math.abs(x);
6
6
  y = Math.abs(y);
7
+ if (x == y) {
8
+ return x;
9
+ }
7
10
  let t;
8
- if (x == 0 || y == 0) {
9
- return 1;
11
+ if (x == 0) {
12
+ return y;
13
+ }
14
+ if (y == 0) {
15
+ return x;
16
+ }
17
+ if (y > x) {
18
+ t = x;
19
+ x = y;
20
+ y = t;
10
21
  }
11
22
  while (y) {
12
23
  t = y;
@@ -76,6 +87,7 @@ function compute(a, b, op) {
76
87
  r2 = l1.r.val * r1.l.val;
77
88
  break;
78
89
  }
90
+ // @ts-ignore
79
91
  const a2 = simplify(l2, r2);
80
92
  if (a2[1] == 1) {
81
93
  return a2[0];
@@ -69,9 +69,9 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
69
69
  nestingContent = options.nestingRules && ast.typ == EnumToken.RuleNodeType;
70
70
  }
71
71
  let i = 0;
72
- let previous;
72
+ let previous = null;
73
73
  let node;
74
- let nodeIndex;
74
+ let nodeIndex = -1;
75
75
  // @ts-ignore
76
76
  for (; i < ast.chi.length; i++) {
77
77
  // @ts-ignore
@@ -83,13 +83,50 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
83
83
  // @ts-ignore
84
84
  if (previous == node) {
85
85
  // @ts-ignore
86
- ast.chi.splice(i, 1);
87
- i--;
86
+ ast.chi.splice(i--, 1);
88
87
  continue;
89
88
  }
90
89
  if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'font-face') {
91
90
  continue;
92
91
  }
92
+ if (node.typ == EnumToken.KeyframeAtRuleNodeType) {
93
+ if (previous?.typ == EnumToken.KeyframeAtRuleNodeType &&
94
+ node.nam == previous.nam &&
95
+ node.val == previous.val) {
96
+ ast.chi?.splice(nodeIndex--, 1);
97
+ previous = ast?.chi?.[nodeIndex] ?? null;
98
+ i = nodeIndex;
99
+ continue;
100
+ }
101
+ if (node.chi.length > 0) {
102
+ minify(node, options, true, errors, nestingContent, context);
103
+ }
104
+ }
105
+ if (node.typ == EnumToken.KeyFrameRuleNodeType) {
106
+ if (previous?.typ == EnumToken.KeyFrameRuleNodeType &&
107
+ node.sel == previous.sel) {
108
+ previous.chi.push(...node.chi);
109
+ // @ts-ignore
110
+ ast.chi.splice(i--, 1);
111
+ continue;
112
+ }
113
+ let k;
114
+ for (k = 0; k < node.chi.length; k++) {
115
+ if (node.chi[k].typ == EnumToken.DeclarationNodeType) {
116
+ let l = node.chi[k].val.length;
117
+ while (l--) {
118
+ if (node.chi[k].val[l].typ == EnumToken.ImportantTokenType) {
119
+ node.chi.splice(k--, 1);
120
+ break;
121
+ }
122
+ if ([EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(node.chi[k].val[l].typ)) {
123
+ continue;
124
+ }
125
+ break;
126
+ }
127
+ }
128
+ }
129
+ }
93
130
  if (node.typ == EnumToken.AtRuleNodeType) {
94
131
  // @ts-ignore
95
132
  if (node.nam == 'media' && ['all', '', null].includes(node.val)) {
@@ -227,7 +264,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
227
264
  return s.join('');
228
265
  }).join(',');
229
266
  // @ts-ignore
230
- let sel = wrap ? node.optimized.optimized[0] + `:is(${rule})` : rule;
267
+ let sel = wrap ? node.optimized.optimized.join('') + `:is(${rule})` : rule;
231
268
  if (rule.includes('&')) {
232
269
  // @ts-ignore
233
270
  rule = replaceCompound(rule, node.optimized.optimized[0]);
@@ -340,6 +377,10 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
340
377
  }
341
378
  }
342
379
  }
380
+ // else if ('chi' in node) {
381
+ //
382
+ // minify(node, options, recursive, errors, nestingContent, context);
383
+ // }
343
384
  if (!nestingContent &&
344
385
  // @ts-ignore
345
386
  previous != null &&
@@ -354,7 +395,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
354
395
  // @ts-ignore
355
396
  if (recursive && node != null && ('chi' in node)) {
356
397
  // @ts-ignore
357
- if (!node.chi.some(n => n.typ == EnumToken.DeclarationNodeType)) {
398
+ if (node.typ == EnumToken.KeyframeAtRuleNodeType || !node.chi.some(n => n.typ == EnumToken.DeclarationNodeType)) {
358
399
  // @ts-ignore
359
400
  if (!(node.typ == EnumToken.AtRuleNodeType && node.nam != 'font-face')) {
360
401
  minify(node, options, recursive, errors, nestingContent, context);