@projectwallace/css-analyzer 9.5.0 → 9.6.2

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.
@@ -1,2 +1,2 @@
1
- import { n as isSupportsBrowserhack, t as isMediaBrowserhack } from "../atrules-CvzPtm16.js";
1
+ import { n as isSupportsBrowserhack, t as isMediaBrowserhack } from "../atrules-CXLSfmpu.js";
2
2
  export { isMediaBrowserhack, isSupportsBrowserhack };
@@ -1,2 +1,2 @@
1
- import { n as isSupportsBrowserhack, t as isMediaBrowserhack } from "../atrules-CskmpIdJ.js";
1
+ import { n as isSupportsBrowserhack, t as isMediaBrowserhack } from "../atrules-Bnb0wvNR.js";
2
2
  export { isMediaBrowserhack, isSupportsBrowserhack };
@@ -1,13 +1,13 @@
1
- import { BREAK, DIMENSION, IDENTIFIER, MEDIA_FEATURE, MEDIA_TYPE, NUMBER, SUPPORTS_QUERY, str_equals, walk } from "@projectwallace/css-parser";
1
+ import { BREAK, DIMENSION, IDENTIFIER, NUMBER, is_media_feature, is_media_type, is_supports_query, str_equals, walk } from "@projectwallace/css-parser";
2
2
  //#region src/atrules/atrules.ts
3
3
  /**
4
4
  * Check if an @supports atRule is a browserhack (Wallace parser version)
5
- * @param node - The Atrule CSSNode from Wallace parser
5
+ * @param prelude - The Atrule CSSNode from Wallace parser
6
6
  */
7
- function isSupportsBrowserhack(node, on_hack) {
8
- walk(node, function(n) {
9
- if (n.type === SUPPORTS_QUERY) {
10
- const normalizedPrelude = (n.prelude || n.value || "").toString().toLowerCase().replaceAll(/\s+/g, "");
7
+ function isSupportsBrowserhack(prelude, on_hack) {
8
+ walk(prelude, function(node) {
9
+ if (is_supports_query(node)) {
10
+ const normalizedPrelude = node.value.toString().toLowerCase().replaceAll(/\s+/g, "");
11
11
  if (normalizedPrelude.includes("-webkit-appearance:none")) {
12
12
  on_hack("-webkit-appearance: none");
13
13
  return BREAK;
@@ -21,13 +21,13 @@ function isSupportsBrowserhack(node, on_hack) {
21
21
  }
22
22
  /**
23
23
  * Check if a @media atRule is a browserhack (Wallace parser version)
24
- * @param node - The Atrule CSSNode from Wallace parser
24
+ * @param prelude - The Atrule CSSNode from Wallace parser
25
25
  * @returns true if the atrule is a browserhack
26
26
  */
27
- function isMediaBrowserhack(node, on_hack) {
28
- walk(node, function(n) {
29
- if (n.type === MEDIA_TYPE) {
30
- const text = n.text || "";
27
+ function isMediaBrowserhack(prelude, on_hack) {
28
+ walk(prelude, function(node) {
29
+ if (is_media_type(node)) {
30
+ const text = node.value;
31
31
  if (text.startsWith("\\0")) {
32
32
  on_hack("\\0");
33
33
  return BREAK;
@@ -37,8 +37,8 @@ function isMediaBrowserhack(node, on_hack) {
37
37
  return BREAK;
38
38
  }
39
39
  }
40
- if (n.type === MEDIA_FEATURE) {
41
- const name = n.property || "";
40
+ if (is_media_feature(node)) {
41
+ const name = node.property;
42
42
  if (str_equals("-moz-images-in-menus", name)) {
43
43
  on_hack("-moz-images-in-menus");
44
44
  return BREAK;
@@ -51,20 +51,20 @@ function isMediaBrowserhack(node, on_hack) {
51
51
  on_hack("-ms-high-contrast");
52
52
  return BREAK;
53
53
  }
54
- if (str_equals("min-resolution", name) && n.has_children) {
55
- for (const child of n) if (child.type === DIMENSION && child.value === .001 && str_equals("dpcm", child.unit || "")) {
54
+ if (str_equals("min-resolution", name) && node.has_children) {
55
+ for (const child of node) if (child.type === DIMENSION && child.value === .001 && str_equals("dpcm", child.unit || "")) {
56
56
  on_hack("min-resolution: .001dpcm");
57
57
  return BREAK;
58
58
  }
59
59
  }
60
- if (str_equals("-webkit-min-device-pixel-ratio", name) && n.has_children) {
61
- for (const child of n) if (child.type === NUMBER && (child.value === 0 || child.value === 1e4)) {
60
+ if (str_equals("-webkit-min-device-pixel-ratio", name) && node.has_children) {
61
+ for (const child of node) if (child.type === NUMBER && (child.value === 0 || child.value === 1e4)) {
62
62
  on_hack("-webkit-min-device-pixel-ratio");
63
63
  return BREAK;
64
64
  }
65
65
  }
66
- if (n.has_children) {
67
- for (const child of n) if (child.type === IDENTIFIER && child.text === "\\0") {
66
+ if (node.has_children) {
67
+ for (const child of node) if (child.type === IDENTIFIER && child.text === "\\0") {
68
68
  on_hack("\\0");
69
69
  return BREAK;
70
70
  }
@@ -0,0 +1,16 @@
1
+ import { CSSNode } from "@projectwallace/css-parser";
2
+
3
+ //#region src/atrules/atrules.d.ts
4
+ /**
5
+ * Check if an @supports atRule is a browserhack (Wallace parser version)
6
+ * @param prelude - The Atrule CSSNode from Wallace parser
7
+ */
8
+ declare function isSupportsBrowserhack(prelude: CSSNode, on_hack: (hack: string) => void): void;
9
+ /**
10
+ * Check if a @media atRule is a browserhack (Wallace parser version)
11
+ * @param prelude - The Atrule CSSNode from Wallace parser
12
+ * @returns true if the atrule is a browserhack
13
+ */
14
+ declare function isMediaBrowserhack(prelude: CSSNode, on_hack: (hack: string) => void): void;
15
+ //#endregion
16
+ export { isSupportsBrowserhack as n, isMediaBrowserhack as t };
@@ -0,0 +1,347 @@
1
+ import { t as KeywordSet } from "./keyword-set-qSyAMR9o.js";
2
+ import { t as endsWith } from "./string-utils-C97yyuqE.js";
3
+ import { is_dimension, is_function, is_identifier, is_number, is_operator, is_string } from "@projectwallace/css-parser";
4
+ //#region src/values/colors.ts
5
+ const namedColors = new KeywordSet([
6
+ "white",
7
+ "black",
8
+ "red",
9
+ "gray",
10
+ "silver",
11
+ "grey",
12
+ "green",
13
+ "orange",
14
+ "blue",
15
+ "dimgray",
16
+ "whitesmoke",
17
+ "lightgray",
18
+ "lightgrey",
19
+ "yellow",
20
+ "gold",
21
+ "pink",
22
+ "gainsboro",
23
+ "magenta",
24
+ "purple",
25
+ "darkgray",
26
+ "navy",
27
+ "darkred",
28
+ "teal",
29
+ "maroon",
30
+ "darkgrey",
31
+ "tomato",
32
+ "darkorange",
33
+ "brown",
34
+ "crimson",
35
+ "lightyellow",
36
+ "slategray",
37
+ "salmon",
38
+ "lightgreen",
39
+ "lightblue",
40
+ "orangered",
41
+ "aliceblue",
42
+ "dodgerblue",
43
+ "lime",
44
+ "darkblue",
45
+ "darkgoldenrod",
46
+ "skyblue",
47
+ "royalblue",
48
+ "darkgreen",
49
+ "ivory",
50
+ "olive",
51
+ "aqua",
52
+ "turquoise",
53
+ "cyan",
54
+ "khaki",
55
+ "beige",
56
+ "snow",
57
+ "ghostwhite",
58
+ "limegreen",
59
+ "coral",
60
+ "dimgrey",
61
+ "hotpink",
62
+ "midnightblue",
63
+ "firebrick",
64
+ "indigo",
65
+ "wheat",
66
+ "mediumblue",
67
+ "lightpink",
68
+ "plum",
69
+ "azure",
70
+ "violet",
71
+ "lavender",
72
+ "deepskyblue",
73
+ "darkslategrey",
74
+ "goldenrod",
75
+ "cornflowerblue",
76
+ "lightskyblue",
77
+ "indianred",
78
+ "yellowgreen",
79
+ "saddlebrown",
80
+ "palegreen",
81
+ "bisque",
82
+ "tan",
83
+ "antiquewhite",
84
+ "steelblue",
85
+ "forestgreen",
86
+ "fuchsia",
87
+ "mediumaquamarine",
88
+ "seagreen",
89
+ "sienna",
90
+ "deeppink",
91
+ "mediumseagreen",
92
+ "peru",
93
+ "greenyellow",
94
+ "lightgoldenrodyellow",
95
+ "orchid",
96
+ "cadetblue",
97
+ "navajowhite",
98
+ "lightsteelblue",
99
+ "slategrey",
100
+ "linen",
101
+ "lightseagreen",
102
+ "darkcyan",
103
+ "lightcoral",
104
+ "aquamarine",
105
+ "blueviolet",
106
+ "cornsilk",
107
+ "lightsalmon",
108
+ "chocolate",
109
+ "lightslategray",
110
+ "floralwhite",
111
+ "darkturquoise",
112
+ "darkslategray",
113
+ "rebeccapurple",
114
+ "burlywood",
115
+ "chartreuse",
116
+ "lightcyan",
117
+ "lemonchiffon",
118
+ "palevioletred",
119
+ "darkslateblue",
120
+ "mediumpurple",
121
+ "lawngreen",
122
+ "slateblue",
123
+ "darkseagreen",
124
+ "blanchedalmond",
125
+ "mistyrose",
126
+ "darkolivegreen",
127
+ "seashell",
128
+ "olivedrab",
129
+ "peachpuff",
130
+ "darkviolet",
131
+ "powderblue",
132
+ "darkmagenta",
133
+ "lightslategrey",
134
+ "honeydew",
135
+ "palegoldenrod",
136
+ "darkkhaki",
137
+ "oldlace",
138
+ "mintcream",
139
+ "sandybrown",
140
+ "mediumturquoise",
141
+ "papayawhip",
142
+ "paleturquoise",
143
+ "mediumvioletred",
144
+ "thistle",
145
+ "springgreen",
146
+ "moccasin",
147
+ "rosybrown",
148
+ "lavenderblush",
149
+ "mediumslateblue",
150
+ "darkorchid",
151
+ "mediumorchid",
152
+ "darksalmon",
153
+ "mediumspringgreen"
154
+ ]);
155
+ const systemColors = new KeywordSet([
156
+ "accentcolor",
157
+ "accentcolortext",
158
+ "activetext",
159
+ "buttonborder",
160
+ "buttonface",
161
+ "buttontext",
162
+ "canvas",
163
+ "canvastext",
164
+ "field",
165
+ "fieldtext",
166
+ "graytext",
167
+ "highlight",
168
+ "highlighttext",
169
+ "linktext",
170
+ "mark",
171
+ "marktext",
172
+ "selecteditem",
173
+ "selecteditemtext",
174
+ "visitedtext"
175
+ ]);
176
+ const colorFunctions = new KeywordSet([
177
+ "rgba",
178
+ "rgb",
179
+ "hsla",
180
+ "hsl",
181
+ "oklch",
182
+ "color",
183
+ "hwb",
184
+ "lch",
185
+ "lab",
186
+ "oklab"
187
+ ]);
188
+ const colorKeywords = new KeywordSet(["transparent", "currentcolor"]);
189
+ //#endregion
190
+ //#region src/values/values.ts
191
+ const keywords = new KeywordSet([
192
+ "auto",
193
+ "none",
194
+ "inherit",
195
+ "initial",
196
+ "unset",
197
+ "revert",
198
+ "revert-layer"
199
+ ]);
200
+ /**
201
+ * Test whether a value is a reset (0, 0px, -0.0e0 etc.)
202
+ */
203
+ function isValueReset(value) {
204
+ for (let node of value) {
205
+ if (is_number(node) && node.value === 0) continue;
206
+ if (is_dimension(node) && node.value === 0) continue;
207
+ return false;
208
+ }
209
+ return true;
210
+ }
211
+ //#endregion
212
+ //#region src/values/destructure-font-shorthand.ts
213
+ const SYSTEM_FONTS = new KeywordSet([
214
+ "caption",
215
+ "icon",
216
+ "menu",
217
+ "message-box",
218
+ "small-caption",
219
+ "status-bar"
220
+ ]);
221
+ /** Keyword values for <absolute-size> and <relative-size> */
222
+ const SIZE_KEYWORDS = new KeywordSet([
223
+ "xx-small",
224
+ "x-small",
225
+ "small",
226
+ "medium",
227
+ "large",
228
+ "x-large",
229
+ "xx-large",
230
+ "xxx-large",
231
+ "smaller",
232
+ "larger"
233
+ ]);
234
+ /**
235
+ * Identifier keywords that appear before font-size in the font shorthand:
236
+ * font-style, font-variant, font-weight (keyword form), font-stretch, and "normal"
237
+ */
238
+ const PRE_SIZE_KEYWORDS = new KeywordSet([
239
+ "italic",
240
+ "oblique",
241
+ "small-caps",
242
+ "bold",
243
+ "bolder",
244
+ "lighter",
245
+ "ultra-condensed",
246
+ "extra-condensed",
247
+ "condensed",
248
+ "semi-condensed",
249
+ "semi-expanded",
250
+ "expanded",
251
+ "extra-expanded",
252
+ "ultra-expanded",
253
+ "normal"
254
+ ]);
255
+ const SLASH = 47;
256
+ /**
257
+ * Parse the CSS `font` shorthand value and extract its structural components.
258
+ *
259
+ * Grammar:
260
+ * font: [<font-style> || <font-variant> || <font-weight> || <font-stretch>]?
261
+ * <font-size>[/<line-height>]? <font-family>
262
+ *
263
+ * Does NOT handle system fonts (caption, icon, menu, …) — the caller should
264
+ * check SYSTEM_FONTS before calling this function.
265
+ *
266
+ * Returns null when the value is a single var() and can't be decomposed.
267
+ *
268
+ * @param value - The VALUE CSSNode for a `font` declaration
269
+ * @param cb - Called for every global CSS keyword found in the value (e.g. inherit)
270
+ */
271
+ function destructure(value, cb) {
272
+ if (!value.has_children) return null;
273
+ if (value.child_count === 1 && is_function(value.first_child)) return null;
274
+ for (const child of value) if (is_identifier(child) && keywords.has(child.name)) cb(child.name);
275
+ let children = value.children;
276
+ let font_size;
277
+ let line_height;
278
+ let font_family_start = -1;
279
+ let slash_index = -1;
280
+ for (let i = 0; i < value.child_count; i++) {
281
+ const child = children[i];
282
+ if (child && is_operator(child) && child.text.charCodeAt(0) === SLASH) {
283
+ slash_index = i;
284
+ break;
285
+ }
286
+ }
287
+ if (slash_index === -1) for (let i = 0; i < children.length; i++) {
288
+ const child = children[i];
289
+ if (!child) continue;
290
+ if (is_dimension(child)) {
291
+ font_size = child.text;
292
+ font_family_start = i + 1;
293
+ break;
294
+ }
295
+ if (is_function(child)) {
296
+ font_size = child.text;
297
+ font_family_start = i + 1;
298
+ break;
299
+ }
300
+ if (is_identifier(child)) {
301
+ const name = child.name;
302
+ if (SIZE_KEYWORDS.has(name)) {
303
+ font_size = child.text;
304
+ font_family_start = i + 1;
305
+ break;
306
+ }
307
+ if (PRE_SIZE_KEYWORDS.has(name) || keywords.has(name)) continue;
308
+ font_family_start = i;
309
+ break;
310
+ }
311
+ if (is_string(child)) {
312
+ font_family_start = i;
313
+ break;
314
+ }
315
+ }
316
+ else {
317
+ if (slash_index > 0) font_size = children[slash_index - 1].text;
318
+ const after_slash = slash_index + 1;
319
+ if (after_slash < children.length) {
320
+ line_height = children[after_slash].text;
321
+ font_family_start = after_slash + 1;
322
+ }
323
+ }
324
+ let font_family = null;
325
+ if (font_family_start >= 0 && font_family_start < children.length) {
326
+ const first = children[font_family_start];
327
+ const last = children.at(-1);
328
+ if (first && last) font_family = value.text.substring(first.start - value.start, last.end - value.start);
329
+ }
330
+ return {
331
+ font_size,
332
+ line_height,
333
+ font_family
334
+ };
335
+ }
336
+ //#endregion
337
+ //#region src/values/browserhacks.ts
338
+ function isIe9Hack(node) {
339
+ if (node.has_children) {
340
+ let last = node.first_child;
341
+ while (last.has_next) last = last.next_sibling;
342
+ return last && is_identifier(last) && endsWith("\\9", last.text) ? true : false;
343
+ }
344
+ return false;
345
+ }
346
+ //#endregion
347
+ export { keywords as a, namedColors as c, isValueReset as i, systemColors as l, SYSTEM_FONTS as n, colorFunctions as o, destructure as r, colorKeywords as s, isIe9Hack as t };
package/dist/index.d.ts CHANGED
@@ -1,19 +1,18 @@
1
- import { n as isSupportsBrowserhack, t as isMediaBrowserhack } from "./atrules-CvzPtm16.js";
2
- import { a as calculate, c as CollectionCount, i as isPrefixed, l as Location, n as getComplexity, r as isAccessibility, u as UniqueWithLocations } from "./utils-BUeYqEL1.js";
3
- import { a as namedColors, i as colorKeywords, n as keywords, o as systemColors, r as colorFunctions, s as KeywordSet } from "./values-Dw53soqy.js";
1
+ import { n as isSupportsBrowserhack, t as isMediaBrowserhack } from "./atrules-CXLSfmpu.js";
2
+ import { a as calculate, c as CollectionCount, i as isPrefixed, l as Location, n as getComplexity, r as isAccessibility, u as UniqueWithLocations } from "./utils-yIUD7vGy.js";
3
+ import { t as KeywordSet } from "./keyword-set-BXSoLQ6m.js";
4
+ import { i as isHack } from "./property-utils-MKX6iGvg.js";
5
+ import { a as namedColors, i as colorKeywords, n as keywords, o as systemColors, r as colorFunctions } from "./values-DgD2lJqZ.js";
4
6
  import { CSSNode } from "@projectwallace/css-parser";
5
7
 
6
- //#region src/properties/property-utils.d.ts
7
- /**
8
- * @see https://github.com/csstree/csstree/blob/master/lib/utils/names.js#L69
9
- */
10
- declare function isHack(property: string): boolean;
11
- //#endregion
12
8
  //#region src/values/vendor-prefix.d.ts
13
- declare function isValuePrefixed(node: CSSNode, on_value: (value: string) => void): void;
9
+ declare function isValuePrefixed(value: CSSNode, on_value: (value: string) => void): void;
14
10
  //#endregion
15
11
  //#region src/vendor-prefix.d.ts
16
- /** Kept for backwards compatibility */
12
+ /**
13
+ * Kept for backwards compatibility
14
+ * @deprecated Will be removed in next major version
15
+ * */
17
16
  declare function hasVendorPrefix(keyword: string): boolean;
18
17
  //#endregion
19
18
  //#region src/index.d.ts
@@ -441,6 +440,18 @@ declare function analyzeInternal<T extends boolean>(css: string, options: Option
441
440
  ratio: number;
442
441
  };
443
442
  };
443
+ shorthands: {
444
+ total: number;
445
+ totalUnique: number;
446
+ unique: Record<string, number>;
447
+ uniquenessRatio: number;
448
+ } & (T extends true ? {
449
+ uniqueWithLocations: UniqueWithLocations;
450
+ } : {
451
+ uniqueWithLocations?: undefined;
452
+ }) & {
453
+ ratio: number;
454
+ };
444
455
  browserhacks: {
445
456
  total: number;
446
457
  totalUnique: number;