@projectwallace/css-analyzer 9.4.0 → 9.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/atrules/index.d.ts +2 -0
- package/dist/atrules/index.js +2 -0
- package/dist/atrules-C8lZ1H_5.d.ts +16 -0
- package/dist/atrules-CskmpIdJ.js +76 -0
- package/dist/browserhacks-Ckz2JiOQ.js +222 -0
- package/dist/index.d.ts +22 -75
- package/dist/index.js +15 -658
- package/dist/keyword-set-BXSoLQ6m.d.ts +11 -0
- package/dist/keyword-set-qSyAMR9o.js +16 -0
- package/dist/properties/index.d.ts +2 -0
- package/dist/properties/index.js +2 -0
- package/dist/property-utils-B3n9KkA9.js +107 -0
- package/dist/property-utils-MKX6iGvg.d.ts +17 -0
- package/dist/selectors/index.d.ts +2 -0
- package/dist/selectors/index.js +3 -0
- package/dist/specificity-BKdu6JZr.js +269 -0
- package/dist/string-utils-C97yyuqE.js +34 -0
- package/dist/utils-DJb_IpTO.d.ts +54 -0
- package/dist/values/index.d.ts +7 -0
- package/dist/values/index.js +3 -0
- package/dist/values-B5nDaGc_.d.ts +17 -0
- package/package.json +22 -4
package/dist/index.js
CHANGED
|
@@ -1,595 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
function isSupportsBrowserhack(node, on_hack) {
|
|
9
|
-
walk(node, function(n) {
|
|
10
|
-
if (n.type === SUPPORTS_QUERY) {
|
|
11
|
-
const normalizedPrelude = (n.prelude || n.value || "").toString().toLowerCase().replaceAll(/\s+/g, "");
|
|
12
|
-
if (normalizedPrelude.includes("-webkit-appearance:none")) {
|
|
13
|
-
on_hack("-webkit-appearance: none");
|
|
14
|
-
return BREAK;
|
|
15
|
-
}
|
|
16
|
-
if (normalizedPrelude.includes("-moz-appearance:meterbar")) {
|
|
17
|
-
on_hack("-moz-appearance: meterbar");
|
|
18
|
-
return BREAK;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Check if a @media atRule is a browserhack (Wallace parser version)
|
|
25
|
-
* @param node - The Atrule CSSNode from Wallace parser
|
|
26
|
-
* @returns true if the atrule is a browserhack
|
|
27
|
-
*/
|
|
28
|
-
function isMediaBrowserhack(node, on_hack) {
|
|
29
|
-
walk(node, function(n) {
|
|
30
|
-
if (n.type === MEDIA_TYPE) {
|
|
31
|
-
const text = n.text || "";
|
|
32
|
-
if (text.startsWith("\\0")) {
|
|
33
|
-
on_hack("\\0");
|
|
34
|
-
return BREAK;
|
|
35
|
-
}
|
|
36
|
-
if (text.includes("\\9")) {
|
|
37
|
-
on_hack("\\9");
|
|
38
|
-
return BREAK;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
if (n.type === MEDIA_FEATURE) {
|
|
42
|
-
const name = n.property || "";
|
|
43
|
-
if (str_equals("-moz-images-in-menus", name)) {
|
|
44
|
-
on_hack("-moz-images-in-menus");
|
|
45
|
-
return BREAK;
|
|
46
|
-
}
|
|
47
|
-
if (str_equals("min--moz-device-pixel-ratio", name)) {
|
|
48
|
-
on_hack("min--moz-device-pixel-ratio");
|
|
49
|
-
return BREAK;
|
|
50
|
-
}
|
|
51
|
-
if (str_equals("-ms-high-contrast", name)) {
|
|
52
|
-
on_hack("-ms-high-contrast");
|
|
53
|
-
return BREAK;
|
|
54
|
-
}
|
|
55
|
-
if (str_equals("min-resolution", name) && n.has_children) {
|
|
56
|
-
for (const child of n) if (child.type === DIMENSION && child.value === .001 && str_equals("dpcm", child.unit || "")) {
|
|
57
|
-
on_hack("min-resolution: .001dpcm");
|
|
58
|
-
return BREAK;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (str_equals("-webkit-min-device-pixel-ratio", name) && n.has_children) {
|
|
62
|
-
for (const child of n) if (child.type === NUMBER && (child.value === 0 || child.value === 1e4)) {
|
|
63
|
-
on_hack("-webkit-min-device-pixel-ratio");
|
|
64
|
-
return BREAK;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (n.has_children) {
|
|
68
|
-
for (const child of n) if (child.type === IDENTIFIER && child.text === "\\0") {
|
|
69
|
-
on_hack("\\0");
|
|
70
|
-
return BREAK;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
//#endregion
|
|
77
|
-
//#region src/keyword-set.ts
|
|
78
|
-
/**
|
|
79
|
-
* @description A Set-like construct to search CSS keywords in a case-insensitive way
|
|
80
|
-
*/
|
|
81
|
-
var KeywordSet = class {
|
|
82
|
-
set;
|
|
83
|
-
constructor(items) {
|
|
84
|
-
/** @type {Set<string>} */
|
|
85
|
-
this.set = new Set(items);
|
|
86
|
-
}
|
|
87
|
-
has(item) {
|
|
88
|
-
return this.set.has(item.toLowerCase());
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
//#endregion
|
|
92
|
-
//#region src/string-utils.ts
|
|
93
|
-
function unquote(str) {
|
|
94
|
-
return str.replaceAll(/(?:^['"])|(?:['"]$)/g, "");
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Case-insensitive compare two character codes
|
|
98
|
-
* @see https://github.com/csstree/csstree/blob/41f276e8862d8223eeaa01a3d113ab70bb13d2d9/lib/tokenizer/utils.js#L22
|
|
99
|
-
*/
|
|
100
|
-
function compareChar(referenceCode, testCode) {
|
|
101
|
-
if (testCode >= 65 && testCode <= 90) testCode = testCode | 32;
|
|
102
|
-
return referenceCode === testCode;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Case-insensitive testing whether a string ends with a given substring
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* endsWith('test', 'my-test') // true
|
|
109
|
-
* endsWith('test', 'est') // false
|
|
110
|
-
*
|
|
111
|
-
* @param base e.g. '-webkit-transform'
|
|
112
|
-
* @param maybe e.g. 'transform'
|
|
113
|
-
* @returns true if `test` ends with `base`, false otherwise
|
|
114
|
-
*/
|
|
115
|
-
function endsWith(base, maybe) {
|
|
116
|
-
if (base === maybe) return true;
|
|
117
|
-
let len = maybe.length;
|
|
118
|
-
let offset = len - base.length;
|
|
119
|
-
if (offset < 0) return false;
|
|
120
|
-
for (let i = len - 1; i >= offset; i--) if (compareChar(base.charCodeAt(i - offset), maybe.charCodeAt(i)) === false) return false;
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
//#endregion
|
|
124
|
-
//#region src/selectors/utils.ts
|
|
125
|
-
const PSEUDO_FUNCTIONS = new KeywordSet([
|
|
126
|
-
"nth-child",
|
|
127
|
-
"where",
|
|
128
|
-
"not",
|
|
129
|
-
"is",
|
|
130
|
-
"has",
|
|
131
|
-
"nth-last-child",
|
|
132
|
-
"matches",
|
|
133
|
-
"-webkit-any",
|
|
134
|
-
"-moz-any"
|
|
135
|
-
]);
|
|
136
|
-
function isPrefixed(selector, on_selector) {
|
|
137
|
-
walk(selector, function(node) {
|
|
138
|
-
if (node.type === PSEUDO_ELEMENT_SELECTOR || node.type === PSEUDO_CLASS_SELECTOR || node.type === TYPE_SELECTOR) {
|
|
139
|
-
if (node.is_vendor_prefixed) {
|
|
140
|
-
let prefix = "";
|
|
141
|
-
if (node.type === PSEUDO_CLASS_SELECTOR) prefix = ":";
|
|
142
|
-
else if (node.type === PSEUDO_ELEMENT_SELECTOR) prefix = "::";
|
|
143
|
-
on_selector(prefix + (node.name || node.text));
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Check if a Wallace selector is an accessibility selector (has aria-* or role attribute)
|
|
150
|
-
*/
|
|
151
|
-
function isAccessibility(selector, on_selector) {
|
|
152
|
-
function normalize(node) {
|
|
153
|
-
let clone = node.clone();
|
|
154
|
-
if (clone.value) return "[" + clone.name?.toLowerCase() + clone.attr_operator + "\"" + unquote(clone.value.toString()) + "\"]";
|
|
155
|
-
return "[" + clone.name?.toLowerCase() + "]";
|
|
156
|
-
}
|
|
157
|
-
walk(selector, function(node) {
|
|
158
|
-
if (node.type === ATTRIBUTE_SELECTOR) {
|
|
159
|
-
const name = node.name || "";
|
|
160
|
-
if (str_equals("role", name) || str_starts_with(name, "aria-")) on_selector(normalize(node));
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Get the Complexity for a Wallace Selector Node
|
|
166
|
-
* @param selector - Wallace CSSNode for a Selector
|
|
167
|
-
* @return The numeric complexity of the Selector
|
|
168
|
-
*/
|
|
169
|
-
function getComplexity(selector) {
|
|
170
|
-
let complexity = 0;
|
|
171
|
-
function findSelectors(node, complexities) {
|
|
172
|
-
walk(node, function(n) {
|
|
173
|
-
if (n.type === SELECTOR) complexities.push(getComplexity(n));
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
walk(selector, function(node) {
|
|
177
|
-
const type = node.type;
|
|
178
|
-
if (type === SELECTOR) return;
|
|
179
|
-
if (type === NTH_SELECTOR) {
|
|
180
|
-
if (node.text && node.text.trim()) complexity++;
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
complexity++;
|
|
184
|
-
if (type === PSEUDO_ELEMENT_SELECTOR || type === TYPE_SELECTOR || type === PSEUDO_CLASS_SELECTOR) {
|
|
185
|
-
if (node.is_vendor_prefixed) complexity++;
|
|
186
|
-
}
|
|
187
|
-
if (type === ATTRIBUTE_SELECTOR) {
|
|
188
|
-
if (node.value) complexity++;
|
|
189
|
-
return SKIP;
|
|
190
|
-
}
|
|
191
|
-
if (type === PSEUDO_CLASS_SELECTOR) {
|
|
192
|
-
const name = node.name || "";
|
|
193
|
-
if (PSEUDO_FUNCTIONS.has(name.toLowerCase())) {
|
|
194
|
-
const childComplexities = [];
|
|
195
|
-
if (node.has_children) for (const child of node) if (child.type === SELECTOR) childComplexities.push(getComplexity(child));
|
|
196
|
-
else findSelectors(child, childComplexities);
|
|
197
|
-
if (childComplexities.length > 0) {
|
|
198
|
-
for (const c of childComplexities) complexity += c;
|
|
199
|
-
return SKIP;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
return complexity;
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Walk a selector node and trigger a callback every time a Combinator was found
|
|
208
|
-
*/
|
|
209
|
-
function getCombinators(selector, onMatch) {
|
|
210
|
-
walk(selector, function(node) {
|
|
211
|
-
if (node.type === COMBINATOR) onMatch({
|
|
212
|
-
name: node.name?.trim() === "" ? " " : node.name,
|
|
213
|
-
loc: {
|
|
214
|
-
offset: node.start,
|
|
215
|
-
line: node.line,
|
|
216
|
-
column: node.column,
|
|
217
|
-
length: 1
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
//#endregion
|
|
223
|
-
//#region src/selectors/specificity.ts
|
|
224
|
-
function compare(s1, s2) {
|
|
225
|
-
if (s1[0] === s2[0]) {
|
|
226
|
-
if (s1[1] === s2[1]) return s1[2] - s2[2];
|
|
227
|
-
return s1[1] - s2[1];
|
|
228
|
-
}
|
|
229
|
-
return s1[0] - s2[0];
|
|
230
|
-
}
|
|
231
|
-
function max(list) {
|
|
232
|
-
return list.sort(compare).at(-1);
|
|
233
|
-
}
|
|
234
|
-
const calculateForAST = (selectorAST) => {
|
|
235
|
-
let a = 0;
|
|
236
|
-
let b = 0;
|
|
237
|
-
let c = 0;
|
|
238
|
-
let current = selectorAST.first_child;
|
|
239
|
-
while (current) {
|
|
240
|
-
switch (current.type) {
|
|
241
|
-
case ID_SELECTOR:
|
|
242
|
-
a += 1;
|
|
243
|
-
break;
|
|
244
|
-
case ATTRIBUTE_SELECTOR:
|
|
245
|
-
case CLASS_SELECTOR:
|
|
246
|
-
b += 1;
|
|
247
|
-
break;
|
|
248
|
-
case PSEUDO_CLASS_SELECTOR:
|
|
249
|
-
switch (current.name?.toLowerCase()) {
|
|
250
|
-
case "where": break;
|
|
251
|
-
case "-webkit-any":
|
|
252
|
-
case "any":
|
|
253
|
-
if (current.first_child) b += 1;
|
|
254
|
-
break;
|
|
255
|
-
case "-moz-any":
|
|
256
|
-
case "is":
|
|
257
|
-
case "matches":
|
|
258
|
-
case "not":
|
|
259
|
-
case "has":
|
|
260
|
-
if (current.has_children) {
|
|
261
|
-
const childSelectorList = current.first_child;
|
|
262
|
-
if (childSelectorList?.type === SELECTOR_LIST) {
|
|
263
|
-
const max1 = max(calculate(childSelectorList));
|
|
264
|
-
a += max1[0];
|
|
265
|
-
b += max1[1];
|
|
266
|
-
c += max1[2];
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
break;
|
|
270
|
-
case "nth-child":
|
|
271
|
-
case "nth-last-child":
|
|
272
|
-
b += 1;
|
|
273
|
-
const nthOf = current.first_child;
|
|
274
|
-
if (nthOf?.type === NTH_OF_SELECTOR && nthOf.selector) {
|
|
275
|
-
const max2 = max(calculate(nthOf.selector));
|
|
276
|
-
a += max2[0];
|
|
277
|
-
b += max2[1];
|
|
278
|
-
c += max2[2];
|
|
279
|
-
}
|
|
280
|
-
break;
|
|
281
|
-
case "host-context":
|
|
282
|
-
case "host":
|
|
283
|
-
b += 1;
|
|
284
|
-
const childSelector = current.first_child?.first_child;
|
|
285
|
-
if (childSelector?.type === SELECTOR) {
|
|
286
|
-
let childPart = childSelector.first_child;
|
|
287
|
-
while (childPart) {
|
|
288
|
-
if (childPart.type === COMBINATOR) break;
|
|
289
|
-
const partSpecificity = calculateForAST({
|
|
290
|
-
type_name: "Selector",
|
|
291
|
-
first_child: childPart,
|
|
292
|
-
has_children: true
|
|
293
|
-
});
|
|
294
|
-
a += partSpecificity[0] ?? 0;
|
|
295
|
-
b += partSpecificity[1] ?? 0;
|
|
296
|
-
c += partSpecificity[2] ?? 0;
|
|
297
|
-
childPart = childPart.next_sibling;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
break;
|
|
301
|
-
case "after":
|
|
302
|
-
case "before":
|
|
303
|
-
case "first-letter":
|
|
304
|
-
case "first-line":
|
|
305
|
-
c += 1;
|
|
306
|
-
break;
|
|
307
|
-
default:
|
|
308
|
-
b += 1;
|
|
309
|
-
break;
|
|
310
|
-
}
|
|
311
|
-
break;
|
|
312
|
-
case PSEUDO_ELEMENT_SELECTOR:
|
|
313
|
-
switch (current.name?.toLowerCase()) {
|
|
314
|
-
case "slotted":
|
|
315
|
-
c += 1;
|
|
316
|
-
const childSelector = current.first_child?.first_child;
|
|
317
|
-
if (childSelector?.type === SELECTOR) {
|
|
318
|
-
let childPart = childSelector.first_child;
|
|
319
|
-
while (childPart) {
|
|
320
|
-
if (childPart.type === COMBINATOR) break;
|
|
321
|
-
const partSpecificity = calculateForAST({
|
|
322
|
-
type_name: "Selector",
|
|
323
|
-
first_child: childPart,
|
|
324
|
-
has_children: true
|
|
325
|
-
});
|
|
326
|
-
a += partSpecificity[0] ?? 0;
|
|
327
|
-
b += partSpecificity[1] ?? 0;
|
|
328
|
-
c += partSpecificity[2] ?? 0;
|
|
329
|
-
childPart = childPart.next_sibling;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
break;
|
|
333
|
-
case "view-transition-group":
|
|
334
|
-
case "view-transition-image-pair":
|
|
335
|
-
case "view-transition-old":
|
|
336
|
-
case "view-transition-new":
|
|
337
|
-
if (current.first_child?.text === "*") break;
|
|
338
|
-
c += 1;
|
|
339
|
-
break;
|
|
340
|
-
default:
|
|
341
|
-
c += 1;
|
|
342
|
-
break;
|
|
343
|
-
}
|
|
344
|
-
break;
|
|
345
|
-
case TYPE_SELECTOR:
|
|
346
|
-
let typeSelector = current.name ?? "";
|
|
347
|
-
if (typeSelector.includes("|")) typeSelector = typeSelector.split("|")[1] ?? "";
|
|
348
|
-
if (typeSelector !== "*") c += 1;
|
|
349
|
-
break;
|
|
350
|
-
default: break;
|
|
351
|
-
}
|
|
352
|
-
current = current.next_sibling;
|
|
353
|
-
}
|
|
354
|
-
return [
|
|
355
|
-
a,
|
|
356
|
-
b,
|
|
357
|
-
c
|
|
358
|
-
];
|
|
359
|
-
};
|
|
360
|
-
const convertToAST = (source) => {
|
|
361
|
-
if (typeof source === "string") try {
|
|
362
|
-
return parse_selector(source);
|
|
363
|
-
} catch (e) {
|
|
364
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
365
|
-
throw new TypeError(`Could not convert passed in source '${source}' to SelectorList: ${message}`);
|
|
366
|
-
}
|
|
367
|
-
if (source instanceof Object) {
|
|
368
|
-
if (source.type === SELECTOR_LIST) return source;
|
|
369
|
-
throw new TypeError(`Passed in source is an Object but no AST / AST of the type SelectorList`);
|
|
370
|
-
}
|
|
371
|
-
throw new TypeError(`Passed in source is not a String nor an Object. I don't know what to do with it.`);
|
|
372
|
-
};
|
|
373
|
-
const calculate = (selector) => {
|
|
374
|
-
if (!selector) return [];
|
|
375
|
-
const ast = convertToAST(selector);
|
|
376
|
-
const specificities = [];
|
|
377
|
-
let selectorNode = ast.first_child;
|
|
378
|
-
while (selectorNode) {
|
|
379
|
-
specificities.push(calculateForAST(selectorNode));
|
|
380
|
-
selectorNode = selectorNode.next_sibling;
|
|
381
|
-
}
|
|
382
|
-
return specificities;
|
|
383
|
-
};
|
|
384
|
-
//#endregion
|
|
385
|
-
//#region src/values/colors.ts
|
|
386
|
-
const namedColors = new KeywordSet([
|
|
387
|
-
"white",
|
|
388
|
-
"black",
|
|
389
|
-
"red",
|
|
390
|
-
"gray",
|
|
391
|
-
"silver",
|
|
392
|
-
"grey",
|
|
393
|
-
"green",
|
|
394
|
-
"orange",
|
|
395
|
-
"blue",
|
|
396
|
-
"dimgray",
|
|
397
|
-
"whitesmoke",
|
|
398
|
-
"lightgray",
|
|
399
|
-
"lightgrey",
|
|
400
|
-
"yellow",
|
|
401
|
-
"gold",
|
|
402
|
-
"pink",
|
|
403
|
-
"gainsboro",
|
|
404
|
-
"magenta",
|
|
405
|
-
"purple",
|
|
406
|
-
"darkgray",
|
|
407
|
-
"navy",
|
|
408
|
-
"darkred",
|
|
409
|
-
"teal",
|
|
410
|
-
"maroon",
|
|
411
|
-
"darkgrey",
|
|
412
|
-
"tomato",
|
|
413
|
-
"darkorange",
|
|
414
|
-
"brown",
|
|
415
|
-
"crimson",
|
|
416
|
-
"lightyellow",
|
|
417
|
-
"slategray",
|
|
418
|
-
"salmon",
|
|
419
|
-
"lightgreen",
|
|
420
|
-
"lightblue",
|
|
421
|
-
"orangered",
|
|
422
|
-
"aliceblue",
|
|
423
|
-
"dodgerblue",
|
|
424
|
-
"lime",
|
|
425
|
-
"darkblue",
|
|
426
|
-
"darkgoldenrod",
|
|
427
|
-
"skyblue",
|
|
428
|
-
"royalblue",
|
|
429
|
-
"darkgreen",
|
|
430
|
-
"ivory",
|
|
431
|
-
"olive",
|
|
432
|
-
"aqua",
|
|
433
|
-
"turquoise",
|
|
434
|
-
"cyan",
|
|
435
|
-
"khaki",
|
|
436
|
-
"beige",
|
|
437
|
-
"snow",
|
|
438
|
-
"ghostwhite",
|
|
439
|
-
"limegreen",
|
|
440
|
-
"coral",
|
|
441
|
-
"dimgrey",
|
|
442
|
-
"hotpink",
|
|
443
|
-
"midnightblue",
|
|
444
|
-
"firebrick",
|
|
445
|
-
"indigo",
|
|
446
|
-
"wheat",
|
|
447
|
-
"mediumblue",
|
|
448
|
-
"lightpink",
|
|
449
|
-
"plum",
|
|
450
|
-
"azure",
|
|
451
|
-
"violet",
|
|
452
|
-
"lavender",
|
|
453
|
-
"deepskyblue",
|
|
454
|
-
"darkslategrey",
|
|
455
|
-
"goldenrod",
|
|
456
|
-
"cornflowerblue",
|
|
457
|
-
"lightskyblue",
|
|
458
|
-
"indianred",
|
|
459
|
-
"yellowgreen",
|
|
460
|
-
"saddlebrown",
|
|
461
|
-
"palegreen",
|
|
462
|
-
"bisque",
|
|
463
|
-
"tan",
|
|
464
|
-
"antiquewhite",
|
|
465
|
-
"steelblue",
|
|
466
|
-
"forestgreen",
|
|
467
|
-
"fuchsia",
|
|
468
|
-
"mediumaquamarine",
|
|
469
|
-
"seagreen",
|
|
470
|
-
"sienna",
|
|
471
|
-
"deeppink",
|
|
472
|
-
"mediumseagreen",
|
|
473
|
-
"peru",
|
|
474
|
-
"greenyellow",
|
|
475
|
-
"lightgoldenrodyellow",
|
|
476
|
-
"orchid",
|
|
477
|
-
"cadetblue",
|
|
478
|
-
"navajowhite",
|
|
479
|
-
"lightsteelblue",
|
|
480
|
-
"slategrey",
|
|
481
|
-
"linen",
|
|
482
|
-
"lightseagreen",
|
|
483
|
-
"darkcyan",
|
|
484
|
-
"lightcoral",
|
|
485
|
-
"aquamarine",
|
|
486
|
-
"blueviolet",
|
|
487
|
-
"cornsilk",
|
|
488
|
-
"lightsalmon",
|
|
489
|
-
"chocolate",
|
|
490
|
-
"lightslategray",
|
|
491
|
-
"floralwhite",
|
|
492
|
-
"darkturquoise",
|
|
493
|
-
"darkslategray",
|
|
494
|
-
"rebeccapurple",
|
|
495
|
-
"burlywood",
|
|
496
|
-
"chartreuse",
|
|
497
|
-
"lightcyan",
|
|
498
|
-
"lemonchiffon",
|
|
499
|
-
"palevioletred",
|
|
500
|
-
"darkslateblue",
|
|
501
|
-
"mediumpurple",
|
|
502
|
-
"lawngreen",
|
|
503
|
-
"slateblue",
|
|
504
|
-
"darkseagreen",
|
|
505
|
-
"blanchedalmond",
|
|
506
|
-
"mistyrose",
|
|
507
|
-
"darkolivegreen",
|
|
508
|
-
"seashell",
|
|
509
|
-
"olivedrab",
|
|
510
|
-
"peachpuff",
|
|
511
|
-
"darkviolet",
|
|
512
|
-
"powderblue",
|
|
513
|
-
"darkmagenta",
|
|
514
|
-
"lightslategrey",
|
|
515
|
-
"honeydew",
|
|
516
|
-
"palegoldenrod",
|
|
517
|
-
"darkkhaki",
|
|
518
|
-
"oldlace",
|
|
519
|
-
"mintcream",
|
|
520
|
-
"sandybrown",
|
|
521
|
-
"mediumturquoise",
|
|
522
|
-
"papayawhip",
|
|
523
|
-
"paleturquoise",
|
|
524
|
-
"mediumvioletred",
|
|
525
|
-
"thistle",
|
|
526
|
-
"springgreen",
|
|
527
|
-
"moccasin",
|
|
528
|
-
"rosybrown",
|
|
529
|
-
"lavenderblush",
|
|
530
|
-
"mediumslateblue",
|
|
531
|
-
"darkorchid",
|
|
532
|
-
"mediumorchid",
|
|
533
|
-
"darksalmon",
|
|
534
|
-
"mediumspringgreen"
|
|
535
|
-
]);
|
|
536
|
-
const systemColors = new KeywordSet([
|
|
537
|
-
"accentcolor",
|
|
538
|
-
"accentcolortext",
|
|
539
|
-
"activetext",
|
|
540
|
-
"buttonborder",
|
|
541
|
-
"buttonface",
|
|
542
|
-
"buttontext",
|
|
543
|
-
"canvas",
|
|
544
|
-
"canvastext",
|
|
545
|
-
"field",
|
|
546
|
-
"fieldtext",
|
|
547
|
-
"graytext",
|
|
548
|
-
"highlight",
|
|
549
|
-
"highlighttext",
|
|
550
|
-
"linktext",
|
|
551
|
-
"mark",
|
|
552
|
-
"marktext",
|
|
553
|
-
"selecteditem",
|
|
554
|
-
"selecteditemtext",
|
|
555
|
-
"visitedtext"
|
|
556
|
-
]);
|
|
557
|
-
const colorFunctions = new KeywordSet([
|
|
558
|
-
"rgba",
|
|
559
|
-
"rgb",
|
|
560
|
-
"hsla",
|
|
561
|
-
"hsl",
|
|
562
|
-
"oklch",
|
|
563
|
-
"color",
|
|
564
|
-
"hwb",
|
|
565
|
-
"lch",
|
|
566
|
-
"lab",
|
|
567
|
-
"oklab"
|
|
568
|
-
]);
|
|
569
|
-
const colorKeywords = new KeywordSet(["transparent", "currentcolor"]);
|
|
570
|
-
//#endregion
|
|
571
|
-
//#region src/values/values.ts
|
|
572
|
-
const keywords = new KeywordSet([
|
|
573
|
-
"auto",
|
|
574
|
-
"none",
|
|
575
|
-
"inherit",
|
|
576
|
-
"initial",
|
|
577
|
-
"unset",
|
|
578
|
-
"revert",
|
|
579
|
-
"revert-layer"
|
|
580
|
-
]);
|
|
581
|
-
/**
|
|
582
|
-
* Test whether a value is a reset (0, 0px, -0.0e0 etc.)
|
|
583
|
-
*/
|
|
584
|
-
function isValueReset(node) {
|
|
585
|
-
for (let child of node.children) {
|
|
586
|
-
if (child.type === NUMBER && child.value === 0) continue;
|
|
587
|
-
if (child.type === DIMENSION && child.value === 0) continue;
|
|
588
|
-
return false;
|
|
589
|
-
}
|
|
590
|
-
return true;
|
|
591
|
-
}
|
|
592
|
-
//#endregion
|
|
1
|
+
import { n as isSupportsBrowserhack, t as isMediaBrowserhack } from "./atrules-CskmpIdJ.js";
|
|
2
|
+
import { t as KeywordSet } from "./keyword-set-qSyAMR9o.js";
|
|
3
|
+
import { n as unquote, t as endsWith } from "./string-utils-C97yyuqE.js";
|
|
4
|
+
import { a as getComplexity, i as getCombinators, n as calculateForAST, o as isAccessibility, s as isPrefixed, t as calculate } from "./specificity-BKdu6JZr.js";
|
|
5
|
+
import { a as colorKeywords, i as colorFunctions, n as isValueReset, o as namedColors, r as keywords, s as systemColors, t as isIe9Hack } from "./browserhacks-Ckz2JiOQ.js";
|
|
6
|
+
import { a as shorthand_properties, i as isHack, n as basename, r as border_radius_properties, t as SPACING_RESET_PROPERTIES } from "./property-utils-B3n9KkA9.js";
|
|
7
|
+
import { ATTRIBUTE_SELECTOR, AT_RULE, BLOCK, CONTAINER_QUERY, DECLARATION, DIMENSION, FUNCTION, HASH, IDENTIFIER, LAYER_NAME, MEDIA_FEATURE, NUMBER, OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, SELECTOR, SELECTOR_LIST, SKIP, STYLE_RULE, SUPPORTS_QUERY, TYPE_SELECTOR, URL, is_custom, is_vendor_prefixed, parse, str_starts_with, walk } from "@projectwallace/css-parser";
|
|
593
8
|
//#region src/values/destructure-font-shorthand.ts
|
|
594
9
|
const SYSTEM_FONTS = new KeywordSet([
|
|
595
10
|
"caption",
|
|
@@ -902,73 +317,11 @@ function getEmbedType(embed) {
|
|
|
902
317
|
return embed.substring(start, semicolon);
|
|
903
318
|
}
|
|
904
319
|
//#endregion
|
|
905
|
-
//#region src/values/browserhacks.ts
|
|
906
|
-
function isIe9Hack(node) {
|
|
907
|
-
let children = node.children;
|
|
908
|
-
if (children) {
|
|
909
|
-
let last = children.at(-1);
|
|
910
|
-
return last && last.type === IDENTIFIER && endsWith("\\9", last.text) ? true : false;
|
|
911
|
-
}
|
|
912
|
-
return false;
|
|
913
|
-
}
|
|
914
|
-
//#endregion
|
|
915
|
-
//#region src/properties/property-utils.ts
|
|
916
|
-
const SPACING_RESET_PROPERTIES = new Set([
|
|
917
|
-
"margin",
|
|
918
|
-
"margin-block",
|
|
919
|
-
"margin-inline",
|
|
920
|
-
"margin-top",
|
|
921
|
-
"margin-block-start",
|
|
922
|
-
"margin-block-end",
|
|
923
|
-
"margin-inline-end",
|
|
924
|
-
"margin-inline-end",
|
|
925
|
-
"margin-right",
|
|
926
|
-
"margin-bottom",
|
|
927
|
-
"margin-left",
|
|
928
|
-
"padding",
|
|
929
|
-
"padding-block",
|
|
930
|
-
"padding-inline",
|
|
931
|
-
"padding-top",
|
|
932
|
-
"padding-right",
|
|
933
|
-
"padding-bottom",
|
|
934
|
-
"padding-left",
|
|
935
|
-
"padding-block-start",
|
|
936
|
-
"padding-block-end",
|
|
937
|
-
"padding-inline-start",
|
|
938
|
-
"padding-inline-end"
|
|
939
|
-
]);
|
|
940
|
-
const border_radius_properties = new KeywordSet([
|
|
941
|
-
"border-radius",
|
|
942
|
-
"border-top-left-radius",
|
|
943
|
-
"border-top-right-radius",
|
|
944
|
-
"border-bottom-right-radius",
|
|
945
|
-
"border-bottom-left-radius",
|
|
946
|
-
"border-start-start-radius",
|
|
947
|
-
"border-start-end-radius",
|
|
948
|
-
"border-end-end-radius",
|
|
949
|
-
"border-end-start-radius"
|
|
950
|
-
]);
|
|
951
|
-
/**
|
|
952
|
-
* @see https://github.com/csstree/csstree/blob/master/lib/utils/names.js#L69
|
|
953
|
-
*/
|
|
954
|
-
function isHack(property) {
|
|
955
|
-
if (is_custom(property) || is_vendor_prefixed(property)) return false;
|
|
956
|
-
let code = property.charCodeAt(0);
|
|
957
|
-
return code === 47 || code === 42 || code === 95 || code === 43 || code === 38 || code === 36 || code === 35;
|
|
958
|
-
}
|
|
959
|
-
/**
|
|
960
|
-
* Get the normalized basename for a property with a vendor prefix
|
|
961
|
-
* @returns The property name without vendor prefix
|
|
962
|
-
*/
|
|
963
|
-
function basename(property) {
|
|
964
|
-
if (is_custom(property)) return property;
|
|
965
|
-
if (is_vendor_prefixed(property)) return property.slice(property.indexOf("-", 2) + 1).toLowerCase();
|
|
966
|
-
if (isHack(property)) return property.slice(1).toLowerCase();
|
|
967
|
-
return property.toLowerCase();
|
|
968
|
-
}
|
|
969
|
-
//#endregion
|
|
970
320
|
//#region src/vendor-prefix.ts
|
|
971
|
-
/**
|
|
321
|
+
/**
|
|
322
|
+
* Kept for backwards compatibility
|
|
323
|
+
* @deprecated
|
|
324
|
+
* */
|
|
972
325
|
function hasVendorPrefix(keyword) {
|
|
973
326
|
return is_vendor_prefixed(keyword);
|
|
974
327
|
}
|
|
@@ -1063,6 +416,7 @@ function analyzeInternal(css, options, useLocations) {
|
|
|
1063
416
|
let propertyHacks = new Collection(useLocations);
|
|
1064
417
|
let propertyVendorPrefixes = new Collection(useLocations);
|
|
1065
418
|
let customProperties = new Collection(useLocations);
|
|
419
|
+
let shorthands = new Collection(useLocations);
|
|
1066
420
|
let propertyComplexities = new AggregateCollection();
|
|
1067
421
|
let valueComplexities = new AggregateCollection();
|
|
1068
422
|
let vendorPrefixedValues = new Collection(useLocations);
|
|
@@ -1253,6 +607,7 @@ function analyzeInternal(css, options, useLocations) {
|
|
|
1253
607
|
propertyHacks.p(property.charAt(0), propertyLoc);
|
|
1254
608
|
propertyComplexities.push(2);
|
|
1255
609
|
} else propertyComplexities.push(1);
|
|
610
|
+
if (shorthand_properties.has(normalizedProperty)) shorthands.p(property, propertyLoc);
|
|
1256
611
|
{
|
|
1257
612
|
let value = node.value;
|
|
1258
613
|
let { text } = value;
|
|
@@ -1559,6 +914,7 @@ function analyzeInternal(css, options, useLocations) {
|
|
|
1559
914
|
ratio: ratio(customProperties.size(), properties.size()),
|
|
1560
915
|
importants: assign(importantCustomProperties.c(), { ratio: ratio(importantCustomProperties.size(), customProperties.size()) })
|
|
1561
916
|
}),
|
|
917
|
+
shorthands: assign(shorthands.c(), { ratio: ratio(shorthands.size(), properties.size()) }),
|
|
1562
918
|
browserhacks: assign(propertyHacks.c(), { ratio: ratio(propertyHacks.size(), properties.size()) }),
|
|
1563
919
|
complexity: propertyComplexity
|
|
1564
920
|
}),
|
|
@@ -1593,6 +949,7 @@ function analyzeInternal(css, options, useLocations) {
|
|
|
1593
949
|
}
|
|
1594
950
|
/**
|
|
1595
951
|
* Compare specificity A to Specificity B
|
|
952
|
+
* @deprecated this one is the inverse of the one exported in /selectors/index.ts; wille be removed in next major version
|
|
1596
953
|
* @returns 0 when a==b, 1 when a<b, -1 when a>b
|
|
1597
954
|
*/
|
|
1598
955
|
function compareSpecificity(a, b) {
|