@tbela99/css-parser 1.4.2 → 1.4.3

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 (216) hide show
  1. package/.nyc_output/4874b20e-6f53-4d7a-be5a-cf68316925f2.json +1 -0
  2. package/.nyc_output/6193bc4c-6f5f-4898-8950-c628825e6342.json +1 -0
  3. package/.nyc_output/processinfo/4874b20e-6f53-4d7a-be5a-cf68316925f2.json +1 -0
  4. package/.nyc_output/processinfo/6193bc4c-6f5f-4898-8950-c628825e6342.json +1 -0
  5. package/.repl_history +4 -0
  6. package/CHANGELOG.md +164 -4
  7. package/README.md +43 -0
  8. package/badges/coverage.svg +20 -0
  9. package/deno.lock +2861 -0
  10. package/dist/config.json.js +33 -1
  11. package/dist/index-umd-web.js +24382 -18476
  12. package/dist/index.cjs +24522 -18618
  13. package/dist/index.d.ts +1396 -929
  14. package/dist/lib/ast/clone.d.ts +10 -0
  15. package/dist/lib/ast/clone.js +45 -0
  16. package/dist/lib/ast/expand.d.ts +14 -0
  17. package/dist/lib/ast/expand.js +89 -64
  18. package/dist/lib/ast/features/calc.d.ts +10 -0
  19. package/dist/lib/ast/features/calc.js +62 -24
  20. package/dist/lib/ast/features/if.d.ts +10 -0
  21. package/dist/lib/ast/features/if.js +215 -0
  22. package/dist/lib/ast/features/index.d.ts +6 -0
  23. package/dist/lib/ast/features/index.js +1 -0
  24. package/dist/lib/ast/features/inlinecssvariables.d.ts +15 -0
  25. package/dist/lib/ast/features/inlinecssvariables.js +32 -27
  26. package/dist/lib/ast/features/prefix.d.ts +8 -0
  27. package/dist/lib/ast/features/prefix.js +68 -43
  28. package/dist/lib/ast/features/shorthand.d.ts +12 -0
  29. package/dist/lib/ast/features/shorthand.js +6 -9
  30. package/dist/lib/ast/features/transform.d.ts +10 -0
  31. package/dist/lib/ast/features/transform.js +9 -13
  32. package/dist/lib/ast/features/type.d.ts +15 -0
  33. package/dist/lib/ast/find.d.ts +165 -0
  34. package/dist/lib/ast/find.js +175 -0
  35. package/dist/lib/ast/math/expression.d.ts +18 -0
  36. package/dist/lib/ast/math/expression.js +140 -98
  37. package/dist/lib/ast/math/math.d.ts +6 -0
  38. package/dist/lib/ast/math/math.js +30 -41
  39. package/dist/lib/ast/minify.d.ts +19 -0
  40. package/dist/lib/ast/minify.js +541 -217
  41. package/dist/lib/ast/transform/compute.d.ts +8 -0
  42. package/dist/lib/ast/transform/compute.js +82 -69
  43. package/dist/lib/ast/transform/matrix.d.ts +22 -0
  44. package/dist/lib/ast/transform/matrix.js +12 -26
  45. package/dist/lib/ast/transform/minify.d.ts +5 -0
  46. package/dist/lib/ast/transform/minify.js +20 -20
  47. package/dist/lib/ast/transform/perspective.d.ts +3 -0
  48. package/dist/lib/ast/transform/perspective.js +1 -1
  49. package/dist/lib/ast/transform/rotate.d.ts +12 -0
  50. package/dist/lib/ast/transform/rotate.js +1 -1
  51. package/dist/lib/ast/transform/scale.d.ts +6 -0
  52. package/dist/lib/ast/transform/scale.js +1 -1
  53. package/dist/lib/ast/transform/skew.d.ts +4 -0
  54. package/dist/lib/ast/transform/skew.js +1 -1
  55. package/dist/lib/ast/transform/translate.d.ts +6 -0
  56. package/dist/lib/ast/transform/translate.js +1 -1
  57. package/dist/lib/ast/transform/utils.d.ts +9 -0
  58. package/dist/lib/ast/types.d.ts +903 -0
  59. package/dist/lib/ast/types.js +277 -23
  60. package/dist/lib/ast/walk.d.ts +162 -0
  61. package/dist/lib/ast/walk.js +116 -60
  62. package/dist/lib/fs/resolve.d.ts +20 -0
  63. package/dist/lib/fs/resolve.js +37 -45
  64. package/dist/lib/parser/declaration/list.d.ts +16 -0
  65. package/dist/lib/parser/declaration/list.js +26 -24
  66. package/dist/lib/parser/declaration/map.d.ts +15 -0
  67. package/dist/lib/parser/declaration/map.js +140 -95
  68. package/dist/lib/parser/declaration/set.d.ts +9 -0
  69. package/dist/lib/parser/declaration/set.js +30 -25
  70. package/dist/lib/parser/node.d.ts +7 -0
  71. package/dist/lib/parser/parse.d.ts +107 -0
  72. package/dist/lib/parser/parse.js +1454 -1445
  73. package/dist/lib/parser/tokenize.d.ts +57 -0
  74. package/dist/lib/parser/tokenize.js +557 -404
  75. package/dist/lib/parser/utils/at-rule-container.d.ts +5 -0
  76. package/dist/lib/parser/utils/at-rule-container.js +486 -0
  77. package/dist/lib/parser/utils/at-rule-font-feature-values.d.ts +5 -0
  78. package/dist/lib/parser/utils/at-rule-font-feature-values.js +13 -0
  79. package/dist/lib/parser/utils/at-rule-generic.d.ts +5 -0
  80. package/dist/lib/parser/utils/at-rule-generic.js +118 -0
  81. package/dist/lib/parser/utils/at-rule-import.d.ts +5 -0
  82. package/dist/lib/parser/utils/at-rule-import.js +393 -0
  83. package/dist/lib/parser/utils/at-rule-media.d.ts +5 -0
  84. package/dist/lib/parser/utils/at-rule-media.js +603 -0
  85. package/dist/lib/parser/utils/at-rule-page.d.ts +5 -0
  86. package/dist/lib/parser/utils/at-rule-page.js +28 -0
  87. package/dist/lib/parser/utils/at-rule-support.d.ts +5 -0
  88. package/dist/lib/parser/utils/at-rule-support.js +366 -0
  89. package/dist/lib/parser/utils/at-rule-token.d.ts +1 -0
  90. package/dist/lib/parser/utils/at-rule-when-else.d.ts +5 -0
  91. package/dist/lib/parser/utils/at-rule-when-else.js +363 -0
  92. package/dist/lib/parser/utils/at-rule.d.ts +13 -0
  93. package/dist/lib/parser/utils/at-rule.js +37 -0
  94. package/dist/lib/parser/utils/cache.d.ts +6 -0
  95. package/dist/lib/parser/utils/cache.js +19 -0
  96. package/dist/lib/parser/utils/config.d.ts +2 -0
  97. package/dist/lib/parser/utils/config.js +1 -0
  98. package/dist/lib/parser/utils/declaration-list.d.ts +5 -0
  99. package/dist/lib/parser/utils/declaration.d.ts +18 -0
  100. package/dist/lib/parser/utils/declaration.js +569 -91
  101. package/dist/lib/parser/utils/eq.d.ts +1 -0
  102. package/dist/lib/parser/utils/hash.d.ts +21 -0
  103. package/dist/lib/parser/utils/hash.js +1 -1
  104. package/dist/lib/parser/utils/selector.d.ts +5 -0
  105. package/dist/lib/parser/utils/selector.js +476 -0
  106. package/dist/lib/parser/utils/text.d.ts +3 -0
  107. package/dist/lib/parser/utils/text.js +17 -1
  108. package/dist/lib/parser/utils/token.d.ts +14 -0
  109. package/dist/lib/parser/utils/token.js +102 -0
  110. package/dist/lib/parser/utils/type.d.ts +2 -0
  111. package/dist/lib/parser/utils/type.js +29 -18
  112. package/dist/lib/renderer/render.d.ts +28 -0
  113. package/dist/lib/renderer/render.js +421 -262
  114. package/dist/lib/renderer/sourcemap/lib/encode.d.ts +1 -0
  115. package/dist/lib/renderer/sourcemap/sourcemap.d.ts +26 -0
  116. package/dist/lib/renderer/sourcemap/sourcemap.js +17 -7
  117. package/dist/lib/syntax/color/a98rgb.d.ts +2 -0
  118. package/dist/lib/syntax/color/a98rgb.js +8 -12
  119. package/dist/lib/syntax/color/cmyk.d.ts +10 -0
  120. package/dist/lib/syntax/color/cmyk.js +23 -21
  121. package/dist/lib/syntax/color/color-mix.d.ts +2 -0
  122. package/dist/lib/syntax/color/color-mix.js +88 -77
  123. package/dist/lib/syntax/color/color.d.ts +42 -0
  124. package/dist/lib/syntax/color/color.js +65 -68
  125. package/dist/lib/syntax/color/hex.d.ts +16 -0
  126. package/dist/lib/syntax/color/hex.js +27 -31
  127. package/dist/lib/syntax/color/hsl.d.ts +20 -0
  128. package/dist/lib/syntax/color/hsl.js +5 -12
  129. package/dist/lib/syntax/color/hsv.d.ts +2 -0
  130. package/dist/lib/syntax/color/hwb.d.ts +21 -0
  131. package/dist/lib/syntax/color/hwb.js +8 -21
  132. package/dist/lib/syntax/color/lab.d.ts +25 -0
  133. package/dist/lib/syntax/color/lab.js +20 -21
  134. package/dist/lib/syntax/color/lch.d.ts +23 -0
  135. package/dist/lib/syntax/color/lch.js +13 -15
  136. package/dist/lib/syntax/color/oklab.d.ts +22 -0
  137. package/dist/lib/syntax/color/oklab.js +20 -39
  138. package/dist/lib/syntax/color/oklch.d.ts +20 -0
  139. package/dist/lib/syntax/color/oklch.js +14 -16
  140. package/dist/lib/syntax/color/p3.d.ts +6 -0
  141. package/dist/lib/syntax/color/p3.js +0 -8
  142. package/dist/lib/syntax/color/prophotorgb.d.ts +2 -0
  143. package/dist/lib/syntax/color/rec2020.d.ts +2 -0
  144. package/dist/lib/syntax/color/rec2020.js +9 -13
  145. package/dist/lib/syntax/color/relativecolor.d.ts +13 -0
  146. package/dist/lib/syntax/color/relativecolor.js +68 -41
  147. package/dist/lib/syntax/color/rgb.d.ts +20 -0
  148. package/dist/lib/syntax/color/rgb.js +14 -18
  149. package/dist/lib/syntax/color/srgb.d.ts +23 -0
  150. package/dist/lib/syntax/color/srgb.js +27 -26
  151. package/dist/lib/syntax/color/utils/components.d.ts +2 -0
  152. package/dist/lib/syntax/color/utils/components.js +30 -14
  153. package/dist/lib/syntax/color/utils/distance.d.ts +18 -0
  154. package/dist/lib/syntax/color/utils/distance.js +1 -8
  155. package/dist/lib/syntax/color/utils/matrix.d.ts +6 -0
  156. package/dist/lib/syntax/color/xyz.d.ts +5 -0
  157. package/dist/lib/syntax/color/xyz.js +8 -20
  158. package/dist/lib/syntax/color/xyzd50.d.ts +4 -0
  159. package/dist/lib/syntax/color/xyzd50.js +6 -20
  160. package/dist/lib/syntax/constants.d.ts +67 -0
  161. package/dist/lib/syntax/constants.js +436 -0
  162. package/dist/lib/syntax/syntax.d.ts +38 -0
  163. package/dist/lib/syntax/syntax.js +533 -568
  164. package/dist/lib/validation/config.d.ts +14 -0
  165. package/dist/lib/validation/config.js +72 -33
  166. package/dist/lib/validation/config.json.js +1159 -74
  167. package/dist/lib/validation/json.d.ts +2 -0
  168. package/dist/lib/validation/match.d.ts +38 -0
  169. package/dist/lib/validation/match.js +2985 -0
  170. package/dist/lib/validation/parser/parse.d.ts +8 -0
  171. package/dist/lib/validation/parser/parse.js +684 -935
  172. package/dist/lib/validation/parser/typedef.d.ts +95 -0
  173. package/dist/lib/validation/parser/typedef.js +100 -0
  174. package/dist/lib/validation/utils/list.d.ts +4 -0
  175. package/dist/lib/validation/utils/list.js +4 -11
  176. package/dist/lib/validation/utils/whitespace.d.ts +2 -0
  177. package/dist/lib/validation/utils/whitespace.js +2 -8
  178. package/dist/node.d.ts +207 -0
  179. package/dist/node.js +42 -39
  180. package/dist/web.d.ts +169 -0
  181. package/dist/web.js +38 -33
  182. package/package.json +15 -12
  183. package/playground/index.html +1328 -0
  184. package/playground/sw.js +55 -0
  185. package/playground/tree.js +176 -0
  186. package/dist/lib/syntax/color/utils/constants.js +0 -214
  187. package/dist/lib/syntax/utils.js +0 -70
  188. package/dist/lib/validation/at-rules/container.js +0 -342
  189. package/dist/lib/validation/at-rules/counter-style.js +0 -90
  190. package/dist/lib/validation/at-rules/custom-media.js +0 -50
  191. package/dist/lib/validation/at-rules/document.js +0 -89
  192. package/dist/lib/validation/at-rules/else.js +0 -5
  193. package/dist/lib/validation/at-rules/font-feature-values.js +0 -63
  194. package/dist/lib/validation/at-rules/import.js +0 -150
  195. package/dist/lib/validation/at-rules/keyframes.js +0 -67
  196. package/dist/lib/validation/at-rules/layer.js +0 -41
  197. package/dist/lib/validation/at-rules/media.js +0 -255
  198. package/dist/lib/validation/at-rules/namespace.js +0 -81
  199. package/dist/lib/validation/at-rules/page-margin-box.js +0 -64
  200. package/dist/lib/validation/at-rules/page.js +0 -100
  201. package/dist/lib/validation/at-rules/supports.js +0 -295
  202. package/dist/lib/validation/at-rules/when.js +0 -185
  203. package/dist/lib/validation/atrule.js +0 -184
  204. package/dist/lib/validation/selector.js +0 -36
  205. package/dist/lib/validation/syntax.js +0 -1073
  206. package/dist/lib/validation/syntaxes/complex-selector-list.js +0 -27
  207. package/dist/lib/validation/syntaxes/complex-selector.js +0 -52
  208. package/dist/lib/validation/syntaxes/compound-selector.js +0 -196
  209. package/dist/lib/validation/syntaxes/family-name.js +0 -57
  210. package/dist/lib/validation/syntaxes/keyframe-selector.js +0 -36
  211. package/dist/lib/validation/syntaxes/layer-name.js +0 -57
  212. package/dist/lib/validation/syntaxes/relative-selector-list.js +0 -31
  213. package/dist/lib/validation/syntaxes/relative-selector.js +0 -38
  214. package/dist/lib/validation/syntaxes/selector-list.js +0 -5
  215. package/dist/lib/validation/syntaxes/selector.js +0 -5
  216. package/dist/lib/validation/syntaxes/url.js +0 -40
@@ -1,19 +1,24 @@
1
- import { parseString, replaceToken } from '../parser/parse.js';
2
- import '../parser/tokenize.js';
3
- import '../parser/utils/config.js';
4
- import { EnumToken } from './types.js';
5
- import { walkValues } from './walk.js';
6
- import { doRender, renderToken } from '../renderer/render.js';
7
- import '../renderer/sourcemap/lib/encode.js';
8
- import { isWhiteSpace, isIdent, isFunction, isIdentStart } from '../syntax/syntax.js';
9
1
  import { eq } from '../parser/utils/eq.js';
2
+ import { renderToken, doRender } from '../renderer/render.js';
10
3
  import * as index from './features/index.js';
4
+ import { walkValues } from './walk.js';
5
+ import { EnumToken } from './types.js';
6
+ import { isWhiteSpace, isIdent, isFunction, isIdentStart } from '../syntax/syntax.js';
11
7
  import { FeatureWalkMode } from './features/type.js';
8
+ import { trimArray } from '../validation/match.js';
9
+ import { definedPropertySettings, combinators } from '../syntax/constants.js';
10
+ import { replaceToken } from '../parser/utils/token.js';
11
+ import { parseString } from '../parser/parse.js';
12
+ import { tokenize } from '../parser/tokenize.js';
13
+ import { replaceCompound } from './expand.js';
12
14
 
13
- const combinators = ['+', '>', '~', '||', '|'];
14
- const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
15
- const notEndingWith = ['(', '['].concat(combinators);
16
- const rules = [EnumToken.AtRuleNodeType, EnumToken.RuleNodeType, EnumToken.AtRuleTokenType, EnumToken.KeyFramesRuleNodeType];
15
+ const notEndingWith = ["(", "["].concat(combinators);
16
+ const rules = [
17
+ EnumToken.AtRuleNodeType,
18
+ EnumToken.RuleNodeType,
19
+ EnumToken.AtRuleTokenType,
20
+ EnumToken.KeyFramesRuleNodeType,
21
+ ];
17
22
  // @ts-ignore
18
23
  const features = Object.values(index).sort((a, b) => a.ordering - b.ordering);
19
24
  /**
@@ -31,14 +36,15 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
31
36
  let postprocess = false;
32
37
  let parents;
33
38
  let replacement;
34
- if (!('features' in options)) {
39
+ if (!("features" in options)) {
35
40
  // @ts-ignore
36
41
  options = {
37
42
  removeDuplicateDeclarations: true,
38
43
  computeShorthand: true,
39
44
  computeCalcExpression: true,
40
45
  removePrefix: false,
41
- features: [], ...options
46
+ features: [],
47
+ ...options,
42
48
  };
43
49
  for (const feature of features) {
44
50
  feature.register(options);
@@ -56,17 +62,23 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
56
62
  if (preprocess) {
57
63
  parents = new Set([ast]);
58
64
  for (const parent of parents) {
59
- if (parent.typ == EnumToken.CommentTokenType ||
60
- parent.typ == EnumToken.CDOCOMMTokenType) {
65
+ if (parent.typ == EnumToken.CommentTokenType || parent.typ == EnumToken.CDOCOMMTokenType) {
61
66
  continue;
62
67
  }
63
68
  replacement = parent;
64
69
  for (const feature of options.features) {
65
- if ((feature.processMode & FeatureWalkMode.Pre) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
70
+ if ((feature.processMode & FeatureWalkMode.Pre) === 0 ||
71
+ (feature.accept != null && !feature.accept.has(parent.typ))) {
66
72
  continue;
67
73
  }
68
74
  if (rules.includes(replacement.typ) && !Array.isArray(replacement.tokens)) {
69
- Object.defineProperty(replacement, 'tokens', { ...definedPropertySettings, value: parseString(replacement.typ == EnumToken.RuleNodeType || replacement.typ == EnumToken.KeyFramesRuleNodeType ? replacement.sel : replacement.val) });
75
+ Object.defineProperty(replacement, "tokens", {
76
+ ...definedPropertySettings,
77
+ value: parseString(replacement.typ == EnumToken.RuleNodeType ||
78
+ replacement.typ === EnumToken.KeyFramesRuleNodeType
79
+ ? replacement.sel
80
+ : replacement.nam),
81
+ });
70
82
  }
71
83
  const result = feature.run(replacement, options, parent.parent ?? ast, context, FeatureWalkMode.Pre);
72
84
  if (result != null) {
@@ -77,18 +89,18 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
77
89
  // @ts-ignore
78
90
  replaceToken(parent.parent, parent, replacement);
79
91
  }
80
- if (('chi' in replacement)) {
92
+ if ("chi" in replacement) {
81
93
  // @ts-ignore
82
94
  for (const node of replacement.chi) {
83
- parents.add(Object.defineProperty(node, 'parent', {
95
+ parents.add(Object.defineProperty(node, "parent", {
84
96
  ...definedPropertySettings,
85
- value: replacement
97
+ value: replacement,
86
98
  }));
87
99
  }
88
100
  }
89
101
  }
90
102
  for (const feature of options.features) {
91
- if ((feature.processMode & FeatureWalkMode.Pre) && 'cleanup' in feature) {
103
+ if (feature.processMode & FeatureWalkMode.Pre && "cleanup" in feature) {
92
104
  // @ts-ignore
93
105
  feature.cleanup(ast, options, context, FeatureWalkMode.Pre);
94
106
  }
@@ -97,14 +109,14 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
97
109
  doMinify(ast, options, recursive, errors, nestingContent, context);
98
110
  parents = new Set([ast]);
99
111
  for (const parent of parents) {
100
- if (parent.typ == EnumToken.CommentTokenType ||
101
- parent.typ == EnumToken.CDOCOMMTokenType) {
112
+ if (parent.typ == EnumToken.CommentTokenType || parent.typ == EnumToken.CDOCOMMTokenType) {
102
113
  continue;
103
114
  }
104
115
  replacement = parent;
105
116
  if (postprocess) {
106
117
  for (const feature of options.features) {
107
- if ((feature.processMode & FeatureWalkMode.Post) === 0 || (feature.accept != null && !feature.accept.has(parent.typ))) {
118
+ if ((feature.processMode & FeatureWalkMode.Post) === 0 ||
119
+ (feature.accept != null && !feature.accept.has(parent.typ))) {
108
120
  continue;
109
121
  }
110
122
  const result = feature.run(replacement, options, parent.parent ?? ast, context, FeatureWalkMode.Post);
@@ -117,18 +129,18 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
117
129
  // @ts-ignore
118
130
  replaceToken(parent.parent, parent, replacement);
119
131
  }
120
- if (('chi' in replacement)) {
132
+ if ("chi" in replacement) {
121
133
  for (const node of replacement.chi) {
122
- parents.add(Object.defineProperty(node, 'parent', {
134
+ parents.add(Object.defineProperty(node, "parent", {
123
135
  ...definedPropertySettings,
124
- value: replacement
136
+ value: replacement,
125
137
  }));
126
138
  }
127
139
  }
128
140
  }
129
141
  if (postprocess) {
130
142
  for (const feature of options.features) {
131
- if (feature.processMode & FeatureWalkMode.Post && 'cleanup' in feature) {
143
+ if (feature.processMode & FeatureWalkMode.Post && "cleanup" in feature) {
132
144
  // @ts-ignore
133
145
  feature.cleanup(ast, options, context, FeatureWalkMode.Post);
134
146
  }
@@ -136,6 +148,141 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
136
148
  }
137
149
  return ast;
138
150
  }
151
+ function transformAtRuleMediaPrelude(values) {
152
+ let hasUpdates = false;
153
+ for (let { value, parent, parents } of walkValues(values)) {
154
+ if (value.typ === EnumToken.MediaQueryConditionTokenType) {
155
+ if (value.op.typ == EnumToken.AndTokenType &&
156
+ // @ts-ignore
157
+ value.l.typ === EnumToken.IdenTokenType &&
158
+ // @ts-ignore
159
+ value.l.val.toLowerCase() === "all") {
160
+ if (parent === null) {
161
+ // @ts-ignore
162
+ values[values.indexOf(value)] = value.l;
163
+ }
164
+ else {
165
+ replaceToken(parent, value, value.l);
166
+ // @ts-ignore
167
+ value = value.l;
168
+ }
169
+ hasUpdates = true;
170
+ }
171
+ }
172
+ // range operator
173
+ if (parent != null &&
174
+ parent.typ === EnumToken.MediaQueryConditionTokenType &&
175
+ parent.op.typ == EnumToken.AndTokenType &&
176
+ // @ts-ignore
177
+ parent.l.typ == EnumToken.ParensTokenType) {
178
+ let token = parent.r.find((t) => t.typ !== EnumToken.WhitespaceTokenType && t.typ !== EnumToken.CommentTokenType);
179
+ if (token?.typ === EnumToken.ParensTokenType) {
180
+ // @ts-ignore
181
+ const node1 = parent.l.chi.find((t) => t.typ !== EnumToken.WhitespaceTokenType && t.typ !== EnumToken.CommentTokenType);
182
+ const node2 = token.chi.find((t) => t.typ !== EnumToken.WhitespaceTokenType && t.typ !== EnumToken.CommentTokenType);
183
+ if (node1?.typ === EnumToken.MediaQueryConditionTokenType &&
184
+ node2?.typ === EnumToken.MediaQueryConditionTokenType &&
185
+ node1.op.typ == EnumToken.ColonTokenType &&
186
+ node2.op.typ == EnumToken.ColonTokenType &&
187
+ // @ts-ignore
188
+ node1.l.typ == EnumToken.IdenTokenType &&
189
+ // @ts-ignore
190
+ node2.l.typ == EnumToken.IdenTokenType &&
191
+ // @ts-ignore
192
+ node1.l.val.startsWith("min-") &&
193
+ // @ts-ignore
194
+ node2.l.val.startsWith("max-") &&
195
+ // @ts-ignore
196
+ node1.l.val.slice(4) ==
197
+ // @ts-ignore
198
+ node2.l.val.slice(4)) {
199
+ const val1 = node1.r.find((t) => t.typ !== EnumToken.WhitespaceTokenType && t.typ !== EnumToken.CommentTokenType);
200
+ const val2 = node2.r.find((t) => t.typ !== EnumToken.WhitespaceTokenType && t.typ !== EnumToken.CommentTokenType);
201
+ const replacement = {
202
+ typ: EnumToken.ParensTokenType,
203
+ chi: [
204
+ // @ts-ignore
205
+ {
206
+ typ: EnumToken.MediaRangeQueryTokenType,
207
+ op: {
208
+ typ: EnumToken.IdenTokenType,
209
+ // @ts-ignore
210
+ val: node1.l.val.slice(4),
211
+ },
212
+ l: val1,
213
+ r: val2,
214
+ loc: value.loc,
215
+ },
216
+ ],
217
+ };
218
+ // @ts-expect-error
219
+ const p = parents?.[parents?.indexOf?.(parent) + 1];
220
+ if (p != null) {
221
+ replaceToken(p, parent, replacement);
222
+ }
223
+ else {
224
+ values.splice(values.indexOf(parent), 1, replacement);
225
+ }
226
+ hasUpdates = true;
227
+ value = replacement;
228
+ }
229
+ }
230
+ }
231
+ }
232
+ return { hasUpdates, values: trimArray(values) };
233
+ }
234
+ /**
235
+ * minify at-rule media
236
+ * - remove redundant tokens
237
+ * - generate range queries
238
+ * @param ast
239
+ *
240
+ * @private
241
+ */
242
+ function minifyAtRuleMedia(tokens) {
243
+ let hasUpdates = false;
244
+ const sections = tokens
245
+ .reduce((acc, t) => {
246
+ if (t.typ === EnumToken.CommaTokenType) {
247
+ acc.push([]);
248
+ }
249
+ else {
250
+ acc[acc.length - 1].push(t);
251
+ }
252
+ return acc;
253
+ }, [[]])
254
+ .reduce((acc, values) => {
255
+ if (acc.has("all")) {
256
+ return acc;
257
+ }
258
+ const result = transformAtRuleMediaPrelude(values);
259
+ if (result.values.length === 0) {
260
+ return acc;
261
+ }
262
+ if (result.hasUpdates) {
263
+ hasUpdates = true;
264
+ }
265
+ acc.set(values.reduce((acc, t) => acc + renderToken(t), ""), result.values);
266
+ return acc;
267
+ }, new Map());
268
+ if (sections.has("all")) {
269
+ tokens.length = 0;
270
+ }
271
+ else if (hasUpdates) {
272
+ tokens.length = 0;
273
+ tokens.push(...[...sections.values()].reduce((acc, t) => {
274
+ if (acc.length > 0) {
275
+ acc.push({
276
+ typ: EnumToken.CommaTokenType,
277
+ });
278
+ }
279
+ acc.push(...t);
280
+ return acc;
281
+ }, []));
282
+ }
283
+ // return ast;
284
+ return tokens;
285
+ }
139
286
  /**
140
287
  * reduce selectors
141
288
  * @param acc
@@ -145,16 +292,12 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
145
292
  */
146
293
  function reduce(acc, curr) {
147
294
  // trim :is()
148
- // if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
149
- //
150
- // curr = curr.slice(1, -1);
151
- // }
152
- if (curr[0] == '&') {
153
- if (curr[1] == ' ' && !isIdent(curr[2]) && !isFunction(curr[2])) {
295
+ if (curr[0] == "&") {
296
+ if (curr[1] == " " && !isIdent(curr[2]) && !isFunction(curr[2])) {
154
297
  curr.splice(0, 2);
155
298
  }
156
299
  }
157
- acc.push(curr.join(''));
300
+ acc.push(curr.join(""));
158
301
  return acc;
159
302
  }
160
303
  /**
@@ -169,15 +312,15 @@ function reduce(acc, curr) {
169
312
  * @private
170
313
  */
171
314
  function doMinify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
172
- if (!('nodes' in context)) {
173
- context.nodes = new Set;
315
+ if (!("nodes" in context)) {
316
+ context.nodes = new Set();
174
317
  }
175
318
  if (context.nodes.has(ast)) {
176
319
  return ast;
177
320
  }
178
321
  context.nodes.add(ast);
179
322
  // @ts-ignore
180
- if ('chi' in ast && ast.chi.length > 0) {
323
+ if ("chi" in ast && ast.chi.length > 0) {
181
324
  const reducer = reduce.bind(ast);
182
325
  if (!nestingContent) {
183
326
  nestingContent = options.nestingRules && ast.typ == EnumToken.RuleNodeType;
@@ -187,28 +330,40 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
187
330
  let node = null;
188
331
  let nodeIndex = -1;
189
332
  for (; i < ast.chi.length; i++) {
190
- if (ast.chi[i].typ == EnumToken.CommentNodeType) {
333
+ if (ast.chi[i].typ === EnumToken.CommentNodeType ||
334
+ ast.chi[i].typ === EnumToken.InvalidRuleNodeType ||
335
+ ast.chi[i].typ === EnumToken.InvalidRuleNodeType) {
336
+ continue;
337
+ }
338
+ while (previous?.typ === EnumToken.CommentNodeType ||
339
+ previous?.typ === EnumToken.InvalidRuleNodeType ||
340
+ previous?.typ === EnumToken.InvalidRuleNodeType) {
341
+ previous = ast.chi[--nodeIndex];
191
342
  continue;
192
343
  }
193
344
  node = ast.chi[i];
194
- if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'font-face') {
345
+ if (node.typ === EnumToken.AtRuleNodeType && node.nam === "font-face") {
195
346
  continue;
196
347
  }
197
- if (node.typ == EnumToken.KeyframesAtRuleNodeType) {
198
- if (previous?.typ == EnumToken.KeyframesAtRuleNodeType &&
199
- node.nam == previous.nam &&
200
- node.val == previous.val) {
348
+ if (node.typ === EnumToken.KeyframesAtRuleNodeType) {
349
+ if (previous?.typ === EnumToken.KeyframesAtRuleNodeType &&
350
+ node.nam === previous.nam &&
351
+ node.val === previous.val) {
201
352
  ast.chi?.splice(nodeIndex--, 1);
202
353
  previous = ast?.chi?.[nodeIndex] ?? null;
203
354
  i = nodeIndex;
204
355
  continue;
205
356
  }
206
357
  }
207
- else if (node.typ == EnumToken.KeyFramesRuleNodeType) {
208
- if (previous?.typ == EnumToken.KeyFramesRuleNodeType &&
209
- node.sel == previous.sel) {
358
+ else if (node.typ === EnumToken.KeyFramesRuleNodeType) {
359
+ if (previous?.typ === EnumToken.KeyFramesRuleNodeType &&
360
+ node.sel === previous.sel) {
361
+ // do not merge keyframes
362
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@keyframes#resolving_duplicates
210
363
  previous.chi.push(...node.chi);
211
- ast.chi.splice(i--, 1);
364
+ ast.chi.splice(i, 1);
365
+ previous = ast?.chi?.[nodeIndex] ?? null;
366
+ i = nodeIndex;
212
367
  continue;
213
368
  }
214
369
  let k;
@@ -216,7 +371,8 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
216
371
  if (node.chi[k].typ == EnumToken.DeclarationNodeType) {
217
372
  let l = node.chi[k].val.length;
218
373
  while (l--) {
219
- if (node.chi[k].val[l].typ == EnumToken.ImportantTokenType) {
374
+ if (node.chi[k].val[l].typ ==
375
+ EnumToken.ImportantTokenType) {
220
376
  node.chi.splice(k--, 1);
221
377
  break;
222
378
  }
@@ -229,16 +385,57 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
229
385
  }
230
386
  }
231
387
  else if (node.typ == EnumToken.AtRuleNodeType) {
232
- if (node.nam == 'media' && ['all', '', null].includes(node.val)) {
233
- ast.chi?.splice(i, 1, ...node.chi);
234
- i--;
235
- continue;
388
+ if (node.nam == "media") {
389
+ if (Array.isArray(node.tokens)) {
390
+ const slice = node.tokens.slice();
391
+ minifyAtRuleMedia(slice);
392
+ if (slice.length !== node.tokens.length) {
393
+ node.tokens.length = 0;
394
+ node.tokens.push(...slice);
395
+ node.val = slice.reduce((acc, curr, index, arr) => acc +
396
+ (curr.typ === EnumToken.CommentTokenType ||
397
+ (curr.typ === EnumToken.WhitespaceTokenType &&
398
+ arr[index + 1]?.typ === EnumToken.CommentTokenType &&
399
+ (index + 3 < arr.length ||
400
+ arr[index + 2]?.typ === EnumToken.WhitespaceTokenType))
401
+ ? ""
402
+ : renderToken(curr)), "");
403
+ }
404
+ }
405
+ if (["all", "", null].includes(node.val)) {
406
+ ast.chi?.splice(i, 1, ...node.chi);
407
+ i--;
408
+ continue;
409
+ }
410
+ }
411
+ else if (node.nam === "import" && Array.isArray(node.tokens)) {
412
+ let l = 0;
413
+ let token;
414
+ for (; l < node.tokens.length; l++) {
415
+ token = node.tokens[l];
416
+ if (token.typ === EnumToken.ParensTokenType ||
417
+ token.typ === EnumToken.MediaQueryConditionTokenType ||
418
+ (token.typ === EnumToken.IdenTokenType && "layer" !== token.val)) {
419
+ break;
420
+ }
421
+ }
422
+ if (l < node.tokens.length) {
423
+ const slice = node.tokens?.slice(l);
424
+ node.tokens.splice(l, slice.length, ...minifyAtRuleMedia(slice));
425
+ node.val = trimArray(node.tokens).reduce((acc, curr, index, arr) => acc +
426
+ (curr.typ === EnumToken.CommentTokenType ||
427
+ (curr.typ === EnumToken.WhitespaceTokenType &&
428
+ arr[index + 1]?.typ === EnumToken.CommentTokenType &&
429
+ (index + 3 < arr.length || arr[index + 2].typ === EnumToken.WhitespaceTokenType))
430
+ ? ""
431
+ : renderToken(curr)), "");
432
+ }
236
433
  }
237
434
  if (previous?.typ == EnumToken.AtRuleNodeType &&
238
- node.nam != 'font-face' &&
239
- previous.nam == node.nam &&
240
- previous.val == node.val) {
241
- if ('chi' in node) {
435
+ node.nam != "font-face" &&
436
+ previous.nam === node.nam &&
437
+ previous.val === node.val) {
438
+ if ("chi" in node) {
242
439
  // @ts-ignore
243
440
  previous.chi.push(...node.chi);
244
441
  if (!hasDeclaration(previous)) {
@@ -257,7 +454,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
257
454
  continue;
258
455
  }
259
456
  // @ts-ignore
260
- else if (node.typ == EnumToken.RuleNodeType) {
457
+ else if (node.typ === EnumToken.RuleNodeType) {
261
458
  reduceRuleSelector(node);
262
459
  let wrapper = null;
263
460
  let match;
@@ -265,7 +462,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
265
462
  if (previous?.typ == EnumToken.RuleNodeType) {
266
463
  reduceRuleSelector(previous);
267
464
  // @ts-ignore
268
- match = matchSelectors(previous.raw, node.raw, ast.typ);
465
+ match = matchSelectors(previous.raw, node.raw);
269
466
  if (match != null) {
270
467
  wrapper = wrapNodes(previous, node, match, ast, reducer, i, nodeIndex);
271
468
  nodeIndex = i - 1;
@@ -299,13 +496,13 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
299
496
  // @ts-ignore
300
497
  wrapper = { ...node, chi: [], sel: node.optimized.optimized[0] };
301
498
  // @ts-ignore
302
- Object.defineProperty(wrapper, 'raw', {
499
+ Object.defineProperty(wrapper, "raw", {
303
500
  ...definedPropertySettings,
304
501
  // @ts-ignore
305
- value: [[node.optimized.optimized[0]]]
502
+ value: [[node.optimized.optimized[0]]],
306
503
  });
307
504
  // @ts-ignore
308
- node.sel = node.optimized.selector.reduce(reducer, []).join(',');
505
+ node.sel = node.optimized.selector.reduce(reducer, []).join(",");
309
506
  // @ts-ignore
310
507
  node.raw = node.optimized.selector.slice();
311
508
  // @ts-ignore
@@ -314,14 +511,30 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
314
511
  ast.chi.splice(i, 1, wrapper);
315
512
  node = wrapper;
316
513
  }
514
+ else if (node.optimized?.reducible) {
515
+ if (node.optimized.optimized.length === 1) {
516
+ const sel1 = node.optimized.optimized[0] +
517
+ ":is(" +
518
+ node.optimized.selector.reduce(reducer, []).join(",") +
519
+ ")";
520
+ const sel2 = node.optimized.selector.reduce((acc, curr) => (acc.length > 0 ? acc + "," : "") + node.optimized.optimized[0] + curr.join(""), "");
521
+ node.sel = sel1.length < sel2.length ? sel1 : sel2;
522
+ }
523
+ else if (node.optimized.optimized.length === 0) {
524
+ const testIdent = /^[a-zA-Z]/;
525
+ node.sel = node.optimized.selector.reduce((acc, curr) => (acc.length > 0 ? acc + "," : "") +
526
+ (nestingContent && testIdent.test(curr[0]) ? "& " : "") +
527
+ curr.join(""), "");
528
+ }
529
+ }
317
530
  }
318
531
  // @ts-ignore
319
532
  else if (node.optimized?.match) {
320
533
  let wrap = true;
321
534
  // @ts-ignore
322
535
  const selector = node.optimized.selector.reduce((acc, curr) => {
323
- if (curr[0] == '&' && curr.length > 1) {
324
- if (curr[1] == ' ') {
536
+ if (curr[0] == "&" && curr.length > 1) {
537
+ if (curr[1] == " ") {
325
538
  curr.splice(0, 2);
326
539
  }
327
540
  else {
@@ -329,14 +542,14 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
329
542
  }
330
543
  }
331
544
  else if (combinators.includes(curr[0])) {
332
- curr.unshift('&');
545
+ curr.unshift("&");
333
546
  wrap = false;
334
547
  }
335
548
  acc.push(curr);
336
549
  return acc;
337
550
  }, []);
338
551
  if (!wrap) {
339
- wrap = selector.some((s) => s[0] != '&');
552
+ wrap = selector.some((s) => s[0] != "&");
340
553
  }
341
554
  let rule = null;
342
555
  const optimized = node.optimized.optimized.slice();
@@ -345,50 +558,82 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
345
558
  if (!combinators.includes(check)) {
346
559
  let last = optimized.pop();
347
560
  wrap = false;
348
- rule = optimized.join('') + `:is(${selector.map(s => {
349
- if (s[0] == '&') {
350
- s.splice(0, 1, last);
351
- }
352
- else {
353
- s.unshift(last);
354
- }
355
- return s.join('');
356
- }).join(',')})`;
561
+ rule =
562
+ optimized.join("") +
563
+ `:is(${selector
564
+ .map((s) => {
565
+ if (s[0] == "&") {
566
+ s.splice(0, 1, last);
567
+ }
568
+ else {
569
+ s.unshift(last);
570
+ }
571
+ return s.join("");
572
+ })
573
+ .join(",")})`;
357
574
  }
358
575
  }
359
576
  if (rule == null) {
360
- rule = selector.map((s) => {
361
- if (s[0] == '&') {
577
+ rule = selector
578
+ .map((s) => {
579
+ if (s[0] == "&") {
362
580
  s.splice(0, 1, ...node.optimized.optimized);
363
581
  }
364
- return s.join('');
365
- }).join(',');
582
+ return s.join("");
583
+ })
584
+ .join(",");
585
+ }
586
+ let sel = wrap ? node.optimized.optimized.join("") + `:is(${rule})` : rule;
587
+ if (sel.length < node.sel.length) {
588
+ node.sel = sel;
366
589
  }
367
- let sel = wrap ? node.optimized.optimized.join('') + `:is(${rule})` : rule;
590
+ }
591
+ else if (node.optimized?.reducible) {
592
+ if (node.optimized.optimized.length === 1) {
593
+ const sel1 = node.optimized.optimized[0] +
594
+ ":is(" +
595
+ node.optimized.selector.reduce(reducer, []).join(",") +
596
+ ")";
597
+ const sel2 = node.optimized.selector.reduce((acc, curr) => (acc.length > 0 ? acc + "," : "") + node.optimized.optimized[0] + curr.join(""), "");
598
+ node.sel = sel1.length < sel2.length ? sel1 : sel2;
599
+ }
600
+ else if (node.optimized.optimized.length === 0) {
601
+ const testIdent = /^[a-zA-Z]/;
602
+ node.sel = node.optimized.selector.reduce((acc, curr) => (acc.length > 0 ? acc + "," : "") +
603
+ (nestingContent && testIdent.test(curr[0]) ? "& " : "") +
604
+ curr.join(""), "");
605
+ }
606
+ }
607
+ else if (node.optimized?.optimized.length > 0) {
608
+ const sel = node.optimized.optimized.join("");
368
609
  if (sel.length < node.sel.length) {
369
610
  node.sel = sel;
611
+ node.raw = [node.optimized.optimized.slice()];
370
612
  }
371
613
  }
372
614
  doMinify(node, options, recursive, errors, nestingContent, context);
373
615
  }
374
616
  if (previous != null) {
375
- if ('chi' in previous && ('chi' in node)) {
376
- if (previous.typ == node.typ) {
617
+ if ("chi" in previous && "chi" in node) {
618
+ if (previous.typ === node.typ) {
377
619
  let shouldMerge = true;
378
620
  let k = previous.chi.length;
379
621
  while (k-- > 0) {
380
- if (previous.chi[k].typ == EnumToken.CommentNodeType) {
622
+ if (previous.chi[k].typ === EnumToken.CommentNodeType ||
623
+ previous.chi[k].typ === EnumToken.InvalidRuleNodeType ||
624
+ previous.chi[k].typ === EnumToken.InvalidRuleNodeType) {
381
625
  continue;
382
626
  }
383
- shouldMerge = previous.chi[k].typ == EnumToken.DeclarationNodeType;
627
+ shouldMerge = previous.chi[k].typ === EnumToken.DeclarationNodeType;
384
628
  break;
385
629
  }
386
630
  if (shouldMerge) {
387
- // @ts-ignore
388
- if (((node.typ == EnumToken.RuleNodeType || node.typ == EnumToken.KeyFramesRuleNodeType) && node.sel == previous.sel) ||
389
- // @ts-ignore
390
- (node.typ == EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
391
- // @ts-ignore
631
+ if (((node.typ === EnumToken.RuleNodeType ||
632
+ node.typ === EnumToken.KeyFramesRuleNodeType) &&
633
+ node.sel === previous.sel) ||
634
+ (node.typ == EnumToken.AtRuleNodeType &&
635
+ node.nam !== "font-face" &&
636
+ node.nam === previous.nam)) {
392
637
  node.chi.unshift(...previous.chi);
393
638
  doMinify(node, options, recursive, errors, nestingContent, context);
394
639
  ast.chi.splice(nodeIndex, 1);
@@ -396,7 +641,8 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
396
641
  nodeIndex = i;
397
642
  continue;
398
643
  }
399
- else if (node.typ == previous?.typ && [EnumToken.KeyFramesRuleNodeType, EnumToken.RuleNodeType].includes(node.typ)) {
644
+ else if (node.typ == previous?.typ &&
645
+ [EnumToken.KeyFramesRuleNodeType, EnumToken.RuleNodeType].includes(node.typ)) {
400
646
  const intersect = diff(previous, node, reducer, options);
401
647
  if (intersect != null) {
402
648
  if (intersect.node1.chi.length == 0) {
@@ -416,7 +662,6 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
416
662
  ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
417
663
  i = (nodeIndex ?? 0) + 1;
418
664
  }
419
- reduceRuleSelector(intersect.result);
420
665
  if (node != ast.chi[i]) {
421
666
  node = ast.chi[i];
422
667
  }
@@ -436,15 +681,16 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
436
681
  if (!nestingContent &&
437
682
  previous != null &&
438
683
  previous.typ == EnumToken.RuleNodeType &&
439
- previous.sel.includes('&')) {
684
+ previous.sel.includes("&")) {
440
685
  fixSelector(previous);
441
686
  }
442
687
  previous = node;
443
688
  nodeIndex = i;
444
689
  }
445
- if (recursive && node != null && ('chi' in node)) {
446
- if (node.typ == EnumToken.KeyframesAtRuleNodeType || !node.chi.some((n) => n.typ == EnumToken.DeclarationNodeType)) {
447
- if (!(node.typ == EnumToken.AtRuleNodeType && node.nam != 'font-face')) {
690
+ if (recursive && node != null && "chi" in node) {
691
+ if (node.typ == EnumToken.KeyframesAtRuleNodeType ||
692
+ !node.chi.some((n) => n.typ == EnumToken.DeclarationNodeType)) {
693
+ if (!(node.typ == EnumToken.AtRuleNodeType && node.nam != "font-face")) {
448
694
  doMinify(node, options, recursive, errors, nestingContent, context);
449
695
  }
450
696
  }
@@ -452,7 +698,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
452
698
  if (!nestingContent &&
453
699
  node != null &&
454
700
  node.typ == EnumToken.RuleNodeType &&
455
- node.sel.includes('&')) {
701
+ node.sel.includes("&")) {
456
702
  fixSelector(node);
457
703
  }
458
704
  }
@@ -483,13 +729,15 @@ function hasDeclaration(node) {
483
729
  * @private
484
730
  */
485
731
  function optimizeSelector(selector) {
486
- selector = selector.reduce((acc, curr) => {
732
+ const map = new Set();
733
+ selector = selector
734
+ .reduce((acc, curr) => {
487
735
  // @ts-ignore
488
- if (curr.length > 0 && curr.at(-1).startsWith(':is(')) {
736
+ if (curr.length > 0 && curr.at(-1).startsWith(":is(")) {
489
737
  // @ts-ignore
490
- const rules = splitRule(curr.at(-1).slice(4, -1)).map(x => {
491
- if (x[0] == '&' && x.length > 1) {
492
- return x.slice(x[1] == ' ' ? 2 : 1);
738
+ const rules = splitRule(curr.at(-1).slice(4, -1)).map((x) => {
739
+ if (x[0] == "&" && x.length > 1) {
740
+ return x.slice(x[1] == " " ? 2 : 1);
493
741
  }
494
742
  return x;
495
743
  });
@@ -501,9 +749,17 @@ function optimizeSelector(selector) {
501
749
  }
502
750
  acc.push(curr);
503
751
  return acc;
504
- }, []);
752
+ }, [])
753
+ .filter((x) => {
754
+ const str = x.join("");
755
+ if (map.has(str)) {
756
+ return false;
757
+ }
758
+ map.add(str);
759
+ return true;
760
+ });
505
761
  const optimized = [];
506
- const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
762
+ const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : curr.length == 0 ? acc : Math.min(acc, curr.length), 0);
507
763
  let i = 0;
508
764
  let j;
509
765
  let match;
@@ -523,7 +779,7 @@ function optimizeSelector(selector) {
523
779
  }
524
780
  while (optimized.length > 0) {
525
781
  const last = optimized.at(-1);
526
- if ((last == ' ' || combinators.includes(last))) {
782
+ if (last == " " || combinators.includes(last)) {
527
783
  optimized.pop();
528
784
  continue;
529
785
  }
@@ -531,19 +787,17 @@ function optimizeSelector(selector) {
531
787
  }
532
788
  selector.forEach((selector) => selector.splice(0, optimized.length));
533
789
  let reducible = optimized.length == 1;
534
- if (optimized[0] == '&') {
535
- if (optimized[1] == ' ') {
790
+ if (optimized[0] == "&") {
791
+ if (optimized[1] == " ") {
536
792
  optimized.splice(0, 2);
537
793
  }
538
794
  }
539
- if (optimized.length == 0 ||
540
- (optimized[0].charAt(0) == '&' ||
541
- selector.length == 1)) {
795
+ if (optimized.length == 0 || optimized[0].charAt(0) == "&" || selector.length == 1) {
542
796
  return {
543
797
  match: false,
544
798
  optimized,
545
- selector: selector.map((selector) => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : (selector)),
546
- reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0]))
799
+ selector: selector.map((selector) => selector[0] == "&" && selector[1] == " " ? selector.slice(2) : selector),
800
+ reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0])),
547
801
  };
548
802
  }
549
803
  return {
@@ -552,26 +806,26 @@ function optimizeSelector(selector) {
552
806
  selector: selector.reduce((acc, curr) => {
553
807
  let hasCompound = true;
554
808
  if (hasCompound && curr.length > 0) {
555
- hasCompound = !['&'].concat(combinators).includes(curr[0].charAt(0));
809
+ hasCompound = !["&"].concat(combinators).includes(curr[0].charAt(0));
556
810
  }
557
811
  // @ts-ignore
558
- if (hasCompound && curr[0] == ' ') {
812
+ if (hasCompound && curr[0] == " ") {
559
813
  hasCompound = false;
560
- curr.unshift('&');
814
+ curr.unshift("&");
561
815
  }
562
816
  if (curr.length == 0) {
563
- curr.push('&');
817
+ curr.push("&");
564
818
  hasCompound = false;
565
819
  }
566
820
  if (reducible) {
567
821
  const chr = curr[0].charAt(0);
568
822
  // @ts-ignore
569
- reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
823
+ reducible = chr == "." || chr == ":" || isIdentStart(chr.charCodeAt(0));
570
824
  }
571
- acc.push(hasCompound ? ['&'].concat(curr) : curr);
825
+ acc.push(hasCompound ? ["&"].concat(curr) : curr);
572
826
  return acc;
573
827
  }, []),
574
- reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
828
+ reducible: selector.every((selector) => ![">", "+", "~", "&"].includes(selector[0])),
575
829
  };
576
830
  }
577
831
  /**
@@ -582,74 +836,74 @@ function optimizeSelector(selector) {
582
836
  */
583
837
  function splitRule(buffer) {
584
838
  const result = [[]];
585
- let str = '';
839
+ let str = "";
586
840
  for (let i = 0; i < buffer.length; i++) {
587
841
  let chr = buffer.charAt(i);
588
842
  if (isWhiteSpace(chr.charCodeAt(0))) {
589
- if (str !== '') {
843
+ if (str !== "") {
590
844
  // @ts-ignore
591
845
  result.at(-1).push(str);
592
- str = '';
846
+ str = "";
593
847
  }
594
848
  // @ts-ignore
595
849
  if (result.at(-1).length > 0) {
596
850
  // @ts-ignore
597
- result.at(-1).push(' ');
851
+ result.at(-1).push(" ");
598
852
  }
599
853
  // i = k;
600
854
  continue;
601
855
  }
602
- if (chr == ',') {
603
- if (str !== '') {
856
+ if (chr == ",") {
857
+ if (str !== "") {
604
858
  result.at(-1).push(str);
605
- str = '';
859
+ str = "";
606
860
  }
607
861
  result.push([]);
608
862
  continue;
609
863
  }
610
- if (chr == '.') {
611
- if (str !== '') {
864
+ if (chr == ".") {
865
+ if (str !== "") {
612
866
  result.at(-1).push(str);
613
- str = '';
867
+ str = "";
614
868
  }
615
869
  str += chr;
616
870
  continue;
617
871
  }
618
872
  if (combinators.includes(chr)) {
619
- if (str !== '') {
873
+ if (str !== "") {
620
874
  result.at(-1).push(str);
621
- str = '';
875
+ str = "";
622
876
  }
623
- if (chr == '|' && buffer.charAt(i + 1) == '|') {
877
+ if (chr == "|" && buffer.charAt(i + 1) == "|") {
624
878
  chr += buffer.charAt(++i);
625
879
  }
626
880
  result.at(-1).push(chr);
627
881
  continue;
628
882
  }
629
- if (chr == ':') {
630
- if (str !== '') {
883
+ if (chr == ":") {
884
+ if (str !== "") {
631
885
  result.at(-1).push(str);
632
- str = '';
886
+ str = "";
633
887
  }
634
- if (buffer.charAt(i + 1) == ':') {
888
+ if (buffer.charAt(i + 1) == ":") {
635
889
  chr += buffer.charAt(++i);
636
890
  }
637
891
  str += chr;
638
892
  continue;
639
893
  }
640
894
  str += chr;
641
- if (chr == '\\') {
895
+ if (chr == "\\") {
642
896
  str += buffer.charAt(++i);
643
897
  continue;
644
898
  }
645
- if (chr == '(' || chr == '[') {
899
+ if (chr == "(" || chr == "[") {
646
900
  const open = chr;
647
- const close = chr == '(' ? ')' : ']';
901
+ const close = chr == "(" ? ")" : "]";
648
902
  let inParens = 1;
649
903
  let k = i;
650
904
  while (++k < buffer.length) {
651
905
  chr = buffer.charAt(k);
652
- if (chr == '\\') {
906
+ if (chr == "\\") {
653
907
  str += buffer.slice(k, k + 2);
654
908
  k++;
655
909
  continue;
@@ -668,7 +922,7 @@ function splitRule(buffer) {
668
922
  i = k;
669
923
  }
670
924
  }
671
- if (str !== '') {
925
+ if (str !== "") {
672
926
  result.at(-1).push(str);
673
927
  }
674
928
  return result;
@@ -685,26 +939,26 @@ function reduceSelector(acc, curr) {
685
939
  // @ts-ignore
686
940
  curr = curr.slice(this.match[0].length);
687
941
  while (curr.length > 0) {
688
- if (curr[0] == ' ') {
942
+ if (curr[0] == " ") {
689
943
  hasCompoundSelector = false;
690
- curr.unshift('&');
944
+ curr.unshift("&");
691
945
  continue;
692
946
  }
693
947
  break;
694
948
  }
695
949
  if (hasCompoundSelector && curr.length > 0) {
696
- hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
950
+ hasCompoundSelector = !["&"].concat(combinators).includes(curr[0].charAt(0));
697
951
  }
698
- if (curr[0] == ':is(') {
952
+ if (curr[0] == ":is(") {
699
953
  let canReduce = true;
700
954
  const isCompound = curr.reduce((acc, token, index) => {
701
955
  if (index == 0) {
702
- canReduce = curr[1] == '&';
956
+ canReduce = curr[1] == "&";
703
957
  }
704
- else if (token == ')') ;
705
- else if (token == ',') {
958
+ else if (token == ")") ;
959
+ else if (token == ",") {
706
960
  if (!canReduce) {
707
- canReduce = curr[index + 1] == '&';
961
+ canReduce = curr[index + 1] == "&";
708
962
  }
709
963
  acc.push([]);
710
964
  }
@@ -715,15 +969,20 @@ function reduceSelector(acc, curr) {
715
969
  if (canReduce) {
716
970
  curr = isCompound.reduce((acc, curr) => {
717
971
  if (acc.length > 0) {
718
- acc.push(',');
972
+ acc.push(",");
719
973
  }
720
974
  acc.push(...curr);
721
975
  return acc;
722
976
  }, []);
723
977
  }
724
978
  }
979
+ acc.push(
725
980
  // @ts-ignore
726
- acc.push(this.match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
981
+ this.match.length == 0
982
+ ? ["&"]
983
+ : hasCompoundSelector && curr[0] != "&" && (curr.length == 0 || !combinators.includes(curr[0].charAt(0)))
984
+ ? ["&"].concat(curr)
985
+ : curr);
727
986
  return acc;
728
987
  }
729
988
  /**
@@ -743,6 +1002,35 @@ function matchSelectors(selector1, selector2) {
743
1002
  let matching = true;
744
1003
  let matchFunction = 0;
745
1004
  let inAttr = 0;
1005
+ const regEx = /^:is\(([:.][^\s,]+)\)$/;
1006
+ for (const _1 of selector1) {
1007
+ if (_1[0] !== "&") {
1008
+ continue;
1009
+ }
1010
+ for (let i = 1; i < _1.length; i++) {
1011
+ const token = _1[i];
1012
+ if (token.startsWith(":is(")) {
1013
+ const match = regEx.exec(token);
1014
+ if (match != null) {
1015
+ _1[i] = match[1];
1016
+ }
1017
+ }
1018
+ }
1019
+ }
1020
+ for (const _1 of selector2) {
1021
+ if (_1[0] !== "&") {
1022
+ continue;
1023
+ }
1024
+ for (let i = 1; i < _1.length; i++) {
1025
+ const token = _1[i];
1026
+ if (token.startsWith(":is(")) {
1027
+ const match = regEx.exec(token);
1028
+ if (match != null) {
1029
+ _1[i] = match[1];
1030
+ }
1031
+ }
1032
+ }
1033
+ }
746
1034
  for (; i < j; i++) {
747
1035
  k = 0;
748
1036
  token = selector1[0][i];
@@ -764,7 +1052,7 @@ function matchSelectors(selector1, selector2) {
764
1052
  if (!matching) {
765
1053
  break;
766
1054
  }
767
- if (token.endsWith('(')) {
1055
+ if (token.endsWith("(")) {
768
1056
  matchFunction++;
769
1057
  }
770
1058
  match.at(-1).push(token);
@@ -776,17 +1064,17 @@ function matchSelectors(selector1, selector2) {
776
1064
  for (const part of match) {
777
1065
  while (part.length > 0) {
778
1066
  const token = part.at(-1);
779
- if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
1067
+ if (token == " " || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
780
1068
  part.pop();
781
1069
  continue;
782
1070
  }
783
1071
  break;
784
1072
  }
785
1073
  }
786
- if (match.every(t => t.length == 0)) {
1074
+ if (match.every((t) => t.length == 0)) {
787
1075
  return null;
788
1076
  }
789
- if (eq([['&']], match)) {
1077
+ if (eq([["&"]], match)) {
790
1078
  return null;
791
1079
  }
792
1080
  const reducer = reduceSelector.bind({ match });
@@ -794,12 +1082,14 @@ function matchSelectors(selector1, selector2) {
794
1082
  selector1 = selector1.reduce(reducer, []);
795
1083
  // @ts-ignore
796
1084
  selector2 = selector2.reduce(reducer, []);
797
- return selector1 == null || selector2 == null ? null : {
798
- eq: eq(selector1, selector2),
799
- match,
800
- selector1,
801
- selector2
802
- };
1085
+ return selector1 == null || selector2 == null
1086
+ ? null
1087
+ : {
1088
+ eq: eq(selector1, selector2),
1089
+ match,
1090
+ selector1,
1091
+ selector2,
1092
+ };
803
1093
  }
804
1094
  /**
805
1095
  * fix selector
@@ -808,19 +1098,20 @@ function matchSelectors(selector1, selector2) {
808
1098
  * @private
809
1099
  */
810
1100
  function fixSelector(node) {
811
- if (node.sel.includes('&')) {
812
- const attributes = parseString(node.sel);
1101
+ if (node.sel.includes("&")) {
1102
+ const attributes = [...tokenize(node.sel)].map((t) => t.token); // parseString(node.sel);
813
1103
  for (const attr of walkValues(attributes)) {
814
- if (attr.value.typ == EnumToken.PseudoClassFuncTokenType && attr.value.val == ':is') {
1104
+ if (attr.value.typ == EnumToken.PseudoClassFuncTokenType &&
1105
+ attr.value.val == ":is") {
815
1106
  let i = attr.value.chi.length;
816
1107
  while (i--) {
817
- if (attr.value.chi[i].typ == EnumToken.LiteralTokenType && attr.value.chi[i].val == '&') {
1108
+ if (attr.value.chi[i].typ == EnumToken.NestingSelectorTokenType) {
818
1109
  attr.value.chi.splice(i, 1);
819
1110
  }
820
1111
  }
821
1112
  }
822
1113
  }
823
- node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), '');
1114
+ node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), "");
824
1115
  }
825
1116
  }
826
1117
  /**
@@ -837,18 +1128,18 @@ function fixSelector(node) {
837
1128
  */
838
1129
  function wrapNodes(previous, node, match, ast, reducer, i, nodeIndex) {
839
1130
  // @ts-ignore
840
- let pSel = match.selector1.reduce(reducer, []).join(',');
1131
+ let pSel = match.selector1.reduce(reducer, []).join(",");
841
1132
  // @ts-ignore
842
- let nSel = match.selector2.reduce(reducer, []).join(',');
1133
+ let nSel = match.selector2.reduce(reducer, []).join(",");
843
1134
  // @ts-ignore
844
- const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
845
- Object.defineProperty(wrapper, 'raw', {
1135
+ const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(",") };
1136
+ Object.defineProperty(wrapper, "raw", {
846
1137
  ...definedPropertySettings,
847
- value: match.match.map(t => t.slice())
1138
+ value: match.match.map((t) => t.slice()),
848
1139
  });
849
- if (pSel == '&' || pSel === '') {
1140
+ if (pSel == "&" || pSel === "") {
850
1141
  wrapper.chi.push(...previous.chi);
851
- if ((nSel == '&' || nSel === '')) {
1142
+ if (nSel == "&" || nSel === "") {
852
1143
  wrapper.chi.push(...node.chi);
853
1144
  }
854
1145
  else {
@@ -877,7 +1168,7 @@ function wrapNodes(previous, node, match, ast, reducer, i, nodeIndex) {
877
1168
  * @private
878
1169
  */
879
1170
  function diff(n1, n2, reducer, options = {}) {
880
- if (!('cache' in options)) {
1171
+ if (!("cache" in options)) {
881
1172
  options.cache = new WeakMap();
882
1173
  }
883
1174
  let node1 = n1;
@@ -894,11 +1185,11 @@ function diff(n1, n2, reducer, options = {}) {
894
1185
  const raw1 = node1.raw;
895
1186
  const raw2 = node2.raw;
896
1187
  if (raw1 != null && raw2 != null) {
897
- const prefixes1 = new Set;
898
- const prefixes2 = new Set;
1188
+ const prefixes1 = new Set();
1189
+ const prefixes2 = new Set();
899
1190
  for (const token1 of raw1) {
900
1191
  for (const t of token1) {
901
- if (t[0] == ':') {
1192
+ if (t.includes(":")) {
902
1193
  const matches = t.match(/::?-([a-z]+)-/);
903
1194
  if (matches == null) {
904
1195
  continue;
@@ -915,7 +1206,7 @@ function diff(n1, n2, reducer, options = {}) {
915
1206
  }
916
1207
  for (const token2 of raw2) {
917
1208
  for (const t of token2) {
918
- if (t[0] == ':') {
1209
+ if (t.includes(":")) {
919
1210
  const matches = t.match(/::?-([a-z]+)-/);
920
1211
  if (matches == null) {
921
1212
  continue;
@@ -950,10 +1241,10 @@ function diff(n1, n2, reducer, options = {}) {
950
1241
  options.cache.set(node2, css2);
951
1242
  }
952
1243
  if (raw1 != null) {
953
- Object.defineProperty(node1, 'raw', { ...definedPropertySettings, value: raw1 });
1244
+ Object.defineProperty(node1, "raw", { ...definedPropertySettings, value: raw1 });
954
1245
  }
955
1246
  if (raw2 != null) {
956
- Object.defineProperty(node2, 'raw', { ...definedPropertySettings, value: raw2 });
1247
+ Object.defineProperty(node2, "raw", { ...definedPropertySettings, value: raw2 });
957
1248
  }
958
1249
  const intersect = [];
959
1250
  while (i--) {
@@ -977,24 +1268,57 @@ function diff(n1, n2, reducer, options = {}) {
977
1268
  }
978
1269
  }
979
1270
  }
980
- const result = (intersect.length == 0 ? null : {
981
- ...node1,
982
- // @ts-ignore
983
- sel: [...new Set([...(n1?.raw?.reduce(reducer, []) ?? splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) ?? splitRule(n2.sel))])].join(','),
984
- chi: intersect.reverse()
985
- });
986
- if (result == null || [n1, n2].reduce((acc, curr) => {
987
- let css = options.cache.get(curr);
988
- if (css == null) {
989
- css = doRender(curr, options).code;
990
- options.cache.set(curr, css);
1271
+ const result = intersect.length === 0 && (node1.chi.length > 0 || node2.chi.length > 0)
1272
+ ? null
1273
+ : {
1274
+ ...node1,
1275
+ // @ts-ignore
1276
+ sel: [
1277
+ ...new Set(splitRule(node1.sel)
1278
+ .concat(splitRule(node2.sel))
1279
+ .map((s) => s.join(""))),
1280
+ ].join(","),
1281
+ // @ts-ignore
1282
+ chi: intersect.reverse(),
1283
+ };
1284
+ if (result == null ||
1285
+ [n1, n2].reduce((acc, curr) => {
1286
+ let css = options.cache.get(curr);
1287
+ if (css == null) {
1288
+ css = doRender(curr, options).code;
1289
+ options.cache.set(curr, css);
1290
+ }
1291
+ return curr.chi.length == 0 ? acc : acc + css.length;
1292
+ }, 0) <=
1293
+ [node1, node2, result].reduce((acc, curr) => {
1294
+ const css = doRender(curr, options).code;
1295
+ return curr.chi.length == 0 ? acc : acc + css.length;
1296
+ }, 0)) {
1297
+ if (node1.chi.length != 0 && node2.chi.length != 0) {
1298
+ return null;
1299
+ }
1300
+ }
1301
+ if (result != null) {
1302
+ const optimized = optimizeSelector(splitRule(result.sel));
1303
+ if (optimized?.match) {
1304
+ const rule = optimized.selector.reduce((acc, curr) => {
1305
+ if (acc.length > 0) {
1306
+ acc += ",";
1307
+ }
1308
+ if (curr.length > 2 && curr[0] === "&" && curr[1] === " ") {
1309
+ return acc + curr.slice(2).join("");
1310
+ }
1311
+ else if (curr.length > 1 && curr[0] === "&") {
1312
+ return acc + curr.slice(1).join("");
1313
+ }
1314
+ return acc + curr.join("");
1315
+ }, "");
1316
+ const match = optimized.optimized.join("");
1317
+ const sel = match + ":is(" + replaceCompound(rule, match) + ")";
1318
+ if (sel.length < result.sel.length) {
1319
+ result.sel = sel;
1320
+ }
991
1321
  }
992
- return curr.chi.length == 0 ? acc : acc + css.length;
993
- }, 0) <= [node1, node2, result].reduce((acc, curr) => {
994
- const css = doRender(curr, options).code;
995
- return curr.chi.length == 0 ? acc : acc + css.length;
996
- }, 0)) {
997
- return null;
998
1322
  }
999
1323
  return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
1000
1324
  }
@@ -1006,44 +1330,44 @@ function diff(n1, n2, reducer, options = {}) {
1006
1330
  */
1007
1331
  function reduceRuleSelector(node) {
1008
1332
  if (node.raw == null) {
1009
- Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: splitRule(node.sel) });
1333
+ Object.defineProperty(node, "raw", { ...definedPropertySettings, value: splitRule(node.sel) });
1010
1334
  }
1011
1335
  let optimized = optimizeSelector(node.raw.reduce((acc, curr) => {
1012
1336
  acc.push(curr.slice());
1013
1337
  return acc;
1014
1338
  }, []));
1015
1339
  if (optimized != null) {
1016
- Object.defineProperty(node, 'optimized', { ...definedPropertySettings, value: optimized });
1340
+ Object.defineProperty(node, "optimized", { ...definedPropertySettings, value: optimized });
1017
1341
  }
1018
1342
  if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
1019
1343
  for (const selector of optimized.selector) {
1020
- if (selector.length > 1 && selector[0] == '&' &&
1344
+ if (selector.length > 1 &&
1345
+ selector[0] == "&" &&
1021
1346
  (combinators.includes(selector[1]) || !/^[a-zA-Z:]/.test(selector[1]))) {
1022
1347
  selector.shift();
1023
1348
  }
1024
1349
  }
1025
- const unique = new Set;
1026
- const raw = [
1027
- [
1028
- optimized.optimized[0], ':is('
1029
- ].concat(optimized.selector.reduce((acc, curr) => {
1030
- const sig = curr.join('');
1031
- if (!unique.has(sig)) {
1032
- if (acc.length > 0) {
1033
- acc.push(',');
1034
- }
1035
- unique.add(sig);
1036
- acc.push(...curr);
1350
+ const unique = new Set();
1351
+ const reduced = optimized.selector.reduce((acc, curr) => {
1352
+ const sig = curr.join("");
1353
+ if (!unique.has(sig)) {
1354
+ if (acc.length > 0) {
1355
+ acc.push(",");
1037
1356
  }
1038
- return acc;
1039
- }, [])).concat(')')
1357
+ unique.add(sig);
1358
+ acc.push(...curr);
1359
+ }
1360
+ return acc;
1361
+ }, []);
1362
+ const raw = [
1363
+ [optimized.optimized[0], reduced.length === 1 ? reduced.join("") : ":is("].concat(reduced).concat(")"),
1040
1364
  ];
1041
- const sel = raw[0].join('');
1365
+ const sel = raw[0].join("");
1042
1366
  if (sel.length < node.sel.length) {
1043
1367
  node.sel = sel;
1044
- Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: raw });
1368
+ Object.defineProperty(node, "raw", { ...definedPropertySettings, value: raw });
1045
1369
  }
1046
1370
  }
1047
1371
  }
1048
1372
 
1049
- export { combinators, definedPropertySettings, minify, splitRule };
1373
+ export { minify, splitRule };