@tbela99/css-parser 0.9.1 → 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 (58) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +15 -8
  3. package/dist/index-umd-web.js +1815 -498
  4. package/dist/index.cjs +1816 -499
  5. package/dist/index.d.ts +46 -14
  6. package/dist/lib/ast/features/calc.js +7 -10
  7. package/dist/lib/ast/features/index.js +1 -0
  8. package/dist/lib/ast/features/inlinecssvariables.js +0 -5
  9. package/dist/lib/ast/features/prefix.js +2 -7
  10. package/dist/lib/ast/features/shorthand.js +6 -9
  11. package/dist/lib/ast/features/transform.js +60 -0
  12. package/dist/lib/ast/math/expression.js +14 -10
  13. package/dist/lib/ast/math/math.js +14 -2
  14. package/dist/lib/ast/minify.js +46 -5
  15. package/dist/lib/ast/transform/compute.js +336 -0
  16. package/dist/lib/ast/transform/convert.js +33 -0
  17. package/dist/lib/ast/transform/matrix.js +111 -0
  18. package/dist/lib/ast/transform/minify.js +296 -0
  19. package/dist/lib/ast/transform/perspective.js +10 -0
  20. package/dist/lib/ast/transform/rotate.js +40 -0
  21. package/dist/lib/ast/transform/scale.js +32 -0
  22. package/dist/lib/ast/transform/skew.js +23 -0
  23. package/dist/lib/ast/transform/translate.js +32 -0
  24. package/dist/lib/ast/transform/utils.js +198 -0
  25. package/dist/lib/ast/types.js +1 -0
  26. package/dist/lib/ast/walk.js +23 -17
  27. package/dist/lib/parser/parse.js +109 -88
  28. package/dist/lib/parser/utils/declaration.js +1 -1
  29. package/dist/lib/renderer/color/{colormix.js → color-mix.js} +6 -0
  30. package/dist/lib/renderer/color/color.js +94 -18
  31. package/dist/lib/renderer/color/hex.js +17 -7
  32. package/dist/lib/renderer/color/hsl.js +7 -2
  33. package/dist/lib/renderer/color/lab.js +8 -0
  34. package/dist/lib/renderer/color/lch.js +8 -0
  35. package/dist/lib/renderer/color/oklab.js +8 -0
  36. package/dist/lib/renderer/color/oklch.js +8 -0
  37. package/dist/lib/renderer/color/relativecolor.js +10 -21
  38. package/dist/lib/renderer/color/rgb.js +10 -7
  39. package/dist/lib/renderer/color/srgb.js +30 -6
  40. package/dist/lib/renderer/color/utils/components.js +13 -2
  41. package/dist/lib/renderer/render.js +67 -30
  42. package/dist/lib/syntax/syntax.js +74 -56
  43. package/dist/lib/validation/at-rules/container.js +6 -6
  44. package/dist/lib/validation/at-rules/document.js +1 -1
  45. package/dist/lib/validation/at-rules/keyframes.js +1 -1
  46. package/dist/lib/validation/at-rules/media.js +0 -1
  47. package/dist/lib/validation/atrule.js +0 -4
  48. package/dist/lib/validation/selector.js +5 -2
  49. package/dist/lib/validation/syntaxes/keyframe-block-list.js +2 -2
  50. package/dist/lib/validation/syntaxes/keyframe-selector.js +11 -90
  51. package/dist/lib/validation/syntaxes/relative-selector.js +15 -14
  52. package/dist/lib/validation/utils/list.js +18 -1
  53. package/dist/node/load.js +1 -1
  54. package/package.json +12 -12
  55. package/dist/lib/renderer/color/prophotoRgb.js +0 -56
  56. package/dist/lib/validation/declaration.js +0 -94
  57. package/dist/lib/validation/syntax.js +0 -1509
  58. package/dist/lib/validation/syntaxes/image.js +0 -29
package/dist/index.d.ts CHANGED
@@ -92,6 +92,7 @@ declare enum EnumToken {
92
92
  MediaFeatureOrTokenType = 90,
93
93
  PseudoPageTokenType = 91,
94
94
  PseudoElementTokenType = 92,
95
+ KeyframeAtRuleNodeType = 93,
95
96
  Time = 25,
96
97
  Iden = 7,
97
98
  EOF = 48,
@@ -134,6 +135,12 @@ declare function minify(ast: AstNode, options?: ParserOptions | MinifyFeatureOpt
134
135
  [key: string]: any;
135
136
  }): AstNode;
136
137
 
138
+ declare enum WalkerOptionEnum {
139
+ Ignore = 0,
140
+ Stop = 1,
141
+ Children = 2,
142
+ IgnoreChildren = 3
143
+ }
137
144
  declare enum WalkerValueEvent {
138
145
  Enter = 0,
139
146
  Leave = 1
@@ -152,7 +159,7 @@ declare function walk(node: AstNode, filter?: WalkerFilter): Generator<WalkResul
152
159
  * @param reverse
153
160
  */
154
161
  declare function walkValues(values: Token[], root?: AstNode | Token | null, filter?: WalkerValueFilter | {
155
- event: WalkerValueEvent;
162
+ event?: WalkerValueEvent;
156
163
  fn?: WalkerValueFilter;
157
164
  type?: EnumToken | EnumToken[] | ((token: Token) => boolean);
158
165
  }, reverse?: boolean): Generator<WalkAttributesResult>;
@@ -873,7 +880,6 @@ export declare interface AstDeclaration extends BaseToken {
873
880
  typ: EnumToken.DeclarationNodeType
874
881
  }
875
882
 
876
-
877
883
  export declare interface AstRule extends BaseToken {
878
884
 
879
885
  typ: EnumToken.RuleNodeType;
@@ -887,7 +893,7 @@ export declare interface AstInvalidRule extends BaseToken {
887
893
 
888
894
  typ: EnumToken.InvalidRuleTokenType;
889
895
  sel: string;
890
- chi: Array<AstDeclaration | AstComment | AstRuleList>;
896
+ chi: Array<AstNode>;
891
897
  }
892
898
 
893
899
  export declare interface AstInvalidAtRule extends BaseToken {
@@ -897,8 +903,6 @@ export declare interface AstInvalidAtRule extends BaseToken {
897
903
  chi?: Array<AstNode>;
898
904
  }
899
905
 
900
-
901
-
902
906
  export declare interface AstKeyFrameRule extends BaseToken {
903
907
 
904
908
  typ: EnumToken.KeyFrameRuleNodeType;
@@ -926,14 +930,31 @@ export declare interface AstAtRule extends BaseToken {
926
930
  chi?: Array<AstDeclaration | AstComment> | Array<AstRule | AstComment>
927
931
  }
928
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
+
929
950
  export declare interface AstRuleList extends BaseToken {
930
951
 
931
- typ: EnumToken.StyleSheetNodeType | EnumToken.RuleNodeType | EnumToken.AtRuleNodeType,
952
+ typ: EnumToken.StyleSheetNodeType | EnumToken.RuleNodeType | EnumToken.AtRuleNodeType | EnumToken.KeyframeAtRuleNodeType | EnumToken.KeyFrameRuleNodeType,
932
953
  chi: Array<BaseToken | AstComment>;
933
954
  }
934
955
 
935
956
  export declare interface AstRuleStyleSheet extends AstRuleList {
936
- typ: EnumToken.StyleSheetNodeType,
957
+ typ: EnumToken.StyleSheetNodeType,
937
958
  chi: Array<AstRuleList | AstComment>
938
959
  }
939
960
 
@@ -944,6 +965,7 @@ export declare type AstNode =
944
965
  | AstAtRule
945
966
  | AstRule
946
967
  | AstDeclaration
968
+ | AstKeyframAtRule
947
969
  | AstKeyFrameRule
948
970
  | AstInvalidRule
949
971
  | AstInvalidAtRule;
@@ -990,13 +1012,13 @@ export declare interface PropertyListOptions {
990
1012
  computeShorthand?: boolean;
991
1013
  }
992
1014
 
993
- export declare type WalkerOption = 'ignore' | 'stop' | 'children' | 'ignore-children' | Token | null;
1015
+ export declare type WalkerOption = WalkerOptionEnum | Token | null;
994
1016
  /**
995
1017
  * returned value:
996
- * - 'ignore': ignore this node and its children
997
- * - 'stop': stop walking the tree
998
- * - 'children': walk the children and ignore the node itself
999
- * - '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
1000
1022
  */
1001
1023
  export declare type WalkerFilter = (node: AstNode) => WalkerOption;
1002
1024
 
@@ -1007,7 +1029,7 @@ export declare type WalkerFilter = (node: AstNode) => WalkerOption;
1007
1029
  * - 'children': walk the children and ignore the node itself
1008
1030
  * - 'ignore-children': walk the node and ignore children
1009
1031
  */
1010
- 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;
1011
1033
 
1012
1034
  export declare interface WalkResult {
1013
1035
  node: AstNode;
@@ -1035,6 +1057,7 @@ export declare interface ErrorDescription {
1035
1057
  col: number;
1036
1058
  };
1037
1059
  error?: Error;
1060
+ rawTokens?: TokenizeResult[];
1038
1061
  }
1039
1062
 
1040
1063
  interface ValidationOptions {
@@ -1050,6 +1073,7 @@ interface MinifyOptions {
1050
1073
  expandNestingRules?: boolean;
1051
1074
  removeDuplicateDeclarations?: boolean;
1052
1075
  computeShorthand?: boolean;
1076
+ computeTransform?: boolean;
1053
1077
  computeCalcExpression?: boolean;
1054
1078
  inlineCssVariables?: boolean;
1055
1079
  removeEmpty?: boolean;
@@ -1165,6 +1189,14 @@ export declare interface TransformResult extends ParseResult, RenderResult {
1165
1189
  export declare interface ParseTokenOptions extends ParserOptions {
1166
1190
  }
1167
1191
 
1192
+ export declare interface TokenizeResult {
1193
+ token: string;
1194
+ len: number;
1195
+ hint?: EnumToken;
1196
+ position: Position;
1197
+ bytesIn: number;
1198
+ }
1199
+
1168
1200
  export declare interface SourceMapObject {
1169
1201
  version: number;
1170
1202
  file?: string;
@@ -1181,7 +1213,7 @@ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
1181
1213
  relative: string;
1182
1214
  };
1183
1215
 
1184
- declare function load(url: string, currentFile: string): Promise<string>;
1216
+ declare function load(url: string, currentFile?: string): Promise<string>;
1185
1217
 
1186
1218
  /**
1187
1219
  * render ast node
@@ -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)) {
@@ -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);