@tbela99/css-parser 1.4.1 → 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 +168 -4
  7. package/README.md +82 -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 +24393 -18479
  12. package/dist/index.cjs +27430 -21519
  13. package/dist/index.d.ts +1403 -933
  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 +543 -215
  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 +53 -47
  180. package/dist/web.d.ts +169 -0
  181. package/dist/web.js +50 -41
  182. package/package.json +18 -13
  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,18 +1,24 @@
1
- import { replaceToken, parseString } 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);
15
+ const notEndingWith = ["(", "["].concat(combinators);
16
+ const rules = [
17
+ EnumToken.AtRuleNodeType,
18
+ EnumToken.RuleNodeType,
19
+ EnumToken.AtRuleTokenType,
20
+ EnumToken.KeyFramesRuleNodeType,
21
+ ];
16
22
  // @ts-ignore
17
23
  const features = Object.values(index).sort((a, b) => a.ordering - b.ordering);
18
24
  /**
@@ -30,14 +36,15 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
30
36
  let postprocess = false;
31
37
  let parents;
32
38
  let replacement;
33
- if (!('features' in options)) {
39
+ if (!("features" in options)) {
34
40
  // @ts-ignore
35
41
  options = {
36
42
  removeDuplicateDeclarations: true,
37
43
  computeShorthand: true,
38
44
  computeCalcExpression: true,
39
45
  removePrefix: false,
40
- features: [], ...options
46
+ features: [],
47
+ ...options,
41
48
  };
42
49
  for (const feature of features) {
43
50
  feature.register(options);
@@ -55,15 +62,24 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
55
62
  if (preprocess) {
56
63
  parents = new Set([ast]);
57
64
  for (const parent of parents) {
58
- if (parent.typ == EnumToken.CommentTokenType ||
59
- parent.typ == EnumToken.CDOCOMMTokenType) {
65
+ if (parent.typ == EnumToken.CommentTokenType || parent.typ == EnumToken.CDOCOMMTokenType) {
60
66
  continue;
61
67
  }
62
68
  replacement = parent;
63
69
  for (const feature of options.features) {
64
- 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))) {
65
72
  continue;
66
73
  }
74
+ if (rules.includes(replacement.typ) && !Array.isArray(replacement.tokens)) {
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
+ });
82
+ }
67
83
  const result = feature.run(replacement, options, parent.parent ?? ast, context, FeatureWalkMode.Pre);
68
84
  if (result != null) {
69
85
  replacement = result;
@@ -73,18 +89,18 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
73
89
  // @ts-ignore
74
90
  replaceToken(parent.parent, parent, replacement);
75
91
  }
76
- if (('chi' in replacement)) {
92
+ if ("chi" in replacement) {
77
93
  // @ts-ignore
78
94
  for (const node of replacement.chi) {
79
- parents.add(Object.defineProperty(node, 'parent', {
95
+ parents.add(Object.defineProperty(node, "parent", {
80
96
  ...definedPropertySettings,
81
- value: replacement
97
+ value: replacement,
82
98
  }));
83
99
  }
84
100
  }
85
101
  }
86
102
  for (const feature of options.features) {
87
- if ((feature.processMode & FeatureWalkMode.Pre) && 'cleanup' in feature) {
103
+ if (feature.processMode & FeatureWalkMode.Pre && "cleanup" in feature) {
88
104
  // @ts-ignore
89
105
  feature.cleanup(ast, options, context, FeatureWalkMode.Pre);
90
106
  }
@@ -93,14 +109,14 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
93
109
  doMinify(ast, options, recursive, errors, nestingContent, context);
94
110
  parents = new Set([ast]);
95
111
  for (const parent of parents) {
96
- if (parent.typ == EnumToken.CommentTokenType ||
97
- parent.typ == EnumToken.CDOCOMMTokenType) {
112
+ if (parent.typ == EnumToken.CommentTokenType || parent.typ == EnumToken.CDOCOMMTokenType) {
98
113
  continue;
99
114
  }
100
115
  replacement = parent;
101
116
  if (postprocess) {
102
117
  for (const feature of options.features) {
103
- 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))) {
104
120
  continue;
105
121
  }
106
122
  const result = feature.run(replacement, options, parent.parent ?? ast, context, FeatureWalkMode.Post);
@@ -113,18 +129,18 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
113
129
  // @ts-ignore
114
130
  replaceToken(parent.parent, parent, replacement);
115
131
  }
116
- if (('chi' in replacement)) {
132
+ if ("chi" in replacement) {
117
133
  for (const node of replacement.chi) {
118
- parents.add(Object.defineProperty(node, 'parent', {
134
+ parents.add(Object.defineProperty(node, "parent", {
119
135
  ...definedPropertySettings,
120
- value: replacement
136
+ value: replacement,
121
137
  }));
122
138
  }
123
139
  }
124
140
  }
125
141
  if (postprocess) {
126
142
  for (const feature of options.features) {
127
- if (feature.processMode & FeatureWalkMode.Post && 'cleanup' in feature) {
143
+ if (feature.processMode & FeatureWalkMode.Post && "cleanup" in feature) {
128
144
  // @ts-ignore
129
145
  feature.cleanup(ast, options, context, FeatureWalkMode.Post);
130
146
  }
@@ -132,6 +148,141 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
132
148
  }
133
149
  return ast;
134
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
+ }
135
286
  /**
136
287
  * reduce selectors
137
288
  * @param acc
@@ -141,16 +292,12 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent, co
141
292
  */
142
293
  function reduce(acc, curr) {
143
294
  // trim :is()
144
- // if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
145
- //
146
- // curr = curr.slice(1, -1);
147
- // }
148
- if (curr[0] == '&') {
149
- if (curr[1] == ' ' && !isIdent(curr[2]) && !isFunction(curr[2])) {
295
+ if (curr[0] == "&") {
296
+ if (curr[1] == " " && !isIdent(curr[2]) && !isFunction(curr[2])) {
150
297
  curr.splice(0, 2);
151
298
  }
152
299
  }
153
- acc.push(curr.join(''));
300
+ acc.push(curr.join(""));
154
301
  return acc;
155
302
  }
156
303
  /**
@@ -165,15 +312,15 @@ function reduce(acc, curr) {
165
312
  * @private
166
313
  */
167
314
  function doMinify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
168
- if (!('nodes' in context)) {
169
- context.nodes = new Set;
315
+ if (!("nodes" in context)) {
316
+ context.nodes = new Set();
170
317
  }
171
318
  if (context.nodes.has(ast)) {
172
319
  return ast;
173
320
  }
174
321
  context.nodes.add(ast);
175
322
  // @ts-ignore
176
- if ('chi' in ast && ast.chi.length > 0) {
323
+ if ("chi" in ast && ast.chi.length > 0) {
177
324
  const reducer = reduce.bind(ast);
178
325
  if (!nestingContent) {
179
326
  nestingContent = options.nestingRules && ast.typ == EnumToken.RuleNodeType;
@@ -183,28 +330,40 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
183
330
  let node = null;
184
331
  let nodeIndex = -1;
185
332
  for (; i < ast.chi.length; i++) {
186
- 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];
187
342
  continue;
188
343
  }
189
344
  node = ast.chi[i];
190
- if (node.typ == EnumToken.AtRuleNodeType && node.nam == 'font-face') {
345
+ if (node.typ === EnumToken.AtRuleNodeType && node.nam === "font-face") {
191
346
  continue;
192
347
  }
193
- if (node.typ == EnumToken.KeyframesAtRuleNodeType) {
194
- if (previous?.typ == EnumToken.KeyframesAtRuleNodeType &&
195
- node.nam == previous.nam &&
196
- 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) {
197
352
  ast.chi?.splice(nodeIndex--, 1);
198
353
  previous = ast?.chi?.[nodeIndex] ?? null;
199
354
  i = nodeIndex;
200
355
  continue;
201
356
  }
202
357
  }
203
- else if (node.typ == EnumToken.KeyFramesRuleNodeType) {
204
- if (previous?.typ == EnumToken.KeyFramesRuleNodeType &&
205
- 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
206
363
  previous.chi.push(...node.chi);
207
- ast.chi.splice(i--, 1);
364
+ ast.chi.splice(i, 1);
365
+ previous = ast?.chi?.[nodeIndex] ?? null;
366
+ i = nodeIndex;
208
367
  continue;
209
368
  }
210
369
  let k;
@@ -212,7 +371,8 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
212
371
  if (node.chi[k].typ == EnumToken.DeclarationNodeType) {
213
372
  let l = node.chi[k].val.length;
214
373
  while (l--) {
215
- if (node.chi[k].val[l].typ == EnumToken.ImportantTokenType) {
374
+ if (node.chi[k].val[l].typ ==
375
+ EnumToken.ImportantTokenType) {
216
376
  node.chi.splice(k--, 1);
217
377
  break;
218
378
  }
@@ -225,16 +385,57 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
225
385
  }
226
386
  }
227
387
  else if (node.typ == EnumToken.AtRuleNodeType) {
228
- if (node.nam == 'media' && ['all', '', null].includes(node.val)) {
229
- ast.chi?.splice(i, 1, ...node.chi);
230
- i--;
231
- 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
+ }
232
433
  }
233
434
  if (previous?.typ == EnumToken.AtRuleNodeType &&
234
- node.nam != 'font-face' &&
235
- previous.nam == node.nam &&
236
- previous.val == node.val) {
237
- if ('chi' in node) {
435
+ node.nam != "font-face" &&
436
+ previous.nam === node.nam &&
437
+ previous.val === node.val) {
438
+ if ("chi" in node) {
238
439
  // @ts-ignore
239
440
  previous.chi.push(...node.chi);
240
441
  if (!hasDeclaration(previous)) {
@@ -253,7 +454,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
253
454
  continue;
254
455
  }
255
456
  // @ts-ignore
256
- else if (node.typ == EnumToken.RuleNodeType) {
457
+ else if (node.typ === EnumToken.RuleNodeType) {
257
458
  reduceRuleSelector(node);
258
459
  let wrapper = null;
259
460
  let match;
@@ -261,7 +462,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
261
462
  if (previous?.typ == EnumToken.RuleNodeType) {
262
463
  reduceRuleSelector(previous);
263
464
  // @ts-ignore
264
- match = matchSelectors(previous.raw, node.raw, ast.typ);
465
+ match = matchSelectors(previous.raw, node.raw);
265
466
  if (match != null) {
266
467
  wrapper = wrapNodes(previous, node, match, ast, reducer, i, nodeIndex);
267
468
  nodeIndex = i - 1;
@@ -295,13 +496,13 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
295
496
  // @ts-ignore
296
497
  wrapper = { ...node, chi: [], sel: node.optimized.optimized[0] };
297
498
  // @ts-ignore
298
- Object.defineProperty(wrapper, 'raw', {
499
+ Object.defineProperty(wrapper, "raw", {
299
500
  ...definedPropertySettings,
300
501
  // @ts-ignore
301
- value: [[node.optimized.optimized[0]]]
502
+ value: [[node.optimized.optimized[0]]],
302
503
  });
303
504
  // @ts-ignore
304
- node.sel = node.optimized.selector.reduce(reducer, []).join(',');
505
+ node.sel = node.optimized.selector.reduce(reducer, []).join(",");
305
506
  // @ts-ignore
306
507
  node.raw = node.optimized.selector.slice();
307
508
  // @ts-ignore
@@ -310,14 +511,30 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
310
511
  ast.chi.splice(i, 1, wrapper);
311
512
  node = wrapper;
312
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
+ }
313
530
  }
314
531
  // @ts-ignore
315
532
  else if (node.optimized?.match) {
316
533
  let wrap = true;
317
534
  // @ts-ignore
318
535
  const selector = node.optimized.selector.reduce((acc, curr) => {
319
- if (curr[0] == '&' && curr.length > 1) {
320
- if (curr[1] == ' ') {
536
+ if (curr[0] == "&" && curr.length > 1) {
537
+ if (curr[1] == " ") {
321
538
  curr.splice(0, 2);
322
539
  }
323
540
  else {
@@ -325,14 +542,14 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
325
542
  }
326
543
  }
327
544
  else if (combinators.includes(curr[0])) {
328
- curr.unshift('&');
545
+ curr.unshift("&");
329
546
  wrap = false;
330
547
  }
331
548
  acc.push(curr);
332
549
  return acc;
333
550
  }, []);
334
551
  if (!wrap) {
335
- wrap = selector.some((s) => s[0] != '&');
552
+ wrap = selector.some((s) => s[0] != "&");
336
553
  }
337
554
  let rule = null;
338
555
  const optimized = node.optimized.optimized.slice();
@@ -341,50 +558,82 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
341
558
  if (!combinators.includes(check)) {
342
559
  let last = optimized.pop();
343
560
  wrap = false;
344
- rule = optimized.join('') + `:is(${selector.map(s => {
345
- if (s[0] == '&') {
346
- s.splice(0, 1, last);
347
- }
348
- else {
349
- s.unshift(last);
350
- }
351
- return s.join('');
352
- }).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(",")})`;
353
574
  }
354
575
  }
355
576
  if (rule == null) {
356
- rule = selector.map((s) => {
357
- if (s[0] == '&') {
577
+ rule = selector
578
+ .map((s) => {
579
+ if (s[0] == "&") {
358
580
  s.splice(0, 1, ...node.optimized.optimized);
359
581
  }
360
- return s.join('');
361
- }).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;
589
+ }
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(""), "");
362
605
  }
363
- let sel = wrap ? node.optimized.optimized.join('') + `:is(${rule})` : rule;
606
+ }
607
+ else if (node.optimized?.optimized.length > 0) {
608
+ const sel = node.optimized.optimized.join("");
364
609
  if (sel.length < node.sel.length) {
365
610
  node.sel = sel;
611
+ node.raw = [node.optimized.optimized.slice()];
366
612
  }
367
613
  }
368
614
  doMinify(node, options, recursive, errors, nestingContent, context);
369
615
  }
370
616
  if (previous != null) {
371
- if ('chi' in previous && ('chi' in node)) {
372
- if (previous.typ == node.typ) {
617
+ if ("chi" in previous && "chi" in node) {
618
+ if (previous.typ === node.typ) {
373
619
  let shouldMerge = true;
374
620
  let k = previous.chi.length;
375
621
  while (k-- > 0) {
376
- 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) {
377
625
  continue;
378
626
  }
379
- shouldMerge = previous.chi[k].typ == EnumToken.DeclarationNodeType;
627
+ shouldMerge = previous.chi[k].typ === EnumToken.DeclarationNodeType;
380
628
  break;
381
629
  }
382
630
  if (shouldMerge) {
383
- // @ts-ignore
384
- if (((node.typ == EnumToken.RuleNodeType || node.typ == EnumToken.KeyFramesRuleNodeType) && node.sel == previous.sel) ||
385
- // @ts-ignore
386
- (node.typ == EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
387
- // @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)) {
388
637
  node.chi.unshift(...previous.chi);
389
638
  doMinify(node, options, recursive, errors, nestingContent, context);
390
639
  ast.chi.splice(nodeIndex, 1);
@@ -392,7 +641,8 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
392
641
  nodeIndex = i;
393
642
  continue;
394
643
  }
395
- 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)) {
396
646
  const intersect = diff(previous, node, reducer, options);
397
647
  if (intersect != null) {
398
648
  if (intersect.node1.chi.length == 0) {
@@ -412,7 +662,6 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
412
662
  ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
413
663
  i = (nodeIndex ?? 0) + 1;
414
664
  }
415
- reduceRuleSelector(intersect.result);
416
665
  if (node != ast.chi[i]) {
417
666
  node = ast.chi[i];
418
667
  }
@@ -432,15 +681,16 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
432
681
  if (!nestingContent &&
433
682
  previous != null &&
434
683
  previous.typ == EnumToken.RuleNodeType &&
435
- previous.sel.includes('&')) {
684
+ previous.sel.includes("&")) {
436
685
  fixSelector(previous);
437
686
  }
438
687
  previous = node;
439
688
  nodeIndex = i;
440
689
  }
441
- if (recursive && node != null && ('chi' in node)) {
442
- if (node.typ == EnumToken.KeyframesAtRuleNodeType || !node.chi.some((n) => n.typ == EnumToken.DeclarationNodeType)) {
443
- 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")) {
444
694
  doMinify(node, options, recursive, errors, nestingContent, context);
445
695
  }
446
696
  }
@@ -448,7 +698,7 @@ function doMinify(ast, options = {}, recursive = false, errors, nestingContent,
448
698
  if (!nestingContent &&
449
699
  node != null &&
450
700
  node.typ == EnumToken.RuleNodeType &&
451
- node.sel.includes('&')) {
701
+ node.sel.includes("&")) {
452
702
  fixSelector(node);
453
703
  }
454
704
  }
@@ -479,13 +729,15 @@ function hasDeclaration(node) {
479
729
  * @private
480
730
  */
481
731
  function optimizeSelector(selector) {
482
- selector = selector.reduce((acc, curr) => {
732
+ const map = new Set();
733
+ selector = selector
734
+ .reduce((acc, curr) => {
483
735
  // @ts-ignore
484
- if (curr.length > 0 && curr.at(-1).startsWith(':is(')) {
736
+ if (curr.length > 0 && curr.at(-1).startsWith(":is(")) {
485
737
  // @ts-ignore
486
- const rules = splitRule(curr.at(-1).slice(4, -1)).map(x => {
487
- if (x[0] == '&' && x.length > 1) {
488
- 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);
489
741
  }
490
742
  return x;
491
743
  });
@@ -497,9 +749,17 @@ function optimizeSelector(selector) {
497
749
  }
498
750
  acc.push(curr);
499
751
  return acc;
500
- }, []);
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
+ });
501
761
  const optimized = [];
502
- 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);
503
763
  let i = 0;
504
764
  let j;
505
765
  let match;
@@ -519,7 +779,7 @@ function optimizeSelector(selector) {
519
779
  }
520
780
  while (optimized.length > 0) {
521
781
  const last = optimized.at(-1);
522
- if ((last == ' ' || combinators.includes(last))) {
782
+ if (last == " " || combinators.includes(last)) {
523
783
  optimized.pop();
524
784
  continue;
525
785
  }
@@ -527,19 +787,17 @@ function optimizeSelector(selector) {
527
787
  }
528
788
  selector.forEach((selector) => selector.splice(0, optimized.length));
529
789
  let reducible = optimized.length == 1;
530
- if (optimized[0] == '&') {
531
- if (optimized[1] == ' ') {
790
+ if (optimized[0] == "&") {
791
+ if (optimized[1] == " ") {
532
792
  optimized.splice(0, 2);
533
793
  }
534
794
  }
535
- if (optimized.length == 0 ||
536
- (optimized[0].charAt(0) == '&' ||
537
- selector.length == 1)) {
795
+ if (optimized.length == 0 || optimized[0].charAt(0) == "&" || selector.length == 1) {
538
796
  return {
539
797
  match: false,
540
798
  optimized,
541
- selector: selector.map((selector) => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : (selector)),
542
- 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])),
543
801
  };
544
802
  }
545
803
  return {
@@ -548,26 +806,26 @@ function optimizeSelector(selector) {
548
806
  selector: selector.reduce((acc, curr) => {
549
807
  let hasCompound = true;
550
808
  if (hasCompound && curr.length > 0) {
551
- hasCompound = !['&'].concat(combinators).includes(curr[0].charAt(0));
809
+ hasCompound = !["&"].concat(combinators).includes(curr[0].charAt(0));
552
810
  }
553
811
  // @ts-ignore
554
- if (hasCompound && curr[0] == ' ') {
812
+ if (hasCompound && curr[0] == " ") {
555
813
  hasCompound = false;
556
- curr.unshift('&');
814
+ curr.unshift("&");
557
815
  }
558
816
  if (curr.length == 0) {
559
- curr.push('&');
817
+ curr.push("&");
560
818
  hasCompound = false;
561
819
  }
562
820
  if (reducible) {
563
821
  const chr = curr[0].charAt(0);
564
822
  // @ts-ignore
565
- reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
823
+ reducible = chr == "." || chr == ":" || isIdentStart(chr.charCodeAt(0));
566
824
  }
567
- acc.push(hasCompound ? ['&'].concat(curr) : curr);
825
+ acc.push(hasCompound ? ["&"].concat(curr) : curr);
568
826
  return acc;
569
827
  }, []),
570
- reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
828
+ reducible: selector.every((selector) => ![">", "+", "~", "&"].includes(selector[0])),
571
829
  };
572
830
  }
573
831
  /**
@@ -578,74 +836,74 @@ function optimizeSelector(selector) {
578
836
  */
579
837
  function splitRule(buffer) {
580
838
  const result = [[]];
581
- let str = '';
839
+ let str = "";
582
840
  for (let i = 0; i < buffer.length; i++) {
583
841
  let chr = buffer.charAt(i);
584
842
  if (isWhiteSpace(chr.charCodeAt(0))) {
585
- if (str !== '') {
843
+ if (str !== "") {
586
844
  // @ts-ignore
587
845
  result.at(-1).push(str);
588
- str = '';
846
+ str = "";
589
847
  }
590
848
  // @ts-ignore
591
849
  if (result.at(-1).length > 0) {
592
850
  // @ts-ignore
593
- result.at(-1).push(' ');
851
+ result.at(-1).push(" ");
594
852
  }
595
853
  // i = k;
596
854
  continue;
597
855
  }
598
- if (chr == ',') {
599
- if (str !== '') {
856
+ if (chr == ",") {
857
+ if (str !== "") {
600
858
  result.at(-1).push(str);
601
- str = '';
859
+ str = "";
602
860
  }
603
861
  result.push([]);
604
862
  continue;
605
863
  }
606
- if (chr == '.') {
607
- if (str !== '') {
864
+ if (chr == ".") {
865
+ if (str !== "") {
608
866
  result.at(-1).push(str);
609
- str = '';
867
+ str = "";
610
868
  }
611
869
  str += chr;
612
870
  continue;
613
871
  }
614
872
  if (combinators.includes(chr)) {
615
- if (str !== '') {
873
+ if (str !== "") {
616
874
  result.at(-1).push(str);
617
- str = '';
875
+ str = "";
618
876
  }
619
- if (chr == '|' && buffer.charAt(i + 1) == '|') {
877
+ if (chr == "|" && buffer.charAt(i + 1) == "|") {
620
878
  chr += buffer.charAt(++i);
621
879
  }
622
880
  result.at(-1).push(chr);
623
881
  continue;
624
882
  }
625
- if (chr == ':') {
626
- if (str !== '') {
883
+ if (chr == ":") {
884
+ if (str !== "") {
627
885
  result.at(-1).push(str);
628
- str = '';
886
+ str = "";
629
887
  }
630
- if (buffer.charAt(i + 1) == ':') {
888
+ if (buffer.charAt(i + 1) == ":") {
631
889
  chr += buffer.charAt(++i);
632
890
  }
633
891
  str += chr;
634
892
  continue;
635
893
  }
636
894
  str += chr;
637
- if (chr == '\\') {
895
+ if (chr == "\\") {
638
896
  str += buffer.charAt(++i);
639
897
  continue;
640
898
  }
641
- if (chr == '(' || chr == '[') {
899
+ if (chr == "(" || chr == "[") {
642
900
  const open = chr;
643
- const close = chr == '(' ? ')' : ']';
901
+ const close = chr == "(" ? ")" : "]";
644
902
  let inParens = 1;
645
903
  let k = i;
646
904
  while (++k < buffer.length) {
647
905
  chr = buffer.charAt(k);
648
- if (chr == '\\') {
906
+ if (chr == "\\") {
649
907
  str += buffer.slice(k, k + 2);
650
908
  k++;
651
909
  continue;
@@ -664,7 +922,7 @@ function splitRule(buffer) {
664
922
  i = k;
665
923
  }
666
924
  }
667
- if (str !== '') {
925
+ if (str !== "") {
668
926
  result.at(-1).push(str);
669
927
  }
670
928
  return result;
@@ -681,26 +939,26 @@ function reduceSelector(acc, curr) {
681
939
  // @ts-ignore
682
940
  curr = curr.slice(this.match[0].length);
683
941
  while (curr.length > 0) {
684
- if (curr[0] == ' ') {
942
+ if (curr[0] == " ") {
685
943
  hasCompoundSelector = false;
686
- curr.unshift('&');
944
+ curr.unshift("&");
687
945
  continue;
688
946
  }
689
947
  break;
690
948
  }
691
949
  if (hasCompoundSelector && curr.length > 0) {
692
- hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
950
+ hasCompoundSelector = !["&"].concat(combinators).includes(curr[0].charAt(0));
693
951
  }
694
- if (curr[0] == ':is(') {
952
+ if (curr[0] == ":is(") {
695
953
  let canReduce = true;
696
954
  const isCompound = curr.reduce((acc, token, index) => {
697
955
  if (index == 0) {
698
- canReduce = curr[1] == '&';
956
+ canReduce = curr[1] == "&";
699
957
  }
700
- else if (token == ')') ;
701
- else if (token == ',') {
958
+ else if (token == ")") ;
959
+ else if (token == ",") {
702
960
  if (!canReduce) {
703
- canReduce = curr[index + 1] == '&';
961
+ canReduce = curr[index + 1] == "&";
704
962
  }
705
963
  acc.push([]);
706
964
  }
@@ -711,15 +969,20 @@ function reduceSelector(acc, curr) {
711
969
  if (canReduce) {
712
970
  curr = isCompound.reduce((acc, curr) => {
713
971
  if (acc.length > 0) {
714
- acc.push(',');
972
+ acc.push(",");
715
973
  }
716
974
  acc.push(...curr);
717
975
  return acc;
718
976
  }, []);
719
977
  }
720
978
  }
979
+ acc.push(
721
980
  // @ts-ignore
722
- 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);
723
986
  return acc;
724
987
  }
725
988
  /**
@@ -739,6 +1002,35 @@ function matchSelectors(selector1, selector2) {
739
1002
  let matching = true;
740
1003
  let matchFunction = 0;
741
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
+ }
742
1034
  for (; i < j; i++) {
743
1035
  k = 0;
744
1036
  token = selector1[0][i];
@@ -760,7 +1052,7 @@ function matchSelectors(selector1, selector2) {
760
1052
  if (!matching) {
761
1053
  break;
762
1054
  }
763
- if (token.endsWith('(')) {
1055
+ if (token.endsWith("(")) {
764
1056
  matchFunction++;
765
1057
  }
766
1058
  match.at(-1).push(token);
@@ -772,17 +1064,17 @@ function matchSelectors(selector1, selector2) {
772
1064
  for (const part of match) {
773
1065
  while (part.length > 0) {
774
1066
  const token = part.at(-1);
775
- if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
1067
+ if (token == " " || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
776
1068
  part.pop();
777
1069
  continue;
778
1070
  }
779
1071
  break;
780
1072
  }
781
1073
  }
782
- if (match.every(t => t.length == 0)) {
1074
+ if (match.every((t) => t.length == 0)) {
783
1075
  return null;
784
1076
  }
785
- if (eq([['&']], match)) {
1077
+ if (eq([["&"]], match)) {
786
1078
  return null;
787
1079
  }
788
1080
  const reducer = reduceSelector.bind({ match });
@@ -790,12 +1082,14 @@ function matchSelectors(selector1, selector2) {
790
1082
  selector1 = selector1.reduce(reducer, []);
791
1083
  // @ts-ignore
792
1084
  selector2 = selector2.reduce(reducer, []);
793
- return selector1 == null || selector2 == null ? null : {
794
- eq: eq(selector1, selector2),
795
- match,
796
- selector1,
797
- selector2
798
- };
1085
+ return selector1 == null || selector2 == null
1086
+ ? null
1087
+ : {
1088
+ eq: eq(selector1, selector2),
1089
+ match,
1090
+ selector1,
1091
+ selector2,
1092
+ };
799
1093
  }
800
1094
  /**
801
1095
  * fix selector
@@ -804,19 +1098,20 @@ function matchSelectors(selector1, selector2) {
804
1098
  * @private
805
1099
  */
806
1100
  function fixSelector(node) {
807
- if (node.sel.includes('&')) {
808
- const attributes = parseString(node.sel);
1101
+ if (node.sel.includes("&")) {
1102
+ const attributes = [...tokenize(node.sel)].map((t) => t.token); // parseString(node.sel);
809
1103
  for (const attr of walkValues(attributes)) {
810
- if (attr.value.typ == EnumToken.PseudoClassFuncTokenType && attr.value.val == ':is') {
1104
+ if (attr.value.typ == EnumToken.PseudoClassFuncTokenType &&
1105
+ attr.value.val == ":is") {
811
1106
  let i = attr.value.chi.length;
812
1107
  while (i--) {
813
- if (attr.value.chi[i].typ == EnumToken.LiteralTokenType && attr.value.chi[i].val == '&') {
1108
+ if (attr.value.chi[i].typ == EnumToken.NestingSelectorTokenType) {
814
1109
  attr.value.chi.splice(i, 1);
815
1110
  }
816
1111
  }
817
1112
  }
818
1113
  }
819
- node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), '');
1114
+ node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), "");
820
1115
  }
821
1116
  }
822
1117
  /**
@@ -833,18 +1128,18 @@ function fixSelector(node) {
833
1128
  */
834
1129
  function wrapNodes(previous, node, match, ast, reducer, i, nodeIndex) {
835
1130
  // @ts-ignore
836
- let pSel = match.selector1.reduce(reducer, []).join(',');
1131
+ let pSel = match.selector1.reduce(reducer, []).join(",");
837
1132
  // @ts-ignore
838
- let nSel = match.selector2.reduce(reducer, []).join(',');
1133
+ let nSel = match.selector2.reduce(reducer, []).join(",");
839
1134
  // @ts-ignore
840
- const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
841
- Object.defineProperty(wrapper, 'raw', {
1135
+ const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(",") };
1136
+ Object.defineProperty(wrapper, "raw", {
842
1137
  ...definedPropertySettings,
843
- value: match.match.map(t => t.slice())
1138
+ value: match.match.map((t) => t.slice()),
844
1139
  });
845
- if (pSel == '&' || pSel === '') {
1140
+ if (pSel == "&" || pSel === "") {
846
1141
  wrapper.chi.push(...previous.chi);
847
- if ((nSel == '&' || nSel === '')) {
1142
+ if (nSel == "&" || nSel === "") {
848
1143
  wrapper.chi.push(...node.chi);
849
1144
  }
850
1145
  else {
@@ -873,7 +1168,7 @@ function wrapNodes(previous, node, match, ast, reducer, i, nodeIndex) {
873
1168
  * @private
874
1169
  */
875
1170
  function diff(n1, n2, reducer, options = {}) {
876
- if (!('cache' in options)) {
1171
+ if (!("cache" in options)) {
877
1172
  options.cache = new WeakMap();
878
1173
  }
879
1174
  let node1 = n1;
@@ -890,11 +1185,11 @@ function diff(n1, n2, reducer, options = {}) {
890
1185
  const raw1 = node1.raw;
891
1186
  const raw2 = node2.raw;
892
1187
  if (raw1 != null && raw2 != null) {
893
- const prefixes1 = new Set;
894
- const prefixes2 = new Set;
1188
+ const prefixes1 = new Set();
1189
+ const prefixes2 = new Set();
895
1190
  for (const token1 of raw1) {
896
1191
  for (const t of token1) {
897
- if (t[0] == ':') {
1192
+ if (t.includes(":")) {
898
1193
  const matches = t.match(/::?-([a-z]+)-/);
899
1194
  if (matches == null) {
900
1195
  continue;
@@ -911,7 +1206,7 @@ function diff(n1, n2, reducer, options = {}) {
911
1206
  }
912
1207
  for (const token2 of raw2) {
913
1208
  for (const t of token2) {
914
- if (t[0] == ':') {
1209
+ if (t.includes(":")) {
915
1210
  const matches = t.match(/::?-([a-z]+)-/);
916
1211
  if (matches == null) {
917
1212
  continue;
@@ -946,10 +1241,10 @@ function diff(n1, n2, reducer, options = {}) {
946
1241
  options.cache.set(node2, css2);
947
1242
  }
948
1243
  if (raw1 != null) {
949
- Object.defineProperty(node1, 'raw', { ...definedPropertySettings, value: raw1 });
1244
+ Object.defineProperty(node1, "raw", { ...definedPropertySettings, value: raw1 });
950
1245
  }
951
1246
  if (raw2 != null) {
952
- Object.defineProperty(node2, 'raw', { ...definedPropertySettings, value: raw2 });
1247
+ Object.defineProperty(node2, "raw", { ...definedPropertySettings, value: raw2 });
953
1248
  }
954
1249
  const intersect = [];
955
1250
  while (i--) {
@@ -973,24 +1268,57 @@ function diff(n1, n2, reducer, options = {}) {
973
1268
  }
974
1269
  }
975
1270
  }
976
- const result = (intersect.length == 0 ? null : {
977
- ...node1,
978
- // @ts-ignore
979
- sel: [...new Set([...(n1?.raw?.reduce(reducer, []) ?? splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) ?? splitRule(n2.sel))])].join(','),
980
- chi: intersect.reverse()
981
- });
982
- if (result == null || [n1, n2].reduce((acc, curr) => {
983
- let css = options.cache.get(curr);
984
- if (css == null) {
985
- css = doRender(curr, options).code;
986
- 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
+ }
987
1321
  }
988
- return curr.chi.length == 0 ? acc : acc + css.length;
989
- }, 0) <= [node1, node2, result].reduce((acc, curr) => {
990
- const css = doRender(curr, options).code;
991
- return curr.chi.length == 0 ? acc : acc + css.length;
992
- }, 0)) {
993
- return null;
994
1322
  }
995
1323
  return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
996
1324
  }
@@ -1002,44 +1330,44 @@ function diff(n1, n2, reducer, options = {}) {
1002
1330
  */
1003
1331
  function reduceRuleSelector(node) {
1004
1332
  if (node.raw == null) {
1005
- Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: splitRule(node.sel) });
1333
+ Object.defineProperty(node, "raw", { ...definedPropertySettings, value: splitRule(node.sel) });
1006
1334
  }
1007
1335
  let optimized = optimizeSelector(node.raw.reduce((acc, curr) => {
1008
1336
  acc.push(curr.slice());
1009
1337
  return acc;
1010
1338
  }, []));
1011
1339
  if (optimized != null) {
1012
- Object.defineProperty(node, 'optimized', { ...definedPropertySettings, value: optimized });
1340
+ Object.defineProperty(node, "optimized", { ...definedPropertySettings, value: optimized });
1013
1341
  }
1014
1342
  if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
1015
1343
  for (const selector of optimized.selector) {
1016
- if (selector.length > 1 && selector[0] == '&' &&
1344
+ if (selector.length > 1 &&
1345
+ selector[0] == "&" &&
1017
1346
  (combinators.includes(selector[1]) || !/^[a-zA-Z:]/.test(selector[1]))) {
1018
1347
  selector.shift();
1019
1348
  }
1020
1349
  }
1021
- const unique = new Set;
1022
- const raw = [
1023
- [
1024
- optimized.optimized[0], ':is('
1025
- ].concat(optimized.selector.reduce((acc, curr) => {
1026
- const sig = curr.join('');
1027
- if (!unique.has(sig)) {
1028
- if (acc.length > 0) {
1029
- acc.push(',');
1030
- }
1031
- unique.add(sig);
1032
- 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(",");
1033
1356
  }
1034
- return acc;
1035
- }, [])).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(")"),
1036
1364
  ];
1037
- const sel = raw[0].join('');
1365
+ const sel = raw[0].join("");
1038
1366
  if (sel.length < node.sel.length) {
1039
1367
  node.sel = sel;
1040
- Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: raw });
1368
+ Object.defineProperty(node, "raw", { ...definedPropertySettings, value: raw });
1041
1369
  }
1042
1370
  }
1043
1371
  }
1044
1372
 
1045
- export { combinators, definedPropertySettings, minify, splitRule };
1373
+ export { minify, splitRule };