@stacksjs/ts-css 0.1.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.
@@ -0,0 +1,3390 @@
1
+ // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+ var __require = import.meta.require;
17
+
18
+ // src/parse/index.ts
19
+ var exports_parse = {};
20
+ __export(exports_parse, {
21
+ walk: () => walk,
22
+ parse: () => parse,
23
+ makeList: () => makeList,
24
+ generate: () => generate,
25
+ decodeName: () => decodeName,
26
+ clone: () => clone,
27
+ Tokenizer: () => Tokenizer,
28
+ TokenType: () => TokenType,
29
+ List: () => CssList
30
+ });
31
+
32
+ // src/parse/list.ts
33
+ function createItem(data) {
34
+ return { prev: null, next: null, data };
35
+ }
36
+
37
+ class CssList {
38
+ head = null;
39
+ tail = null;
40
+ cursors = [];
41
+ allocateCursor(prev, next) {
42
+ const cursor = { prev, next };
43
+ this.cursors.push(cursor);
44
+ return cursor;
45
+ }
46
+ releaseCursor() {
47
+ this.cursors.pop();
48
+ }
49
+ updateCursors(prevOld, prevNew, nextOld, nextNew) {
50
+ for (const c of this.cursors) {
51
+ if (c.prev === prevOld)
52
+ c.prev = prevNew;
53
+ if (c.next === nextOld)
54
+ c.next = nextNew;
55
+ }
56
+ }
57
+ static createItem(data) {
58
+ return createItem(data);
59
+ }
60
+ createItem(data) {
61
+ return createItem(data);
62
+ }
63
+ get isEmpty() {
64
+ return this.head === null;
65
+ }
66
+ get first() {
67
+ return this.head?.data ?? null;
68
+ }
69
+ get last() {
70
+ return this.tail?.data ?? null;
71
+ }
72
+ *[Symbol.iterator]() {
73
+ for (let cur = this.head;cur != null; cur = cur.next)
74
+ yield cur.data;
75
+ }
76
+ fromArray(items) {
77
+ let prev = null;
78
+ this.head = null;
79
+ for (const data of items) {
80
+ const item = createItem(data);
81
+ item.prev = prev;
82
+ if (prev)
83
+ prev.next = item;
84
+ else
85
+ this.head = item;
86
+ prev = item;
87
+ }
88
+ this.tail = prev;
89
+ return this;
90
+ }
91
+ toArray() {
92
+ const out = [];
93
+ for (let cur = this.head;cur != null; cur = cur.next)
94
+ out.push(cur.data);
95
+ return out;
96
+ }
97
+ toJSON() {
98
+ return this.toArray();
99
+ }
100
+ forEach(fn, thisArg) {
101
+ const cursor = this.allocateCursor(null, this.head);
102
+ while (cursor.next !== null) {
103
+ const item = cursor.next;
104
+ cursor.prev = item;
105
+ cursor.next = item.next;
106
+ fn.call(thisArg, item.data, item, this);
107
+ }
108
+ this.releaseCursor();
109
+ }
110
+ forEachRight(fn, thisArg) {
111
+ const cursor = this.allocateCursor(this.tail, null);
112
+ while (cursor.prev !== null) {
113
+ const item = cursor.prev;
114
+ cursor.next = item;
115
+ cursor.prev = item.prev;
116
+ fn.call(thisArg, item.data, item, this);
117
+ }
118
+ this.releaseCursor();
119
+ }
120
+ reduce(fn, initial) {
121
+ let acc = initial;
122
+ let i = 0;
123
+ for (let cur = this.head;cur != null; cur = cur.next)
124
+ acc = fn(acc, cur.data, i++, this);
125
+ return acc;
126
+ }
127
+ some(fn) {
128
+ let i = 0;
129
+ for (let cur = this.head;cur != null; cur = cur.next) {
130
+ if (fn(cur.data, i++, this))
131
+ return true;
132
+ }
133
+ return false;
134
+ }
135
+ map(fn) {
136
+ const result = new CssList;
137
+ let prev = null;
138
+ let i = 0;
139
+ for (let cur = this.head;cur != null; cur = cur.next) {
140
+ const item = createItem(fn(cur.data, i++, this));
141
+ item.prev = prev;
142
+ if (prev)
143
+ prev.next = item;
144
+ else
145
+ result.head = item;
146
+ prev = item;
147
+ }
148
+ result.tail = prev;
149
+ return result;
150
+ }
151
+ filter(fn) {
152
+ const result = new CssList;
153
+ let prev = null;
154
+ let i = 0;
155
+ for (let cur = this.head;cur != null; cur = cur.next) {
156
+ if (fn(cur.data, i++, this)) {
157
+ const item = createItem(cur.data);
158
+ item.prev = prev;
159
+ if (prev)
160
+ prev.next = item;
161
+ else
162
+ result.head = item;
163
+ prev = item;
164
+ }
165
+ }
166
+ result.tail = prev;
167
+ return result;
168
+ }
169
+ clear() {
170
+ let cur = this.head;
171
+ while (cur) {
172
+ const nxt = cur.next;
173
+ cur.prev = null;
174
+ cur.next = null;
175
+ cur = nxt;
176
+ }
177
+ this.head = null;
178
+ this.tail = null;
179
+ }
180
+ copy() {
181
+ const result = new CssList;
182
+ let prev = null;
183
+ for (let cur = this.head;cur != null; cur = cur.next) {
184
+ const item = createItem(cur.data);
185
+ item.prev = prev;
186
+ if (prev)
187
+ prev.next = item;
188
+ else
189
+ result.head = item;
190
+ prev = item;
191
+ }
192
+ result.tail = prev;
193
+ return result;
194
+ }
195
+ prepend(item) {
196
+ return this.insert(item, this.head);
197
+ }
198
+ prependData(data) {
199
+ return this.insert(createItem(data), this.head);
200
+ }
201
+ append(item) {
202
+ return this.insert(item, null);
203
+ }
204
+ appendData(data) {
205
+ return this.insert(createItem(data), null);
206
+ }
207
+ insert(item, before = null) {
208
+ if (before != null) {
209
+ this.updateCursors(before.prev, item, before, item);
210
+ if (before.prev === null) {
211
+ if (this.head !== before)
212
+ throw new Error("before doesn't belong to list");
213
+ this.head = item;
214
+ before.prev = item;
215
+ item.next = before;
216
+ this.updateCursors(null, item, null, null);
217
+ } else {
218
+ before.prev.next = item;
219
+ item.prev = before.prev;
220
+ before.prev = item;
221
+ item.next = before;
222
+ }
223
+ } else {
224
+ this.updateCursors(this.tail, item, null, item);
225
+ if (this.tail !== null) {
226
+ this.tail.next = item;
227
+ item.prev = this.tail;
228
+ this.tail = item;
229
+ } else {
230
+ this.head = item;
231
+ this.tail = item;
232
+ }
233
+ }
234
+ return this;
235
+ }
236
+ insertData(data, before = null) {
237
+ return this.insert(createItem(data), before);
238
+ }
239
+ remove(item) {
240
+ this.updateCursors(item, item.prev, item, item.next);
241
+ if (item.prev !== null)
242
+ item.prev.next = item.next;
243
+ else if (this.head === item)
244
+ this.head = item.next;
245
+ else
246
+ throw new Error("item doesn't belong to list");
247
+ if (item.next !== null)
248
+ item.next.prev = item.prev;
249
+ else if (this.tail === item)
250
+ this.tail = item.prev;
251
+ else
252
+ throw new Error("item doesn't belong to list");
253
+ item.prev = null;
254
+ item.next = null;
255
+ return item;
256
+ }
257
+ push(data) {
258
+ this.insert(createItem(data), null);
259
+ }
260
+ pop() {
261
+ if (this.tail === null)
262
+ return null;
263
+ return this.remove(this.tail);
264
+ }
265
+ unshift(data) {
266
+ this.prependData(data);
267
+ }
268
+ shift() {
269
+ if (this.head === null)
270
+ return null;
271
+ return this.remove(this.head);
272
+ }
273
+ prependList(list) {
274
+ return this.insertList(list, this.head);
275
+ }
276
+ appendList(list) {
277
+ return this.insertList(list, null);
278
+ }
279
+ insertList(list, before = null) {
280
+ if (list.head === null)
281
+ return this;
282
+ if (before !== null) {
283
+ this.updateCursors(before.prev, list.tail, before, list.head);
284
+ if (before.prev !== null) {
285
+ before.prev.next = list.head;
286
+ list.head.prev = before.prev;
287
+ } else {
288
+ this.head = list.head;
289
+ }
290
+ before.prev = list.tail;
291
+ list.tail.next = before;
292
+ } else {
293
+ this.updateCursors(this.tail, list.tail, null, list.head);
294
+ if (this.tail !== null) {
295
+ this.tail.next = list.head;
296
+ list.head.prev = this.tail;
297
+ } else {
298
+ this.head = list.head;
299
+ }
300
+ this.tail = list.tail;
301
+ }
302
+ list.head = null;
303
+ list.tail = null;
304
+ return this;
305
+ }
306
+ replace(oldItem, newItemOrList) {
307
+ if (newItemOrList instanceof CssList) {
308
+ this.insertList(newItemOrList, oldItem);
309
+ this.remove(oldItem);
310
+ } else {
311
+ this.insert(newItemOrList, oldItem);
312
+ this.remove(oldItem);
313
+ }
314
+ }
315
+ }
316
+ function makeList() {
317
+ return new CssList;
318
+ }
319
+
320
+ // src/parse/clone.ts
321
+ function clone(node) {
322
+ return cloneAny(node);
323
+ }
324
+ function cloneAny(value) {
325
+ if (value === null || typeof value !== "object")
326
+ return value;
327
+ if (value instanceof CssList) {
328
+ const out2 = new CssList;
329
+ for (const child of value)
330
+ out2.appendData(cloneAny(child));
331
+ return out2;
332
+ }
333
+ if (Array.isArray(value))
334
+ return value.map(cloneAny);
335
+ if ("type" in value && typeof value.type === "string") {
336
+ const out2 = { type: value.type };
337
+ for (const k of Object.keys(value)) {
338
+ if (k === "type")
339
+ continue;
340
+ out2[k] = cloneAny(value[k]);
341
+ }
342
+ return out2;
343
+ }
344
+ const out = {};
345
+ for (const k of Object.keys(value))
346
+ out[k] = cloneAny(value[k]);
347
+ return out;
348
+ }
349
+ // src/parse/generator.ts
350
+ function generate(node) {
351
+ switch (node.type) {
352
+ case "StyleSheet":
353
+ return joinChildren(node.children, "");
354
+ case "Rule":
355
+ return `${generate(node.prelude)}{${generate(node.block)}}`;
356
+ case "Block":
357
+ return joinBlockChildren(node.children);
358
+ case "Atrule": {
359
+ let out = `@${node.name}`;
360
+ if (node.prelude) {
361
+ const p = generate(node.prelude);
362
+ if (p)
363
+ out += ` ${p}`;
364
+ }
365
+ if (node.block) {
366
+ out += `{${generate(node.block)}}`;
367
+ } else {
368
+ out += ";";
369
+ }
370
+ return out;
371
+ }
372
+ case "AtrulePrelude":
373
+ return joinChildren(node.children, "");
374
+ case "SelectorList":
375
+ return joinChildren(node.children, ",");
376
+ case "Selector":
377
+ return joinChildren(node.children, "");
378
+ case "TypeSelector":
379
+ return node.name;
380
+ case "IdSelector":
381
+ return `#${node.name}`;
382
+ case "ClassSelector":
383
+ return `.${node.name}`;
384
+ case "NestingSelector":
385
+ return "&";
386
+ case "AttributeSelector": {
387
+ let out = `[${node.name.name}`;
388
+ if (node.matcher && node.value) {
389
+ out += node.matcher;
390
+ if (node.value.type === "String")
391
+ out += `"${escapeStringContent(node.value.value)}"`;
392
+ else
393
+ out += node.value.name;
394
+ }
395
+ if (node.flags)
396
+ out += ` ${node.flags}`;
397
+ out += "]";
398
+ return out;
399
+ }
400
+ case "PseudoClassSelector":
401
+ return node.children ? `:${node.name}(${joinChildren(node.children, "")})` : `:${node.name}`;
402
+ case "PseudoElementSelector":
403
+ return node.children ? `::${node.name}(${joinChildren(node.children, "")})` : `::${node.name}`;
404
+ case "Combinator":
405
+ return node.name === " " ? " " : node.name;
406
+ case "Declaration":
407
+ return `${node.property}:${generate(node.value)}${node.important ? "!important" : ""}`;
408
+ case "DeclarationList":
409
+ return joinChildren(node.children, ";");
410
+ case "Value":
411
+ return joinChildren(node.children, "");
412
+ case "Identifier":
413
+ return node.name;
414
+ case "Number":
415
+ return node.value;
416
+ case "Percentage":
417
+ return `${node.value}%`;
418
+ case "Dimension":
419
+ return node.value + node.unit;
420
+ case "String":
421
+ return `"${escapeStringContent(node.value)}"`;
422
+ case "Url":
423
+ return /[\s"'()\\\u0000-\u001F\u007F]/.test(node.value) ? `url("${escapeStringContent(node.value)}")` : `url(${node.value})`;
424
+ case "Hash":
425
+ return `#${node.name}`;
426
+ case "Operator":
427
+ return node.value;
428
+ case "Function":
429
+ return `${node.name}(${joinChildren(node.children, "")})`;
430
+ case "Parentheses":
431
+ return `(${joinChildren(node.children, "")})`;
432
+ case "Brackets":
433
+ return `[${joinChildren(node.children, "")}]`;
434
+ case "Raw":
435
+ return node.value;
436
+ case "Comment":
437
+ return node.value.startsWith("!") ? `/*${node.value}*/` : "";
438
+ case "WhiteSpace":
439
+ return " ";
440
+ case "CDO":
441
+ return "<!--";
442
+ case "CDC":
443
+ return "-->";
444
+ case "AnPlusB": {
445
+ const a = node.a ?? "";
446
+ const b = node.b ?? "";
447
+ if (a && b) {
448
+ const bn = Number(b);
449
+ return `${a === "1" ? "" : a === "-1" ? "-" : a}n${bn >= 0 ? `+${b}` : b}`;
450
+ }
451
+ if (a)
452
+ return `${a === "1" ? "" : a === "-1" ? "-" : a}n`;
453
+ return b;
454
+ }
455
+ case "Ratio":
456
+ return `${node.left.value}/${node.right.value}`;
457
+ case "UnicodeRange":
458
+ return node.value;
459
+ case "Nth":
460
+ return node.selector ? `${generate(node.nth)} of ${generate(node.selector)}` : generate(node.nth);
461
+ case "MediaQueryList":
462
+ return joinChildren(node.children, ",");
463
+ case "MediaQuery":
464
+ return joinChildren(node.children, "");
465
+ case "MediaFeature": {
466
+ let out = `(${node.name}`;
467
+ if (node.value)
468
+ out += `:${generate(node.value)}`;
469
+ out += ")";
470
+ return out;
471
+ }
472
+ }
473
+ return "";
474
+ }
475
+ function joinChildren(list, separator) {
476
+ let out = "";
477
+ let first = true;
478
+ let prev = null;
479
+ let cur = list.head;
480
+ while (cur != null) {
481
+ const child = cur.data;
482
+ if (child.type === "WhiteSpace") {
483
+ const nextNode = cur.next ? cur.next.data : null;
484
+ if (isCompactOperator(prev) || isCompactOperator(nextNode)) {
485
+ cur = cur.next;
486
+ continue;
487
+ }
488
+ }
489
+ const text = generate(child);
490
+ if (!text) {
491
+ cur = cur.next;
492
+ continue;
493
+ }
494
+ if (!first && separator && !isStructuralSeparator(prev))
495
+ out += separator;
496
+ first = false;
497
+ out += text;
498
+ prev = child;
499
+ cur = cur.next;
500
+ }
501
+ return out;
502
+ }
503
+ function joinBlockChildren(list) {
504
+ let out = "";
505
+ let prev = null;
506
+ let cur = list.head;
507
+ while (cur != null) {
508
+ const child = cur.data;
509
+ const text = generate(child);
510
+ if (!text) {
511
+ cur = cur.next;
512
+ continue;
513
+ }
514
+ if (prev && needsSemicolon(prev, child))
515
+ out += ";";
516
+ out += text;
517
+ prev = child;
518
+ cur = cur.next;
519
+ }
520
+ return out;
521
+ }
522
+ function needsSemicolon(prev, next) {
523
+ return prev.type === "Declaration" && next.type !== "Comment";
524
+ }
525
+ function isCompactOperator(node) {
526
+ if (!node || node.type !== "Operator")
527
+ return false;
528
+ const v = node.value;
529
+ return v === ":" || v === "," || v === "/";
530
+ }
531
+ function isStructuralSeparator(node) {
532
+ if (!node)
533
+ return false;
534
+ return node.type === "Operator" || node.type === "Combinator";
535
+ }
536
+ function escapeStringContent(s) {
537
+ let out = "";
538
+ for (let i = 0;i < s.length; i++) {
539
+ const ch = s.charCodeAt(i);
540
+ if (ch === 92) {
541
+ out += "\\\\";
542
+ } else if (ch === 34) {
543
+ out += "\\\"";
544
+ } else if (ch < 32 || ch === 127) {
545
+ const hex = ch.toString(16);
546
+ const next = i + 1 < s.length ? s.charCodeAt(i + 1) : -1;
547
+ const needsSpace = next === 32 || next === 9 || next === 10 || next === 12 || next === 13 || next >= 48 && next <= 57 || next >= 65 && next <= 70 || next >= 97 && next <= 102;
548
+ out += `\\${hex}${needsSpace ? " " : ""}`;
549
+ } else {
550
+ out += s[i];
551
+ }
552
+ }
553
+ return out;
554
+ }
555
+ // src/parse/tokenizer.ts
556
+ var TokenType;
557
+ ((TokenType2) => {
558
+ TokenType2[TokenType2["EOF"] = 0] = "EOF";
559
+ TokenType2[TokenType2["Ident"] = 1] = "Ident";
560
+ TokenType2[TokenType2["Function"] = 2] = "Function";
561
+ TokenType2[TokenType2["AtKeyword"] = 3] = "AtKeyword";
562
+ TokenType2[TokenType2["Hash"] = 4] = "Hash";
563
+ TokenType2[TokenType2["String"] = 5] = "String";
564
+ TokenType2[TokenType2["BadString"] = 6] = "BadString";
565
+ TokenType2[TokenType2["Url"] = 7] = "Url";
566
+ TokenType2[TokenType2["BadUrl"] = 8] = "BadUrl";
567
+ TokenType2[TokenType2["Delim"] = 9] = "Delim";
568
+ TokenType2[TokenType2["Number"] = 10] = "Number";
569
+ TokenType2[TokenType2["Percentage"] = 11] = "Percentage";
570
+ TokenType2[TokenType2["Dimension"] = 12] = "Dimension";
571
+ TokenType2[TokenType2["WhiteSpace"] = 13] = "WhiteSpace";
572
+ TokenType2[TokenType2["CDO"] = 14] = "CDO";
573
+ TokenType2[TokenType2["CDC"] = 15] = "CDC";
574
+ TokenType2[TokenType2["Colon"] = 16] = "Colon";
575
+ TokenType2[TokenType2["Semicolon"] = 17] = "Semicolon";
576
+ TokenType2[TokenType2["Comma"] = 18] = "Comma";
577
+ TokenType2[TokenType2["LeftSquareBracket"] = 19] = "LeftSquareBracket";
578
+ TokenType2[TokenType2["RightSquareBracket"] = 20] = "RightSquareBracket";
579
+ TokenType2[TokenType2["LeftParenthesis"] = 21] = "LeftParenthesis";
580
+ TokenType2[TokenType2["RightParenthesis"] = 22] = "RightParenthesis";
581
+ TokenType2[TokenType2["LeftCurlyBracket"] = 23] = "LeftCurlyBracket";
582
+ TokenType2[TokenType2["RightCurlyBracket"] = 24] = "RightCurlyBracket";
583
+ TokenType2[TokenType2["Comment"] = 25] = "Comment";
584
+ })(TokenType ||= {});
585
+ var REPLACEMENT = 65533;
586
+ var CHAR_CLASS = (() => {
587
+ const t = new Uint8Array(128);
588
+ for (let c = 0;c < 128; c++) {
589
+ let bits = 0;
590
+ if (c === 32 || c === 9 || c === 10 || c === 12 || c === 13)
591
+ bits |= 1;
592
+ if (c >= 48 && c <= 57)
593
+ bits |= 2;
594
+ if (c >= 48 && c <= 57 || c >= 65 && c <= 70 || c >= 97 && c <= 102)
595
+ bits |= 4;
596
+ if (c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95)
597
+ bits |= 8;
598
+ if (c === 10 || c === 12 || c === 13)
599
+ bits |= 16;
600
+ t[c] = bits;
601
+ }
602
+ return t;
603
+ })();
604
+ function isDigit(code) {
605
+ return code < 128 && (CHAR_CLASS[code] & 2) !== 0;
606
+ }
607
+ function isHexDigit(code) {
608
+ return code < 128 && (CHAR_CLASS[code] & 4) !== 0;
609
+ }
610
+ function isNameStart(code) {
611
+ return code >= 128 || code < 128 && (CHAR_CLASS[code] & 8) !== 0;
612
+ }
613
+ function isName(code) {
614
+ return code === 45 || code >= 128 || code < 128 && (CHAR_CLASS[code] & (2 | 8)) !== 0;
615
+ }
616
+ function isNonPrintable(code) {
617
+ return code >= 0 && code <= 8 || code === 11 || code >= 14 && code <= 31 || code === 127;
618
+ }
619
+ function isNewline(code) {
620
+ return code < 128 && (CHAR_CLASS[code] & 16) !== 0;
621
+ }
622
+ function isWhitespace(code) {
623
+ return code < 128 && (CHAR_CLASS[code] & 1) !== 0;
624
+ }
625
+ function isValidEscape(c1, c2) {
626
+ if (c1 !== 92)
627
+ return false;
628
+ if (isNewline(c2))
629
+ return false;
630
+ return true;
631
+ }
632
+ function startsIdentifier(c1, c2, c3) {
633
+ if (c1 === 45) {
634
+ return isNameStart(c2) || c2 === 45 || isValidEscape(c2, c3);
635
+ }
636
+ if (isNameStart(c1))
637
+ return true;
638
+ if (c1 === 92)
639
+ return isValidEscape(c1, c2);
640
+ return false;
641
+ }
642
+ function startsNumber(c1, c2, c3) {
643
+ if (c1 === 43 || c1 === 45) {
644
+ if (isDigit(c2))
645
+ return true;
646
+ if (c2 === 46 && isDigit(c3))
647
+ return true;
648
+ return false;
649
+ }
650
+ if (c1 === 46)
651
+ return isDigit(c2);
652
+ return isDigit(c1);
653
+ }
654
+
655
+ class Tokenizer {
656
+ source;
657
+ offset = 0;
658
+ types;
659
+ starts;
660
+ ends;
661
+ count = 0;
662
+ _tokens = null;
663
+ _lineStarts = null;
664
+ constructor(source) {
665
+ this.source = source;
666
+ const cap = Math.max(64, Math.ceil(source.length / 3));
667
+ this.types = new Uint8Array(cap);
668
+ this.starts = new Uint32Array(cap);
669
+ this.ends = new Uint32Array(cap);
670
+ this.tokenize();
671
+ }
672
+ get lineStarts() {
673
+ if (this._lineStarts == null)
674
+ this._lineStarts = buildLineStarts(this.source);
675
+ return this._lineStarts;
676
+ }
677
+ get tokens() {
678
+ if (this._tokens != null)
679
+ return this._tokens;
680
+ const out = Array.from({ length: this.count });
681
+ for (let i = 0;i < this.count; i++)
682
+ out[i] = { type: this.types[i], start: this.starts[i], end: this.ends[i] };
683
+ this._tokens = out;
684
+ return out;
685
+ }
686
+ addToken(type, start, end) {
687
+ if (this.count >= this.types.length)
688
+ this.grow();
689
+ this.types[this.count] = type;
690
+ this.starts[this.count] = start;
691
+ this.ends[this.count] = end;
692
+ this.count++;
693
+ }
694
+ grow() {
695
+ const oldLen = this.types.length;
696
+ const newLen = oldLen * 2;
697
+ const t = new Uint8Array(newLen);
698
+ t.set(this.types);
699
+ this.types = t;
700
+ const s = new Uint32Array(newLen);
701
+ s.set(this.starts);
702
+ this.starts = s;
703
+ const e = new Uint32Array(newLen);
704
+ e.set(this.ends);
705
+ this.ends = e;
706
+ }
707
+ tokenize() {
708
+ const src = this.source;
709
+ let i = 0;
710
+ const len = src.length;
711
+ while (i < len) {
712
+ const c1 = src.charCodeAt(i);
713
+ if (c1 === 47 && src.charCodeAt(i + 1) === 42) {
714
+ const start = i;
715
+ i += 2;
716
+ while (i < len && !(src.charCodeAt(i) === 42 && src.charCodeAt(i + 1) === 47))
717
+ i++;
718
+ i = i < len ? i + 2 : len;
719
+ this.addToken(25 /* Comment */, start, i);
720
+ continue;
721
+ }
722
+ if (isWhitespace(c1)) {
723
+ const start = i;
724
+ while (i < len && isWhitespace(src.charCodeAt(i)))
725
+ i++;
726
+ this.addToken(13 /* WhiteSpace */, start, i);
727
+ continue;
728
+ }
729
+ if (c1 === 34 || c1 === 39) {
730
+ i = this.consumeString(c1, i);
731
+ continue;
732
+ }
733
+ if (c1 === 35) {
734
+ if (i + 1 < len && (isName(src.charCodeAt(i + 1)) || isValidEscape(src.charCodeAt(i + 1), src.charCodeAt(i + 2)))) {
735
+ const start = i;
736
+ i++;
737
+ i = this.consumeName(i);
738
+ this.addToken(4 /* Hash */, start, i);
739
+ continue;
740
+ }
741
+ this.addToken(9 /* Delim */, i, i + 1);
742
+ i++;
743
+ continue;
744
+ }
745
+ switch (c1) {
746
+ case 40:
747
+ this.addToken(21 /* LeftParenthesis */, i, i + 1);
748
+ i++;
749
+ continue;
750
+ case 41:
751
+ this.addToken(22 /* RightParenthesis */, i, i + 1);
752
+ i++;
753
+ continue;
754
+ case 91:
755
+ this.addToken(19 /* LeftSquareBracket */, i, i + 1);
756
+ i++;
757
+ continue;
758
+ case 93:
759
+ this.addToken(20 /* RightSquareBracket */, i, i + 1);
760
+ i++;
761
+ continue;
762
+ case 123:
763
+ this.addToken(23 /* LeftCurlyBracket */, i, i + 1);
764
+ i++;
765
+ continue;
766
+ case 125:
767
+ this.addToken(24 /* RightCurlyBracket */, i, i + 1);
768
+ i++;
769
+ continue;
770
+ case 44:
771
+ this.addToken(18 /* Comma */, i, i + 1);
772
+ i++;
773
+ continue;
774
+ case 58:
775
+ this.addToken(16 /* Colon */, i, i + 1);
776
+ i++;
777
+ continue;
778
+ case 59:
779
+ this.addToken(17 /* Semicolon */, i, i + 1);
780
+ i++;
781
+ continue;
782
+ }
783
+ if (c1 === 60 && src.startsWith("!--", i + 1)) {
784
+ this.addToken(14 /* CDO */, i, i + 4);
785
+ i += 4;
786
+ continue;
787
+ }
788
+ if (c1 === 45 && src.startsWith("->", i + 1)) {
789
+ this.addToken(15 /* CDC */, i, i + 3);
790
+ i += 3;
791
+ continue;
792
+ }
793
+ if (c1 === 64) {
794
+ const c22 = src.charCodeAt(i + 1);
795
+ const c32 = src.charCodeAt(i + 2);
796
+ const c4 = src.charCodeAt(i + 3);
797
+ if (startsIdentifier(c22, c32, c4)) {
798
+ const start = i;
799
+ i++;
800
+ i = this.consumeName(i);
801
+ this.addToken(3 /* AtKeyword */, start, i);
802
+ continue;
803
+ }
804
+ this.addToken(9 /* Delim */, i, i + 1);
805
+ i++;
806
+ continue;
807
+ }
808
+ const c2 = src.charCodeAt(i + 1);
809
+ const c3 = src.charCodeAt(i + 2);
810
+ if (startsNumber(c1, c2, c3)) {
811
+ i = this.consumeNumeric(i);
812
+ continue;
813
+ }
814
+ if (startsIdentifier(c1, c2, c3)) {
815
+ i = this.consumeIdentLike(i);
816
+ continue;
817
+ }
818
+ if (c1 === 92) {
819
+ if (isValidEscape(c1, c2)) {
820
+ i = this.consumeIdentLike(i);
821
+ continue;
822
+ }
823
+ this.addToken(9 /* Delim */, i, i + 1);
824
+ i++;
825
+ continue;
826
+ }
827
+ this.addToken(9 /* Delim */, i, i + 1);
828
+ i++;
829
+ }
830
+ this.addToken(0 /* EOF */, len, len);
831
+ }
832
+ consumeString(quote, start) {
833
+ const src = this.source;
834
+ const len = src.length;
835
+ let i = start + 1;
836
+ while (i < len) {
837
+ const c = src.charCodeAt(i);
838
+ if (c === quote) {
839
+ i++;
840
+ this.addToken(5 /* String */, start, i);
841
+ return i;
842
+ }
843
+ if (isNewline(c)) {
844
+ this.addToken(6 /* BadString */, start, i);
845
+ return i;
846
+ }
847
+ if (c === 92) {
848
+ const c2 = src.charCodeAt(i + 1);
849
+ if (isNewline(c2)) {
850
+ i += 2;
851
+ continue;
852
+ }
853
+ if (i + 1 < len) {
854
+ i = this.consumeEscapeSkip(i + 1);
855
+ continue;
856
+ }
857
+ }
858
+ i++;
859
+ }
860
+ this.addToken(5 /* String */, start, i);
861
+ return i;
862
+ }
863
+ consumeEscapeSkip(i) {
864
+ const src = this.source;
865
+ if (i >= src.length)
866
+ return i;
867
+ const c = src.charCodeAt(i);
868
+ if (isHexDigit(c)) {
869
+ let n = 1;
870
+ i++;
871
+ while (n < 6 && i < src.length && isHexDigit(src.charCodeAt(i))) {
872
+ i++;
873
+ n++;
874
+ }
875
+ if (i < src.length && isWhitespace(src.charCodeAt(i)))
876
+ i++;
877
+ return i;
878
+ }
879
+ return i + 1;
880
+ }
881
+ consumeName(start) {
882
+ const src = this.source;
883
+ const len = src.length;
884
+ let i = start;
885
+ while (i < len) {
886
+ const c = src.charCodeAt(i);
887
+ if (c < 128 && (CHAR_CLASS[c] & (2 | 8)) !== 0) {
888
+ i++;
889
+ continue;
890
+ }
891
+ if (c === 45) {
892
+ i++;
893
+ continue;
894
+ }
895
+ if (c >= 128) {
896
+ i++;
897
+ continue;
898
+ }
899
+ if (c === 92 && isValidEscape(c, src.charCodeAt(i + 1))) {
900
+ i = this.consumeEscapeSkip(i + 1);
901
+ continue;
902
+ }
903
+ break;
904
+ }
905
+ return i;
906
+ }
907
+ consumeNumber(start) {
908
+ const src = this.source;
909
+ let i = start;
910
+ if (src.charCodeAt(i) === 43 || src.charCodeAt(i) === 45)
911
+ i++;
912
+ while (i < src.length && isDigit(src.charCodeAt(i)))
913
+ i++;
914
+ if (src.charCodeAt(i) === 46 && isDigit(src.charCodeAt(i + 1))) {
915
+ i += 2;
916
+ while (i < src.length && isDigit(src.charCodeAt(i)))
917
+ i++;
918
+ }
919
+ const eC = src.charCodeAt(i);
920
+ if (eC === 69 || eC === 101) {
921
+ const next = src.charCodeAt(i + 1);
922
+ const next2 = src.charCodeAt(i + 2);
923
+ if (isDigit(next)) {
924
+ i += 2;
925
+ while (i < src.length && isDigit(src.charCodeAt(i)))
926
+ i++;
927
+ } else if ((next === 43 || next === 45) && isDigit(next2)) {
928
+ i += 3;
929
+ while (i < src.length && isDigit(src.charCodeAt(i)))
930
+ i++;
931
+ }
932
+ }
933
+ return i;
934
+ }
935
+ consumeNumeric(start) {
936
+ const src = this.source;
937
+ const numEnd = this.consumeNumber(start);
938
+ const c1 = src.charCodeAt(numEnd);
939
+ const c2 = src.charCodeAt(numEnd + 1);
940
+ const c3 = src.charCodeAt(numEnd + 2);
941
+ if (startsIdentifier(c1, c2, c3)) {
942
+ const end = this.consumeName(numEnd);
943
+ this.addToken(12 /* Dimension */, start, end);
944
+ return end;
945
+ }
946
+ if (c1 === 37) {
947
+ this.addToken(11 /* Percentage */, start, numEnd + 1);
948
+ return numEnd + 1;
949
+ }
950
+ this.addToken(10 /* Number */, start, numEnd);
951
+ return numEnd;
952
+ }
953
+ consumeIdentLike(start) {
954
+ const src = this.source;
955
+ const nameEnd = this.consumeName(start);
956
+ const c = src.charCodeAt(nameEnd);
957
+ if (c === 40 && nameEnd - start === 3) {
958
+ const c0 = src.charCodeAt(start) | 32;
959
+ const c1 = src.charCodeAt(start + 1) | 32;
960
+ const c2 = src.charCodeAt(start + 2) | 32;
961
+ if (c0 === 117 && c1 === 114 && c2 === 108) {
962
+ let i = nameEnd + 1;
963
+ while (i < src.length && isWhitespace(src.charCodeAt(i)))
964
+ i++;
965
+ const next = src.charCodeAt(i);
966
+ if (next === 34 || next === 39) {
967
+ this.addToken(2 /* Function */, start, nameEnd + 1);
968
+ return nameEnd + 1;
969
+ }
970
+ return this.consumeUrl(start, nameEnd);
971
+ }
972
+ }
973
+ if (c === 40) {
974
+ this.addToken(2 /* Function */, start, nameEnd + 1);
975
+ return nameEnd + 1;
976
+ }
977
+ this.addToken(1 /* Ident */, start, nameEnd);
978
+ return nameEnd;
979
+ }
980
+ consumeUrl(start, nameEnd) {
981
+ const src = this.source;
982
+ const len = src.length;
983
+ let i = nameEnd + 1;
984
+ while (i < len && isWhitespace(src.charCodeAt(i)))
985
+ i++;
986
+ while (i < len) {
987
+ const c = src.charCodeAt(i);
988
+ if (c === 41) {
989
+ i++;
990
+ this.addToken(7 /* Url */, start, i);
991
+ return i;
992
+ }
993
+ if (isWhitespace(c)) {
994
+ const wsStart = i;
995
+ while (i < len && isWhitespace(src.charCodeAt(i)))
996
+ i++;
997
+ if (i >= len) {
998
+ this.addToken(7 /* Url */, start, i);
999
+ return i;
1000
+ }
1001
+ if (src.charCodeAt(i) === 41) {
1002
+ i++;
1003
+ this.addToken(7 /* Url */, start, i);
1004
+ return i;
1005
+ }
1006
+ return this.consumeBadUrl(start, wsStart);
1007
+ }
1008
+ if (c === 34 || c === 39 || c === 40 || isNonPrintable(c)) {
1009
+ return this.consumeBadUrl(start, i);
1010
+ }
1011
+ if (c === 92) {
1012
+ if (isValidEscape(c, src.charCodeAt(i + 1))) {
1013
+ i = this.consumeEscapeSkip(i + 1);
1014
+ continue;
1015
+ }
1016
+ return this.consumeBadUrl(start, i);
1017
+ }
1018
+ i++;
1019
+ }
1020
+ this.addToken(7 /* Url */, start, i);
1021
+ return i;
1022
+ }
1023
+ consumeBadUrl(start, from) {
1024
+ const src = this.source;
1025
+ let i = from;
1026
+ while (i < src.length) {
1027
+ const c = src.charCodeAt(i);
1028
+ if (c === 41) {
1029
+ i++;
1030
+ break;
1031
+ }
1032
+ if (c === 92 && isValidEscape(c, src.charCodeAt(i + 1))) {
1033
+ i = this.consumeEscapeSkip(i + 1);
1034
+ continue;
1035
+ }
1036
+ i++;
1037
+ }
1038
+ this.addToken(8 /* BadUrl */, start, i);
1039
+ return i;
1040
+ }
1041
+ locate(offset) {
1042
+ const ls = this.lineStarts;
1043
+ let lo = 0;
1044
+ let hi = ls.length - 1;
1045
+ while (lo < hi) {
1046
+ const mid = lo + hi + 1 >> 1;
1047
+ if (ls[mid] <= offset)
1048
+ lo = mid;
1049
+ else
1050
+ hi = mid - 1;
1051
+ }
1052
+ const lineStart = ls[lo];
1053
+ return { line: lo + 1, column: offset - lineStart + 1 };
1054
+ }
1055
+ }
1056
+ function buildLineStarts(source) {
1057
+ const out = [0];
1058
+ const len = source.length;
1059
+ for (let i = 0;i < len; i++) {
1060
+ const c = source.charCodeAt(i);
1061
+ if (c === 10) {
1062
+ out.push(i + 1);
1063
+ } else if (c === 13) {
1064
+ if (source.charCodeAt(i + 1) !== 10)
1065
+ out.push(i + 1);
1066
+ }
1067
+ }
1068
+ return out;
1069
+ }
1070
+ function decodeString(source, start, end) {
1071
+ for (let k = start;k < end; k++) {
1072
+ if (source.charCodeAt(k) === 92)
1073
+ return decodeStringSlow(source, start, end, k);
1074
+ }
1075
+ return source.slice(start, end);
1076
+ }
1077
+ function decodeStringSlow(source, start, end, firstEscape) {
1078
+ let out = source.slice(start, firstEscape);
1079
+ let i = firstEscape;
1080
+ while (i < end) {
1081
+ const c = source.charCodeAt(i);
1082
+ if (c !== 92) {
1083
+ out += source[i];
1084
+ i++;
1085
+ continue;
1086
+ }
1087
+ if (i + 1 >= end) {
1088
+ i++;
1089
+ continue;
1090
+ }
1091
+ const next = source.charCodeAt(i + 1);
1092
+ if (next === 10) {
1093
+ i += 2;
1094
+ continue;
1095
+ }
1096
+ if (next === 13) {
1097
+ i += source.charCodeAt(i + 2) === 10 ? 3 : 2;
1098
+ continue;
1099
+ }
1100
+ if (isHexDigit(next)) {
1101
+ let j = i + 1;
1102
+ let hex = "";
1103
+ while (hex.length < 6 && j < end && isHexDigit(source.charCodeAt(j))) {
1104
+ hex += source[j];
1105
+ j++;
1106
+ }
1107
+ const code = Number.parseInt(hex, 16);
1108
+ if (j < end && isWhitespace(source.charCodeAt(j)))
1109
+ j++;
1110
+ out += code === 0 || code >= 55296 && code <= 57343 || code > 1114111 ? String.fromCodePoint(REPLACEMENT) : String.fromCodePoint(code);
1111
+ i = j;
1112
+ continue;
1113
+ }
1114
+ out += source[i + 1];
1115
+ i += 2;
1116
+ }
1117
+ return out;
1118
+ }
1119
+ function decodeName(source, start, end) {
1120
+ for (let k = start;k < end; k++) {
1121
+ if (source.charCodeAt(k) === 92)
1122
+ return decodeNameSlow(source, start, end, k);
1123
+ }
1124
+ return source.slice(start, end);
1125
+ }
1126
+ function decodeNameSlow(source, start, end, firstEscape) {
1127
+ let out = source.slice(start, firstEscape);
1128
+ let i = firstEscape;
1129
+ while (i < end) {
1130
+ const c = source.charCodeAt(i);
1131
+ if (c !== 92) {
1132
+ out += source[i];
1133
+ i++;
1134
+ continue;
1135
+ }
1136
+ let j = i + 1;
1137
+ let hex = "";
1138
+ while (hex.length < 6 && j < end && isHexDigit(source.charCodeAt(j))) {
1139
+ hex += source[j];
1140
+ j++;
1141
+ }
1142
+ if (hex.length > 0) {
1143
+ const code = Number.parseInt(hex, 16);
1144
+ if (j < end && isWhitespace(source.charCodeAt(j)))
1145
+ j++;
1146
+ out += code === 0 || code >= 55296 && code <= 57343 || code > 1114111 ? String.fromCodePoint(REPLACEMENT) : String.fromCodePoint(code);
1147
+ i = j;
1148
+ continue;
1149
+ }
1150
+ if (j < end) {
1151
+ out += source[j];
1152
+ i = j + 1;
1153
+ continue;
1154
+ }
1155
+ out += String.fromCodePoint(REPLACEMENT);
1156
+ i = j;
1157
+ }
1158
+ return out;
1159
+ }
1160
+
1161
+ // src/parse/parser/index.ts
1162
+ function makeState(source, options) {
1163
+ const tokenizer = new Tokenizer(source);
1164
+ return {
1165
+ source,
1166
+ types: tokenizer.types,
1167
+ starts: tokenizer.starts,
1168
+ ends: tokenizer.ends,
1169
+ count: tokenizer.count,
1170
+ end: tokenizer.count,
1171
+ pos: 0,
1172
+ positions: options.positions ?? false,
1173
+ filename: options.filename,
1174
+ parseValue: options.parseValue ?? true,
1175
+ parseAtrulePrelude: options.parseAtrulePrelude ?? true,
1176
+ parseCustomProperty: options.parseCustomProperty ?? false,
1177
+ parseRulePrelude: options.parseRulePrelude ?? true,
1178
+ onParseError: options.onParseError,
1179
+ tokenizer
1180
+ };
1181
+ }
1182
+ function peekType(s) {
1183
+ return s.pos < s.end ? s.types[s.pos] : 0 /* EOF */;
1184
+ }
1185
+ function peek(s) {
1186
+ const i = s.pos;
1187
+ if (i >= s.end)
1188
+ return { type: 0 /* EOF */, start: s.starts[i] ?? s.source.length, end: s.ends[i] ?? s.source.length };
1189
+ return { type: s.types[i], start: s.starts[i], end: s.ends[i] };
1190
+ }
1191
+ function consume(s) {
1192
+ const i = s.pos++;
1193
+ if (i >= s.end)
1194
+ return { type: 0 /* EOF */, start: s.starts[i] ?? s.source.length, end: s.ends[i] ?? s.source.length };
1195
+ return { type: s.types[i], start: s.starts[i], end: s.ends[i] };
1196
+ }
1197
+ function tokenSlice(s, t) {
1198
+ return s.source.slice(t.start, t.end);
1199
+ }
1200
+ function skipWhitespace(s) {
1201
+ const types = s.types;
1202
+ const end = s.end;
1203
+ while (s.pos < end) {
1204
+ const t = types[s.pos];
1205
+ if (t === 13 /* WhiteSpace */ || t === 25 /* Comment */)
1206
+ s.pos++;
1207
+ else
1208
+ break;
1209
+ }
1210
+ }
1211
+ function skipWhitespaceOnly(s) {
1212
+ const types = s.types;
1213
+ const end = s.end;
1214
+ while (s.pos < end && types[s.pos] === 13 /* WhiteSpace */)
1215
+ s.pos++;
1216
+ }
1217
+ function loc(s, startTok, endTok) {
1218
+ if (!s.positions)
1219
+ return null;
1220
+ const start = s.tokenizer.locate(startTok.start);
1221
+ const end = s.tokenizer.locate(endTok.end);
1222
+ return {
1223
+ source: s.filename ?? "<unknown>",
1224
+ start: { offset: startTok.start, line: start.line, column: start.column },
1225
+ end: { offset: endTok.end, line: end.line, column: end.column }
1226
+ };
1227
+ }
1228
+ function emptyLoc(s) {
1229
+ if (!s.positions)
1230
+ return null;
1231
+ const t = peek(s);
1232
+ const p = s.tokenizer.locate(t.start);
1233
+ return {
1234
+ source: s.filename ?? "<unknown>",
1235
+ start: { offset: t.start, line: p.line, column: p.column },
1236
+ end: { offset: t.start, line: p.line, column: p.column }
1237
+ };
1238
+ }
1239
+ function rawNode(value, start, end, s) {
1240
+ return { type: "Raw", value, loc: loc(s, start, end) };
1241
+ }
1242
+ function newList() {
1243
+ return new CssList;
1244
+ }
1245
+ function reportError(s, message, at, fallback) {
1246
+ if (s.onParseError) {
1247
+ const { line, column } = s.tokenizer.locate(at.start);
1248
+ const err = new SyntaxError(`${s.filename ?? "<input>"}:${line}:${column}: ${message}`);
1249
+ err.line = line;
1250
+ err.column = column;
1251
+ err.offset = at.start;
1252
+ s.onParseError(err, fallback);
1253
+ }
1254
+ return fallback;
1255
+ }
1256
+ function parse(source, options = {}) {
1257
+ const s = makeState(source, options);
1258
+ const ctx = options.context ?? "stylesheet";
1259
+ switch (ctx) {
1260
+ case "stylesheet":
1261
+ return parseStyleSheet(s);
1262
+ case "atrule":
1263
+ return parseAtrule(s) ?? makeEmptyStyleSheet(s);
1264
+ case "atrulePrelude":
1265
+ return parseAtrulePreludeContext(s);
1266
+ case "mediaQuery":
1267
+ case "mediaQueryList":
1268
+ return parseRawAsValue(s);
1269
+ case "rule":
1270
+ return parseRule(s);
1271
+ case "selectorList":
1272
+ return parseSelectorList(s);
1273
+ case "selector":
1274
+ return parseSelector(s);
1275
+ case "block":
1276
+ return parseBlock(s);
1277
+ case "declarationList":
1278
+ return parseDeclarationList(s);
1279
+ case "declaration":
1280
+ return parseDeclaration(s) ?? makeEmptyStyleSheet(s);
1281
+ case "value":
1282
+ return parseValue(s);
1283
+ case "raw":
1284
+ return parseRawAsValue(s);
1285
+ default:
1286
+ return parseStyleSheet(s);
1287
+ }
1288
+ }
1289
+ function makeEmptyStyleSheet(s) {
1290
+ return { type: "StyleSheet", children: newList(), loc: emptyLoc(s) };
1291
+ }
1292
+ function parseRawAsValue(s) {
1293
+ const start = peek(s);
1294
+ let end = start;
1295
+ while (peekType(s) !== 0 /* EOF */) {
1296
+ end = consume(s);
1297
+ }
1298
+ return { type: "Raw", value: s.source.slice(start.start, end.end), loc: loc(s, start, end) };
1299
+ }
1300
+ function parseStyleSheet(s) {
1301
+ const startTok = peek(s);
1302
+ const children = newList();
1303
+ const types = s.types;
1304
+ const end = s.end;
1305
+ while (s.pos < end) {
1306
+ const t = types[s.pos];
1307
+ if (t === 13 /* WhiteSpace */) {
1308
+ s.pos++;
1309
+ continue;
1310
+ }
1311
+ if (t === 25 /* Comment */) {
1312
+ const tok = { type: 25 /* Comment */, start: s.starts[s.pos], end: s.ends[s.pos] };
1313
+ const node = makeComment(s, tok);
1314
+ s.pos++;
1315
+ children.appendData(node);
1316
+ continue;
1317
+ }
1318
+ if (t === 0 /* EOF */)
1319
+ break;
1320
+ if (t === 14 /* CDO */ || t === 15 /* CDC */) {
1321
+ s.pos++;
1322
+ continue;
1323
+ }
1324
+ if (t === 3 /* AtKeyword */) {
1325
+ const at = parseAtrule(s);
1326
+ if (at)
1327
+ children.appendData(at);
1328
+ continue;
1329
+ }
1330
+ if (t === 24 /* RightCurlyBracket */) {
1331
+ s.pos++;
1332
+ continue;
1333
+ }
1334
+ const before = s.pos;
1335
+ const r = parseRule(s);
1336
+ children.appendData(r);
1337
+ if (s.pos === before)
1338
+ s.pos++;
1339
+ }
1340
+ const lastIdx = s.end - 1;
1341
+ const endTok = lastIdx >= 0 ? { type: s.types[lastIdx], start: s.starts[lastIdx], end: s.ends[lastIdx] } : { type: 0 /* EOF */, start: 0, end: 0 };
1342
+ return { type: "StyleSheet", children, loc: loc(s, startTok, endTok) };
1343
+ }
1344
+ function makeComment(s, t) {
1345
+ return { type: "Comment", value: s.source.slice(t.start + 2, t.end - 2), loc: loc(s, t, t) };
1346
+ }
1347
+ function parseAtrule(s) {
1348
+ const startTok = peek(s);
1349
+ if (startTok.type !== 3 /* AtKeyword */)
1350
+ return null;
1351
+ s.pos++;
1352
+ const name = lowerIfNeeded(s.source, startTok.start + 1, startTok.end);
1353
+ skipWhitespace(s);
1354
+ const preludeStartPos = s.pos;
1355
+ const preludeStartTok = peek(s);
1356
+ const types = s.types;
1357
+ const tend = s.end;
1358
+ let scanPos = preludeStartPos;
1359
+ let preludeEndPos = preludeStartPos;
1360
+ while (scanPos < tend) {
1361
+ const t = types[scanPos];
1362
+ if (t === 0 /* EOF */ || t === 17 /* Semicolon */ || t === 23 /* LeftCurlyBracket */)
1363
+ break;
1364
+ if (t !== 13 /* WhiteSpace */ && t !== 25 /* Comment */)
1365
+ preludeEndPos = scanPos + 1;
1366
+ scanPos++;
1367
+ }
1368
+ let prelude = null;
1369
+ if (preludeEndPos > preludeStartPos) {
1370
+ const preludeStartByte = s.starts[preludeStartPos];
1371
+ const preludeEndByte = s.ends[preludeEndPos - 1];
1372
+ const preludeEndTok = { type: types[preludeEndPos - 1], start: s.starts[preludeEndPos - 1], end: preludeEndByte };
1373
+ const raw = s.source.slice(preludeStartByte, preludeEndByte).trim();
1374
+ if (raw.length > 0) {
1375
+ if (s.parseAtrulePrelude) {
1376
+ try {
1377
+ const savedEnd = s.end;
1378
+ s.end = preludeEndPos;
1379
+ s.pos = preludeStartPos;
1380
+ const children = newList();
1381
+ while (peekType(s) !== 0 /* EOF */) {
1382
+ const node = parseValueChild(s);
1383
+ if (node)
1384
+ children.appendData(node);
1385
+ }
1386
+ promoteRatiosDeep(children);
1387
+ s.end = savedEnd;
1388
+ s.pos = scanPos;
1389
+ if (children.isEmpty)
1390
+ prelude = rawNode(raw, preludeStartTok, preludeEndTok, s);
1391
+ else
1392
+ prelude = { type: "AtrulePrelude", children, loc: null };
1393
+ } catch (err) {
1394
+ const fallback = rawNode(raw, preludeStartTok, preludeEndTok, s);
1395
+ reportError(s, `Failed to parse @${name} prelude: ${err.message}`, preludeStartTok, fallback);
1396
+ prelude = fallback;
1397
+ s.pos = scanPos;
1398
+ }
1399
+ } else {
1400
+ prelude = rawNode(raw, preludeStartTok, preludeEndTok, s);
1401
+ s.pos = scanPos;
1402
+ }
1403
+ } else {
1404
+ s.pos = scanPos;
1405
+ }
1406
+ } else {
1407
+ s.pos = scanPos;
1408
+ }
1409
+ let block = null;
1410
+ if (peekType(s) === 17 /* Semicolon */) {
1411
+ consume(s);
1412
+ } else if (peekType(s) === 23 /* LeftCurlyBracket */) {
1413
+ block = parseBlock(s, AT_RULES_WITH_NESTED_RULES.has(name));
1414
+ }
1415
+ return { type: "Atrule", name, prelude, block, loc: loc(s, startTok, peek(s)) };
1416
+ }
1417
+ var SELECTOR_LIST_PSEUDOS_PARSE = new Set([
1418
+ "is",
1419
+ "not",
1420
+ "where",
1421
+ "has",
1422
+ "matches",
1423
+ "-moz-any",
1424
+ "-webkit-any"
1425
+ ]);
1426
+ var AT_RULES_WITH_NESTED_RULES = new Set([
1427
+ "media",
1428
+ "supports",
1429
+ "document",
1430
+ "layer",
1431
+ "container",
1432
+ "scope",
1433
+ "starting-style",
1434
+ "-moz-document",
1435
+ "keyframes",
1436
+ "-webkit-keyframes",
1437
+ "-moz-keyframes",
1438
+ "-o-keyframes"
1439
+ ]);
1440
+ function parseAtrulePreludeContext(s) {
1441
+ const startTok = peek(s);
1442
+ const children = newList();
1443
+ while (peekType(s) !== 0 /* EOF */) {
1444
+ const t = peek(s);
1445
+ if (t.type === 13 /* WhiteSpace */) {
1446
+ s.pos++;
1447
+ continue;
1448
+ }
1449
+ const node = parseValueChild(s);
1450
+ if (node)
1451
+ children.appendData(node);
1452
+ }
1453
+ return { type: "AtrulePrelude", children, loc: loc(s, startTok, peek(s)) };
1454
+ }
1455
+ function parseRule(s) {
1456
+ const startTok = peek(s);
1457
+ let prelude;
1458
+ if (s.parseRulePrelude) {
1459
+ prelude = parseSelectorList(s);
1460
+ } else {
1461
+ const preludeStart = peek(s);
1462
+ let preludeEnd = preludeStart;
1463
+ while (peekType(s) !== 0 /* EOF */ && peekType(s) !== 23 /* LeftCurlyBracket */)
1464
+ preludeEnd = consume(s);
1465
+ const preludeText = s.source.slice(preludeStart.start, preludeEnd.end).trim();
1466
+ prelude = rawNode(preludeText, preludeStart, preludeEnd, s);
1467
+ }
1468
+ const block = parseBlock(s, true);
1469
+ return { type: "Rule", prelude, block, loc: loc(s, startTok, peek(s)) };
1470
+ }
1471
+ function parseBlock(s, allowNested = false) {
1472
+ const startTok = peek(s);
1473
+ if (peekType(s) !== 23 /* LeftCurlyBracket */)
1474
+ return { type: "Block", children: newList(), loc: emptyLoc(s) };
1475
+ s.pos++;
1476
+ const children = newList();
1477
+ const types = s.types;
1478
+ const end = s.end;
1479
+ while (s.pos < end) {
1480
+ const t = types[s.pos];
1481
+ if (t === 24 /* RightCurlyBracket */ || t === 0 /* EOF */)
1482
+ break;
1483
+ if (t === 13 /* WhiteSpace */) {
1484
+ s.pos++;
1485
+ continue;
1486
+ }
1487
+ if (t === 25 /* Comment */) {
1488
+ const tok = { type: 25 /* Comment */, start: s.starts[s.pos], end: s.ends[s.pos] };
1489
+ s.pos++;
1490
+ children.appendData(makeComment(s, tok));
1491
+ continue;
1492
+ }
1493
+ if (t === 3 /* AtKeyword */) {
1494
+ const at = parseAtrule(s);
1495
+ if (at)
1496
+ children.appendData(at);
1497
+ continue;
1498
+ }
1499
+ if (allowNested && lookahead(s, isCurlyAheadBeforeSemicolon)) {
1500
+ const r = parseRule(s);
1501
+ children.appendData(r);
1502
+ continue;
1503
+ }
1504
+ const decl = parseDeclaration(s);
1505
+ if (decl)
1506
+ children.appendData(decl);
1507
+ if (s.pos < end && types[s.pos] === 17 /* Semicolon */)
1508
+ s.pos++;
1509
+ }
1510
+ if (peekType(s) === 24 /* RightCurlyBracket */)
1511
+ s.pos++;
1512
+ return { type: "Block", children, loc: loc(s, startTok, peek(s)) };
1513
+ }
1514
+ function lookahead(s, predicate) {
1515
+ const saved = s.pos;
1516
+ const r = predicate(s);
1517
+ s.pos = saved;
1518
+ return r;
1519
+ }
1520
+ function isCurlyAheadBeforeSemicolon(s) {
1521
+ const types = s.types;
1522
+ const end = s.end;
1523
+ while (s.pos < end) {
1524
+ const t = types[s.pos];
1525
+ if (t === 23 /* LeftCurlyBracket */)
1526
+ return true;
1527
+ if (t === 17 /* Semicolon */ || t === 24 /* RightCurlyBracket */ || t === 0 /* EOF */)
1528
+ return false;
1529
+ s.pos++;
1530
+ }
1531
+ return false;
1532
+ }
1533
+ function parseDeclarationList(s) {
1534
+ const startTok = peek(s);
1535
+ const children = newList();
1536
+ while (peekType(s) !== 0 /* EOF */ && peekType(s) !== 24 /* RightCurlyBracket */) {
1537
+ const t = peek(s);
1538
+ if (t.type === 13 /* WhiteSpace */) {
1539
+ s.pos++;
1540
+ continue;
1541
+ }
1542
+ if (t.type === 25 /* Comment */) {
1543
+ children.appendData(makeComment(s, consume(s)));
1544
+ continue;
1545
+ }
1546
+ if (t.type === 17 /* Semicolon */) {
1547
+ s.pos++;
1548
+ continue;
1549
+ }
1550
+ if (t.type === 3 /* AtKeyword */) {
1551
+ const at = parseAtrule(s);
1552
+ if (at)
1553
+ children.appendData(at);
1554
+ continue;
1555
+ }
1556
+ const decl = parseDeclaration(s);
1557
+ if (decl)
1558
+ children.appendData(decl);
1559
+ if (peekType(s) === 17 /* Semicolon */)
1560
+ consume(s);
1561
+ }
1562
+ return { type: "DeclarationList", children, loc: loc(s, startTok, peek(s)) };
1563
+ }
1564
+ function parseDeclaration(s) {
1565
+ skipWhitespace(s);
1566
+ const startTok = peek(s);
1567
+ if (startTok.type !== 1 /* Ident */ && startTok.type !== 4 /* Hash */ && !(startTok.type === 9 /* Delim */ && s.source[startTok.start] === "*" && s.source[startTok.start + 1] === " ")) {
1568
+ if (startTok.type === 9 /* Delim */ && s.source[startTok.start] === "*") {
1569
+ s.pos++;
1570
+ } else {
1571
+ reportError(s, `Expected property name`, startTok, { type: "Raw", value: "", loc: null });
1572
+ const types2 = s.types;
1573
+ const end = s.end;
1574
+ while (s.pos < end) {
1575
+ const t = types2[s.pos];
1576
+ if (t === 0 /* EOF */ || t === 17 /* Semicolon */ || t === 24 /* RightCurlyBracket */)
1577
+ break;
1578
+ s.pos++;
1579
+ }
1580
+ return null;
1581
+ }
1582
+ }
1583
+ const propStart = s.starts[s.pos];
1584
+ const propEnd = s.ends[s.pos];
1585
+ s.pos++;
1586
+ const property = s.source.slice(propStart, propEnd);
1587
+ skipWhitespaceOnly(s);
1588
+ if (peekType(s) !== 16 /* Colon */) {
1589
+ reportError(s, `Expected ':' after property "${property}"`, peek(s), { type: "Raw", value: "", loc: null });
1590
+ const types2 = s.types;
1591
+ const end = s.end;
1592
+ while (s.pos < end) {
1593
+ const t = types2[s.pos];
1594
+ if (t === 0 /* EOF */ || t === 17 /* Semicolon */ || t === 24 /* RightCurlyBracket */)
1595
+ break;
1596
+ s.pos++;
1597
+ }
1598
+ return null;
1599
+ }
1600
+ s.pos++;
1601
+ skipWhitespaceOnly(s);
1602
+ const types = s.types;
1603
+ const starts = s.starts;
1604
+ const tend = s.end;
1605
+ const valueStartPos = s.pos;
1606
+ let scanPos = valueStartPos;
1607
+ let lastNonWsPos = valueStartPos;
1608
+ let importantIdentPos = -1;
1609
+ let bangPos = -1;
1610
+ while (scanPos < tend) {
1611
+ const t = types[scanPos];
1612
+ if (t === 0 /* EOF */ || t === 17 /* Semicolon */ || t === 24 /* RightCurlyBracket */)
1613
+ break;
1614
+ if (t === 9 /* Delim */ && s.source.charCodeAt(starts[scanPos]) === 33) {
1615
+ let look = scanPos + 1;
1616
+ while (look < tend && types[look] === 13 /* WhiteSpace */)
1617
+ look++;
1618
+ if (look < tend && types[look] === 1 /* Ident */) {
1619
+ const ts = starts[look];
1620
+ const te = s.ends[look];
1621
+ if (te - ts === 9 && (s.source.charCodeAt(ts) | 32) === 105 && (s.source.charCodeAt(ts + 1) | 32) === 109 && (s.source.charCodeAt(ts + 2) | 32) === 112 && (s.source.charCodeAt(ts + 3) | 32) === 111 && (s.source.charCodeAt(ts + 4) | 32) === 114 && (s.source.charCodeAt(ts + 5) | 32) === 116 && (s.source.charCodeAt(ts + 6) | 32) === 97 && (s.source.charCodeAt(ts + 7) | 32) === 110 && (s.source.charCodeAt(ts + 8) | 32) === 116) {
1622
+ bangPos = scanPos;
1623
+ importantIdentPos = look;
1624
+ scanPos = look + 1;
1625
+ continue;
1626
+ }
1627
+ }
1628
+ }
1629
+ if (t !== 13 /* WhiteSpace */ && t !== 25 /* Comment */)
1630
+ lastNonWsPos = scanPos + 1;
1631
+ scanPos++;
1632
+ }
1633
+ const valueEndPos = lastNonWsPos;
1634
+ const importantTok = importantIdentPos >= 0 ? { type: 1 /* Ident */, start: starts[importantIdentPos], end: s.ends[importantIdentPos] } : null;
1635
+ const isCustom = property.startsWith("--");
1636
+ let value;
1637
+ const valueStartByte = starts[valueStartPos];
1638
+ const valueEndByte = valueEndPos > valueStartPos ? s.ends[valueEndPos - 1] : valueStartByte;
1639
+ const valueStartTok = { type: types[valueStartPos], start: valueStartByte, end: s.ends[valueStartPos] };
1640
+ const valueEndTok = valueEndPos > valueStartPos ? { type: types[valueEndPos - 1], start: starts[valueEndPos - 1], end: valueEndByte } : valueStartTok;
1641
+ if (isCustom && !s.parseCustomProperty || !s.parseValue) {
1642
+ const valueText = s.source.slice(valueStartByte, valueEndByte).trim();
1643
+ value = { type: "Raw", value: valueText, loc: loc(s, valueStartTok, valueEndTok) };
1644
+ } else if (valueEndPos === valueStartPos) {
1645
+ value = { type: "Value", children: newList(), loc: loc(s, valueStartTok, valueEndTok) };
1646
+ } else {
1647
+ const savedEnd = s.end;
1648
+ s.end = valueEndPos;
1649
+ s.pos = valueStartPos;
1650
+ value = parseValueChildren(s);
1651
+ s.end = savedEnd;
1652
+ }
1653
+ s.pos = scanPos;
1654
+ return {
1655
+ type: "Declaration",
1656
+ property,
1657
+ important: importantTok ? true : false,
1658
+ value,
1659
+ loc: loc(s, startTok, peek(s))
1660
+ };
1661
+ }
1662
+ function parseValue(s) {
1663
+ return parseValueChildren(s);
1664
+ }
1665
+ function parseValueChildren(s) {
1666
+ const startTok = peek(s);
1667
+ const children = newList();
1668
+ while (peekType(s) !== 0 /* EOF */ && peekType(s) !== 17 /* Semicolon */ && peekType(s) !== 24 /* RightCurlyBracket */ && peekType(s) !== 22 /* RightParenthesis */ && peekType(s) !== 20 /* RightSquareBracket */) {
1669
+ const node = parseValueChild(s);
1670
+ if (node)
1671
+ children.appendData(node);
1672
+ }
1673
+ promoteRatios(children);
1674
+ return { type: "Value", children, loc: loc(s, startTok, peek(s)) };
1675
+ }
1676
+ function promoteRatiosDeep(list) {
1677
+ for (const child of list) {
1678
+ if ("children" in child && child.children instanceof CssList)
1679
+ promoteRatiosDeep(child.children);
1680
+ }
1681
+ promoteRatios(list);
1682
+ }
1683
+ function promoteRatios(list) {
1684
+ let cur = list.head;
1685
+ while (cur) {
1686
+ if (cur.data.type === "Number") {
1687
+ let slashItem = cur.next;
1688
+ while (slashItem && slashItem.data.type === "WhiteSpace")
1689
+ slashItem = slashItem.next;
1690
+ if (slashItem && slashItem.data.type === "Operator" && slashItem.data.value === "/") {
1691
+ let rightItem = slashItem.next;
1692
+ while (rightItem && rightItem.data.type === "WhiteSpace")
1693
+ rightItem = rightItem.next;
1694
+ if (rightItem && rightItem.data.type === "Number") {
1695
+ const ratio = {
1696
+ type: "Ratio",
1697
+ left: cur.data,
1698
+ right: rightItem.data,
1699
+ loc: null
1700
+ };
1701
+ let toRemove = cur.next;
1702
+ while (toRemove && toRemove !== rightItem.next) {
1703
+ const nxt = toRemove.next;
1704
+ list.remove(toRemove);
1705
+ toRemove = nxt;
1706
+ }
1707
+ list.replace(cur, list.createItem(ratio));
1708
+ cur = list.head;
1709
+ continue;
1710
+ }
1711
+ }
1712
+ }
1713
+ cur = cur.next;
1714
+ }
1715
+ }
1716
+ function parseValueChild(s) {
1717
+ const i = s.pos;
1718
+ if (i >= s.end)
1719
+ return null;
1720
+ const ttype = s.types[i];
1721
+ const tstart = s.starts[i];
1722
+ const tend = s.ends[i];
1723
+ const src = s.source;
1724
+ switch (ttype) {
1725
+ case 13 /* WhiteSpace */: {
1726
+ s.pos++;
1727
+ return s.positions ? { type: "WhiteSpace", value: " ", loc: locRange(s, tstart, tend) } : { type: "WhiteSpace", value: " ", loc: null };
1728
+ }
1729
+ case 25 /* Comment */: {
1730
+ s.pos++;
1731
+ return { type: "Comment", value: src.slice(tstart + 2, tend - 2), loc: s.positions ? locRange(s, tstart, tend) : null };
1732
+ }
1733
+ case 10 /* Number */: {
1734
+ s.pos++;
1735
+ return { type: "Number", value: src.slice(tstart, tend), loc: s.positions ? locRange(s, tstart, tend) : null };
1736
+ }
1737
+ case 11 /* Percentage */: {
1738
+ s.pos++;
1739
+ return { type: "Percentage", value: src.slice(tstart, tend - 1), loc: s.positions ? locRange(s, tstart, tend) : null };
1740
+ }
1741
+ case 12 /* Dimension */: {
1742
+ s.pos++;
1743
+ let unitStart = tstart;
1744
+ const c0 = src.charCodeAt(unitStart);
1745
+ if (c0 === 43 || c0 === 45)
1746
+ unitStart++;
1747
+ let sawDot = false;
1748
+ while (unitStart < tend) {
1749
+ const c = src.charCodeAt(unitStart);
1750
+ if (c >= 48 && c <= 57) {
1751
+ unitStart++;
1752
+ continue;
1753
+ }
1754
+ if (c === 46 && !sawDot) {
1755
+ sawDot = true;
1756
+ unitStart++;
1757
+ continue;
1758
+ }
1759
+ break;
1760
+ }
1761
+ const eC = src.charCodeAt(unitStart);
1762
+ if (eC === 69 || eC === 101) {
1763
+ let look = unitStart + 1;
1764
+ const sgn = src.charCodeAt(look);
1765
+ if (sgn === 43 || sgn === 45)
1766
+ look++;
1767
+ let any = false;
1768
+ while (look < tend) {
1769
+ const c = src.charCodeAt(look);
1770
+ if (c >= 48 && c <= 57) {
1771
+ look++;
1772
+ any = true;
1773
+ continue;
1774
+ }
1775
+ break;
1776
+ }
1777
+ if (any)
1778
+ unitStart = look;
1779
+ }
1780
+ return {
1781
+ type: "Dimension",
1782
+ value: src.slice(tstart, unitStart),
1783
+ unit: src.slice(unitStart, tend),
1784
+ loc: s.positions ? locRange(s, tstart, tend) : null
1785
+ };
1786
+ }
1787
+ case 1 /* Ident */: {
1788
+ s.pos++;
1789
+ return { type: "Identifier", name: decodeName(src, tstart, tend), loc: s.positions ? locRange(s, tstart, tend) : null };
1790
+ }
1791
+ case 5 /* String */: {
1792
+ s.pos++;
1793
+ const innerStart = tstart + 1;
1794
+ const closesProperly = tend - tstart >= 2 && src.charCodeAt(tend - 1) === src.charCodeAt(tstart);
1795
+ const innerEnd = closesProperly ? tend - 1 : tend;
1796
+ const value = decodeString(src, innerStart, innerEnd);
1797
+ return { type: "String", value, loc: s.positions ? locRange(s, tstart, tend) : null };
1798
+ }
1799
+ case 7 /* Url */: {
1800
+ s.pos++;
1801
+ let a = tstart + 4;
1802
+ while (a < tend && isWhitespaceCode(src.charCodeAt(a)))
1803
+ a++;
1804
+ let b = tend;
1805
+ if (b > a && src.charCodeAt(b - 1) === 41)
1806
+ b--;
1807
+ while (b > a && isWhitespaceCode(src.charCodeAt(b - 1)))
1808
+ b--;
1809
+ let value;
1810
+ if (b - a >= 2) {
1811
+ const q0 = src.charCodeAt(a);
1812
+ const q1 = src.charCodeAt(b - 1);
1813
+ if ((q0 === 34 || q0 === 39) && q0 === q1)
1814
+ value = src.slice(a + 1, b - 1);
1815
+ else
1816
+ value = src.slice(a, b);
1817
+ } else {
1818
+ value = src.slice(a, b);
1819
+ }
1820
+ return { type: "Url", value, loc: s.positions ? locRange(s, tstart, tend) : null };
1821
+ }
1822
+ case 4 /* Hash */: {
1823
+ s.pos++;
1824
+ return { type: "Hash", name: src.slice(tstart + 1, tend), loc: s.positions ? locRange(s, tstart, tend) : null };
1825
+ }
1826
+ case 2 /* Function */: {
1827
+ return parseFunction(s);
1828
+ }
1829
+ case 21 /* LeftParenthesis */: {
1830
+ return parseParentheses(s);
1831
+ }
1832
+ case 18 /* Comma */: {
1833
+ s.pos++;
1834
+ return { type: "Operator", value: ",", loc: s.positions ? locRange(s, tstart, tend) : null };
1835
+ }
1836
+ case 16 /* Colon */: {
1837
+ s.pos++;
1838
+ return { type: "Operator", value: ":", loc: s.positions ? locRange(s, tstart, tend) : null };
1839
+ }
1840
+ case 9 /* Delim */: {
1841
+ s.pos++;
1842
+ const code = src.charCodeAt(tstart);
1843
+ const ch = src[tstart];
1844
+ if (isValueOperatorChar(code))
1845
+ return { type: "Operator", value: ch, loc: s.positions ? locRange(s, tstart, tend) : null };
1846
+ return { type: "Identifier", name: ch, loc: s.positions ? locRange(s, tstart, tend) : null };
1847
+ }
1848
+ case 19 /* LeftSquareBracket */: {
1849
+ s.pos++;
1850
+ const children = newList();
1851
+ while (peekType(s) !== 0 /* EOF */ && peekType(s) !== 20 /* RightSquareBracket */) {
1852
+ const inner = parseValueChild(s);
1853
+ if (inner)
1854
+ children.appendData(inner);
1855
+ }
1856
+ const endByte = s.pos < s.end ? s.ends[s.pos] : tend;
1857
+ if (peekType(s) === 20 /* RightSquareBracket */)
1858
+ s.pos++;
1859
+ return { type: "Brackets", children, loc: s.positions ? locRange(s, tstart, endByte) : null };
1860
+ }
1861
+ case 3 /* AtKeyword */:
1862
+ case 23 /* LeftCurlyBracket */:
1863
+ case 24 /* RightCurlyBracket */:
1864
+ case 22 /* RightParenthesis */:
1865
+ case 20 /* RightSquareBracket */:
1866
+ case 17 /* Semicolon */:
1867
+ case 0 /* EOF */:
1868
+ case 14 /* CDO */:
1869
+ case 15 /* CDC */:
1870
+ case 6 /* BadString */:
1871
+ case 8 /* BadUrl */: {
1872
+ s.pos++;
1873
+ return { type: "Raw", value: src.slice(tstart, tend), loc: s.positions ? locRange(s, tstart, tend) : null };
1874
+ }
1875
+ }
1876
+ s.pos++;
1877
+ return null;
1878
+ }
1879
+ function isWhitespaceCode(c) {
1880
+ return c === 32 || c === 9 || c === 10 || c === 12 || c === 13;
1881
+ }
1882
+ function isValueOperatorChar(code) {
1883
+ return code === 47 || code === 43 || code === 45 || code === 42 || code === 61 || code === 62 || code === 60 || code === 126 || code === 124 || code === 36 || code === 94 || code === 33 || code === 38;
1884
+ }
1885
+ function lowerIfNeeded(source, start, end) {
1886
+ for (let i = start;i < end; i++) {
1887
+ const c = source.charCodeAt(i);
1888
+ if (c >= 65 && c <= 90)
1889
+ return source.slice(start, end).toLowerCase();
1890
+ }
1891
+ return source.slice(start, end);
1892
+ }
1893
+ function locRange(s, startByte, endByte) {
1894
+ const start = s.tokenizer.locate(startByte);
1895
+ const end = s.tokenizer.locate(endByte);
1896
+ return {
1897
+ source: s.filename ?? "<unknown>",
1898
+ start: { offset: startByte, line: start.line, column: start.column },
1899
+ end: { offset: endByte, line: end.line, column: end.column }
1900
+ };
1901
+ }
1902
+ function parseFunction(s) {
1903
+ const startTok = consume(s);
1904
+ const name = lowerIfNeeded(s.source, startTok.start, startTok.end - 1);
1905
+ const children = newList();
1906
+ while (peekType(s) !== 0 /* EOF */ && peekType(s) !== 22 /* RightParenthesis */) {
1907
+ const node = parseValueChild(s);
1908
+ if (node)
1909
+ children.appendData(node);
1910
+ }
1911
+ if (peekType(s) === 22 /* RightParenthesis */)
1912
+ consume(s);
1913
+ if (name === "url") {
1914
+ for (let cur = children.head;cur != null; cur = cur.next) {
1915
+ if (cur.data.type === "String")
1916
+ return { type: "Url", value: cur.data.value, loc: loc(s, startTok, peek(s)) };
1917
+ }
1918
+ }
1919
+ return { type: "Function", name, children, loc: loc(s, startTok, peek(s)) };
1920
+ }
1921
+ function parseParentheses(s) {
1922
+ const startTok = consume(s);
1923
+ const children = newList();
1924
+ while (peekType(s) !== 0 /* EOF */ && peekType(s) !== 22 /* RightParenthesis */) {
1925
+ const node = parseValueChild(s);
1926
+ if (node)
1927
+ children.appendData(node);
1928
+ }
1929
+ if (peekType(s) === 22 /* RightParenthesis */)
1930
+ consume(s);
1931
+ return { type: "Parentheses", children, loc: loc(s, startTok, peek(s)) };
1932
+ }
1933
+ function parseSelectorList(s) {
1934
+ const startTok = peek(s);
1935
+ const children = newList();
1936
+ while (peekType(s) !== 0 /* EOF */) {
1937
+ skipWhitespace(s);
1938
+ if (peekType(s) === 0 /* EOF */ || peekType(s) === 23 /* LeftCurlyBracket */)
1939
+ break;
1940
+ const sel = parseSelector(s);
1941
+ if (sel.children.head !== null)
1942
+ children.appendData(sel);
1943
+ skipWhitespace(s);
1944
+ if (peekType(s) === 18 /* Comma */) {
1945
+ consume(s);
1946
+ continue;
1947
+ }
1948
+ break;
1949
+ }
1950
+ return { type: "SelectorList", children, loc: loc(s, startTok, peek(s)) };
1951
+ }
1952
+ function parseSelector(s) {
1953
+ const startTok = peek(s);
1954
+ const children = newList();
1955
+ let lastWasCombinator = true;
1956
+ while (peekType(s) !== 0 /* EOF */ && peekType(s) !== 18 /* Comma */ && peekType(s) !== 23 /* LeftCurlyBracket */) {
1957
+ const t = peek(s);
1958
+ if (t.type === 13 /* WhiteSpace */) {
1959
+ consume(s);
1960
+ if (!lastWasCombinator && peekType(s) !== 0 /* EOF */ && peekType(s) !== 18 /* Comma */ && peekType(s) !== 23 /* LeftCurlyBracket */ && !isExplicitCombinator(s) && !isColumnCombinator(s)) {
1961
+ const c = { type: "Combinator", name: " ", loc: loc(s, t, t) };
1962
+ children.appendData(c);
1963
+ lastWasCombinator = true;
1964
+ }
1965
+ continue;
1966
+ }
1967
+ if (t.type === 9 /* Delim */ && s.source.charCodeAt(t.start) === 124 && s.types[s.pos + 1] === 9 /* Delim */ && s.source.charCodeAt(s.starts[s.pos + 1]) === 124) {
1968
+ const startCol = peek(s);
1969
+ consume(s);
1970
+ const endCol = consume(s);
1971
+ const c = { type: "Combinator", name: "||", loc: loc(s, startCol, endCol) };
1972
+ children.appendData(c);
1973
+ lastWasCombinator = true;
1974
+ skipWhitespace(s);
1975
+ continue;
1976
+ }
1977
+ if (isExplicitCombinator(s)) {
1978
+ const ct = consume(s);
1979
+ const ch = s.source[ct.start];
1980
+ const c = { type: "Combinator", name: ch, loc: loc(s, ct, ct) };
1981
+ children.appendData(c);
1982
+ lastWasCombinator = true;
1983
+ skipWhitespace(s);
1984
+ continue;
1985
+ }
1986
+ const seg = parseSelectorSegment(s);
1987
+ if (!seg)
1988
+ break;
1989
+ children.appendData(seg);
1990
+ lastWasCombinator = false;
1991
+ }
1992
+ while (children.tail && children.tail.data.type === "Combinator")
1993
+ children.remove(children.tail);
1994
+ return { type: "Selector", children, loc: loc(s, startTok, peek(s)) };
1995
+ }
1996
+ function isExplicitCombinator(s) {
1997
+ const t = peek(s);
1998
+ if (t.type !== 9 /* Delim */)
1999
+ return false;
2000
+ const ch = s.source[t.start];
2001
+ return ch === ">" || ch === "+" || ch === "~";
2002
+ }
2003
+ function isColumnCombinator(s) {
2004
+ if (s.types[s.pos] !== 9 /* Delim */)
2005
+ return false;
2006
+ if (s.source.charCodeAt(s.starts[s.pos]) !== 124)
2007
+ return false;
2008
+ if (s.types[s.pos + 1] !== 9 /* Delim */)
2009
+ return false;
2010
+ return s.source.charCodeAt(s.starts[s.pos + 1]) === 124;
2011
+ }
2012
+ function parseSelectorSegment(s) {
2013
+ const t = peek(s);
2014
+ switch (t.type) {
2015
+ case 1 /* Ident */: {
2016
+ consume(s);
2017
+ if (peekType(s) === 9 /* Delim */ && s.source[peek(s).start] === "|" && s.source[peek(s).start + 1] !== "=" && !(s.types[s.pos + 1] === 9 /* Delim */ && s.source.charCodeAt(s.starts[s.pos + 1]) === 124)) {
2018
+ consume(s);
2019
+ if (peekType(s) === 1 /* Ident */) {
2020
+ const local = consume(s);
2021
+ const node2 = {
2022
+ type: "TypeSelector",
2023
+ name: `${tokenSlice(s, t)}|${tokenSlice(s, local)}`,
2024
+ loc: loc(s, t, local)
2025
+ };
2026
+ return node2;
2027
+ }
2028
+ if (peekType(s) === 9 /* Delim */ && s.source[peek(s).start] === "*") {
2029
+ const star = consume(s);
2030
+ const node2 = {
2031
+ type: "TypeSelector",
2032
+ name: `${tokenSlice(s, t)}|*`,
2033
+ loc: loc(s, t, star)
2034
+ };
2035
+ return node2;
2036
+ }
2037
+ }
2038
+ const node = { type: "TypeSelector", name: tokenSlice(s, t), loc: loc(s, t, t) };
2039
+ return node;
2040
+ }
2041
+ case 11 /* Percentage */: {
2042
+ consume(s);
2043
+ const node = { type: "TypeSelector", name: tokenSlice(s, t), loc: loc(s, t, t) };
2044
+ return node;
2045
+ }
2046
+ case 10 /* Number */: {
2047
+ consume(s);
2048
+ const node = { type: "TypeSelector", name: tokenSlice(s, t), loc: loc(s, t, t) };
2049
+ return node;
2050
+ }
2051
+ case 9 /* Delim */: {
2052
+ const ch = s.source[t.start];
2053
+ if (ch === "*") {
2054
+ consume(s);
2055
+ const node = { type: "TypeSelector", name: "*", loc: loc(s, t, t) };
2056
+ return node;
2057
+ }
2058
+ if (ch === ".") {
2059
+ consume(s);
2060
+ if (peekType(s) === 1 /* Ident */) {
2061
+ const id = consume(s);
2062
+ const node = { type: "ClassSelector", name: tokenSlice(s, id), loc: loc(s, t, id) };
2063
+ return node;
2064
+ }
2065
+ return null;
2066
+ }
2067
+ if (ch === "&") {
2068
+ consume(s);
2069
+ return { type: "NestingSelector", loc: loc(s, t, t) };
2070
+ }
2071
+ consume(s);
2072
+ return null;
2073
+ }
2074
+ case 4 /* Hash */: {
2075
+ consume(s);
2076
+ const node = { type: "IdSelector", name: s.source.slice(t.start + 1, t.end), loc: loc(s, t, t) };
2077
+ return node;
2078
+ }
2079
+ case 16 /* Colon */: {
2080
+ consume(s);
2081
+ const isElement = peekType(s) === 16 /* Colon */;
2082
+ if (isElement)
2083
+ consume(s);
2084
+ return parsePseudo(s, isElement, t);
2085
+ }
2086
+ case 19 /* LeftSquareBracket */: {
2087
+ return parseAttribute(s);
2088
+ }
2089
+ }
2090
+ return null;
2091
+ }
2092
+ function parsePseudo(s, isElement, startTok) {
2093
+ const t = peek(s);
2094
+ if (t.type === 1 /* Ident */) {
2095
+ consume(s);
2096
+ const name = lowerIfNeeded(s.source, t.start, t.end);
2097
+ const node = isElement ? { type: "PseudoElementSelector", name, children: null, loc: loc(s, startTok, t) } : { type: "PseudoClassSelector", name, children: null, loc: loc(s, startTok, t) };
2098
+ return node;
2099
+ }
2100
+ if (t.type === 2 /* Function */) {
2101
+ consume(s);
2102
+ const name = lowerIfNeeded(s.source, t.start, t.end - 1);
2103
+ const children = newList();
2104
+ const isSelectorListPseudo = !isElement && SELECTOR_LIST_PSEUDOS_PARSE.has(name);
2105
+ if (isSelectorListPseudo) {
2106
+ const argStart = peek(s);
2107
+ let argEnd = argStart;
2108
+ let depth = 1;
2109
+ while (peekType(s) !== 0 /* EOF */ && depth > 0) {
2110
+ if (peekType(s) === 21 /* LeftParenthesis */ || peekType(s) === 2 /* Function */)
2111
+ depth++;
2112
+ else if (peekType(s) === 22 /* RightParenthesis */) {
2113
+ depth--;
2114
+ if (depth === 0)
2115
+ break;
2116
+ }
2117
+ argEnd = consume(s);
2118
+ }
2119
+ if (peekType(s) === 22 /* RightParenthesis */)
2120
+ consume(s);
2121
+ const inner = s.source.slice(argStart.start, argEnd.end).trim();
2122
+ if (inner.length > 0) {
2123
+ const sub = makeState(inner, { positions: false });
2124
+ const list = parseSelectorList(sub);
2125
+ children.appendData(list);
2126
+ }
2127
+ } else {
2128
+ while (peekType(s) !== 0 /* EOF */ && peekType(s) !== 22 /* RightParenthesis */) {
2129
+ const inner = parseValueChild(s);
2130
+ if (inner)
2131
+ children.appendData(inner);
2132
+ }
2133
+ if (peekType(s) === 22 /* RightParenthesis */)
2134
+ consume(s);
2135
+ }
2136
+ if (isElement) {
2137
+ const node2 = { type: "PseudoElementSelector", name, children, loc: loc(s, startTok, peek(s)) };
2138
+ return node2;
2139
+ }
2140
+ const node = { type: "PseudoClassSelector", name, children, loc: loc(s, startTok, peek(s)) };
2141
+ return node;
2142
+ }
2143
+ return null;
2144
+ }
2145
+ function parseAttribute(s) {
2146
+ const startTok = consume(s);
2147
+ skipWhitespace(s);
2148
+ const nameTok = peek(s);
2149
+ if (nameTok.type !== 1 /* Ident */)
2150
+ return null;
2151
+ consume(s);
2152
+ const name = { type: "Identifier", name: tokenSlice(s, nameTok), loc: loc(s, nameTok, nameTok) };
2153
+ skipWhitespace(s);
2154
+ let matcher = null;
2155
+ let value = null;
2156
+ let flags = null;
2157
+ const next = peek(s);
2158
+ if (next.type === 9 /* Delim */) {
2159
+ const ch = s.source[next.start];
2160
+ const ch2 = s.source[next.start + 1];
2161
+ if (ch === "=") {
2162
+ matcher = "=";
2163
+ consume(s);
2164
+ } else if ((ch === "~" || ch === "|" || ch === "^" || ch === "$" || ch === "*") && ch2 === "=") {
2165
+ consume(s);
2166
+ const eq = peek(s);
2167
+ if (eq.type === 9 /* Delim */ && s.source[eq.start] === "=") {
2168
+ consume(s);
2169
+ matcher = `${ch}=`;
2170
+ }
2171
+ }
2172
+ skipWhitespace(s);
2173
+ const v = peek(s);
2174
+ if (v.type === 5 /* String */) {
2175
+ consume(s);
2176
+ const closesProperly = v.end - v.start >= 2 && s.source.charCodeAt(v.end - 1) === s.source.charCodeAt(v.start);
2177
+ const text = decodeString(s.source, v.start + 1, closesProperly ? v.end - 1 : v.end);
2178
+ value = { type: "String", value: text, loc: loc(s, v, v) };
2179
+ } else if (v.type === 1 /* Ident */) {
2180
+ consume(s);
2181
+ value = { type: "Identifier", name: tokenSlice(s, v), loc: loc(s, v, v) };
2182
+ }
2183
+ skipWhitespace(s);
2184
+ const flagTok = peek(s);
2185
+ if (flagTok.type === 1 /* Ident */) {
2186
+ consume(s);
2187
+ flags = tokenSlice(s, flagTok);
2188
+ }
2189
+ }
2190
+ skipWhitespace(s);
2191
+ let endTok = peek(s);
2192
+ if (peekType(s) === 20 /* RightSquareBracket */) {
2193
+ endTok = consume(s);
2194
+ }
2195
+ return { type: "AttributeSelector", name, matcher, value, flags, loc: loc(s, startTok, endTok) };
2196
+ }
2197
+ // src/parse/walker.ts
2198
+ var SKIP = Symbol("walkSkip");
2199
+ var STOP = Symbol("walkStop");
2200
+ function newContext(root) {
2201
+ return {
2202
+ root,
2203
+ stylesheet: null,
2204
+ atrule: null,
2205
+ atrulePrelude: null,
2206
+ rule: null,
2207
+ selector: null,
2208
+ block: null,
2209
+ declaration: null,
2210
+ function: null
2211
+ };
2212
+ }
2213
+ function walkImpl(root, visitor) {
2214
+ const ctx = newContext(root);
2215
+ const enter = typeof visitor === "function" ? visitor : visitor.enter;
2216
+ const leave = typeof visitor === "function" ? null : visitor.leave ?? null;
2217
+ const filter = typeof visitor === "function" ? null : visitor.visit ?? null;
2218
+ const reverse = typeof visitor === "function" ? false : visitor.reverse ?? false;
2219
+ function visitNode(node, item, list) {
2220
+ let pushed = null;
2221
+ let prev;
2222
+ switch (node.type) {
2223
+ case "StyleSheet":
2224
+ pushed = "stylesheet";
2225
+ prev = ctx.stylesheet;
2226
+ ctx.stylesheet = node;
2227
+ break;
2228
+ case "Atrule":
2229
+ pushed = "atrule";
2230
+ prev = ctx.atrule;
2231
+ ctx.atrule = node;
2232
+ break;
2233
+ case "AtrulePrelude":
2234
+ pushed = "atrulePrelude";
2235
+ prev = ctx.atrulePrelude;
2236
+ ctx.atrulePrelude = node;
2237
+ break;
2238
+ case "Rule":
2239
+ pushed = "rule";
2240
+ prev = ctx.rule;
2241
+ ctx.rule = node;
2242
+ break;
2243
+ case "Selector":
2244
+ pushed = "selector";
2245
+ prev = ctx.selector;
2246
+ ctx.selector = node;
2247
+ break;
2248
+ case "Block":
2249
+ pushed = "block";
2250
+ prev = ctx.block;
2251
+ ctx.block = node;
2252
+ break;
2253
+ case "Declaration":
2254
+ pushed = "declaration";
2255
+ prev = ctx.declaration;
2256
+ ctx.declaration = node;
2257
+ break;
2258
+ case "Function":
2259
+ pushed = "function";
2260
+ prev = ctx.function;
2261
+ ctx.function = node;
2262
+ break;
2263
+ }
2264
+ let result;
2265
+ if ((filter === null || filter === node.type) && enter) {
2266
+ const r = enter.call(ctx, node, item, list);
2267
+ if (r === SKIP) {
2268
+ if (pushed)
2269
+ ctx[pushed] = prev;
2270
+ return;
2271
+ }
2272
+ if (r === STOP) {
2273
+ if (pushed)
2274
+ ctx[pushed] = prev;
2275
+ return STOP;
2276
+ }
2277
+ }
2278
+ result = walkChildren(node, reverse, visitNode);
2279
+ if (result === STOP) {
2280
+ if (pushed)
2281
+ ctx[pushed] = prev;
2282
+ return STOP;
2283
+ }
2284
+ if ((filter === null || filter === node.type) && leave) {
2285
+ const r = leave.call(ctx, node, item, list);
2286
+ if (r === STOP) {
2287
+ if (pushed)
2288
+ ctx[pushed] = prev;
2289
+ return STOP;
2290
+ }
2291
+ }
2292
+ if (pushed)
2293
+ ctx[pushed] = prev;
2294
+ return;
2295
+ }
2296
+ return visitNode(root, null, null);
2297
+ }
2298
+ var walk = Object.assign(walkImpl, { skip: SKIP, stop: STOP });
2299
+ function walkChildren(node, reverse, visitNode) {
2300
+ if ("children" in node && node.children instanceof CssList) {
2301
+ return walkList(node.children, reverse, visitNode);
2302
+ }
2303
+ if (node.type === "Rule") {
2304
+ const r1 = visitNode(node.prelude, null, null);
2305
+ if (r1 === STOP)
2306
+ return STOP;
2307
+ const r2 = visitNode(node.block, null, null);
2308
+ if (r2 === STOP)
2309
+ return STOP;
2310
+ return;
2311
+ }
2312
+ if (node.type === "Atrule") {
2313
+ if (node.prelude) {
2314
+ const r = visitNode(node.prelude, null, null);
2315
+ if (r === STOP)
2316
+ return STOP;
2317
+ }
2318
+ if (node.block) {
2319
+ const r = visitNode(node.block, null, null);
2320
+ if (r === STOP)
2321
+ return STOP;
2322
+ }
2323
+ return;
2324
+ }
2325
+ if (node.type === "Declaration") {
2326
+ return visitNode(node.value, null, null);
2327
+ }
2328
+ if (node.type === "AttributeSelector") {
2329
+ const r = visitNode(node.name, null, null);
2330
+ if (r === STOP)
2331
+ return STOP;
2332
+ if (node.value)
2333
+ return visitNode(node.value, null, null);
2334
+ return;
2335
+ }
2336
+ return;
2337
+ }
2338
+ function walkList(list, reverse, visitNode) {
2339
+ let stopped;
2340
+ if (reverse) {
2341
+ list.forEachRight((data, item, l) => {
2342
+ if (stopped)
2343
+ return;
2344
+ const r = visitNode(data, item, l);
2345
+ if (r === STOP)
2346
+ stopped = STOP;
2347
+ });
2348
+ } else {
2349
+ list.forEach((data, item, l) => {
2350
+ if (stopped)
2351
+ return;
2352
+ const r = visitNode(data, item, l);
2353
+ if (r === STOP)
2354
+ stopped = STOP;
2355
+ });
2356
+ }
2357
+ return stopped;
2358
+ }
2359
+ // src/what/index.ts
2360
+ var exports_what = {};
2361
+ __export(exports_what, {
2362
+ stringify: () => stringify,
2363
+ parse: () => parse2,
2364
+ isTraversal: () => isTraversal,
2365
+ IgnoreCaseMode: () => IgnoreCaseMode
2366
+ });
2367
+
2368
+ // src/what/parse.ts
2369
+ var RE_NAME_STICKY = /(?:\\(?:[\dA-Fa-f]{1,6} ?|[^])|[\w\-\u00B0-\uFFFF])+/y;
2370
+ var RE_ESCAPE = /\\([\dA-Fa-f]{1,6} ?|[^])/g;
2371
+ function unescape(name) {
2372
+ return name.replace(RE_ESCAPE, (_m, escape) => {
2373
+ if (escape.length > 1 && /^[\dA-Fa-f]/.test(escape)) {
2374
+ const code = Number.parseInt(escape, 16);
2375
+ if (code >= 55296 && code <= 57343)
2376
+ return "\uFFFD";
2377
+ return String.fromCodePoint(code);
2378
+ }
2379
+ return escape;
2380
+ });
2381
+ }
2382
+ function unescapeIfNeeded(name) {
2383
+ return name.indexOf("\\") < 0 ? name : unescape(name);
2384
+ }
2385
+ var ATTRIBUTES_QUIRKS = new Set([
2386
+ "accept",
2387
+ "accept-charset",
2388
+ "align",
2389
+ "alink",
2390
+ "axis",
2391
+ "bgcolor",
2392
+ "charset",
2393
+ "checked",
2394
+ "clear",
2395
+ "codetype",
2396
+ "color",
2397
+ "compact",
2398
+ "declare",
2399
+ "defer",
2400
+ "dir",
2401
+ "direction",
2402
+ "disabled",
2403
+ "enctype",
2404
+ "face",
2405
+ "frame",
2406
+ "hreflang",
2407
+ "http-equiv",
2408
+ "lang",
2409
+ "language",
2410
+ "link",
2411
+ "media",
2412
+ "method",
2413
+ "multiple",
2414
+ "nohref",
2415
+ "noresize",
2416
+ "noshade",
2417
+ "nowrap",
2418
+ "readonly",
2419
+ "rel",
2420
+ "rev",
2421
+ "rules",
2422
+ "scope",
2423
+ "scrolling",
2424
+ "selected",
2425
+ "shape",
2426
+ "target",
2427
+ "text",
2428
+ "type",
2429
+ "valign",
2430
+ "valuetype",
2431
+ "vlink"
2432
+ ]);
2433
+ function actionFromChar(ch) {
2434
+ switch (ch) {
2435
+ case 126:
2436
+ return "element";
2437
+ case 94:
2438
+ return "start";
2439
+ case 36:
2440
+ return "end";
2441
+ case 42:
2442
+ return "any";
2443
+ case 33:
2444
+ return "not";
2445
+ case 124:
2446
+ return "hyphen";
2447
+ default:
2448
+ return null;
2449
+ }
2450
+ }
2451
+ function isWsCode(c) {
2452
+ return c === 32 || c === 9 || c === 10 || c === 13 || c === 12;
2453
+ }
2454
+ function parse2(selector, options = {}) {
2455
+ const subselects = [];
2456
+ const endIndex = parseSelectorImpl(subselects, selector, options, 0);
2457
+ if (endIndex < selector.length)
2458
+ throw new Error(`Unmatched selector: ${selector.slice(endIndex)}`);
2459
+ return subselects;
2460
+ }
2461
+ function readName(selector, from) {
2462
+ RE_NAME_STICKY.lastIndex = from;
2463
+ const m = RE_NAME_STICKY.exec(selector);
2464
+ if (!m)
2465
+ throw new Error(`Expected name, found ${selector.slice(from)}`);
2466
+ return { value: unescapeIfNeeded(m[0]), end: from + m[0].length };
2467
+ }
2468
+ function stripWS(selector, from) {
2469
+ while (from < selector.length && isWsCode(selector.charCodeAt(from)))
2470
+ from++;
2471
+ return from;
2472
+ }
2473
+ function parseSelectorImpl(subselects, selector, options, startIndex) {
2474
+ let tokens = [];
2475
+ let i = stripWS(selector, startIndex);
2476
+ const len = selector.length;
2477
+ const xmlMode = options.xmlMode === true;
2478
+ const lowerCaseAttrs = options.lowerCaseAttributeNames !== false && !xmlMode;
2479
+ const lowerCaseTagsFlag = options.lowerCaseTags !== false;
2480
+ while (i < len) {
2481
+ const code = selector.charCodeAt(i);
2482
+ if (isWsCode(code)) {
2483
+ let trimmed = i + 1;
2484
+ while (trimmed < len && isWsCode(selector.charCodeAt(trimmed)))
2485
+ trimmed++;
2486
+ if (tokens.length === 0)
2487
+ return trimmed;
2488
+ i = trimmed;
2489
+ addTraversal(tokens, "descendant");
2490
+ continue;
2491
+ }
2492
+ if (code === 62 || code === 60 || code === 126 || code === 43 || code === 124) {
2493
+ let j = i + 1;
2494
+ while (j < len && isWsCode(selector.charCodeAt(j)))
2495
+ j++;
2496
+ i = j;
2497
+ switch (code) {
2498
+ case 62:
2499
+ addTraversal(tokens, "child");
2500
+ break;
2501
+ case 60:
2502
+ addTraversal(tokens, "parent");
2503
+ break;
2504
+ case 126:
2505
+ addTraversal(tokens, "sibling");
2506
+ break;
2507
+ case 43:
2508
+ addTraversal(tokens, "adjacent");
2509
+ break;
2510
+ case 124:
2511
+ if (i < len && selector.charCodeAt(i) === 124) {
2512
+ i++;
2513
+ i = stripWS(selector, i);
2514
+ addTraversal(tokens, "column-combinator");
2515
+ } else {
2516
+ tokens.push({ type: "tag", name: "", namespace: "" });
2517
+ }
2518
+ break;
2519
+ }
2520
+ continue;
2521
+ }
2522
+ if (code === 44) {
2523
+ if (tokens.length === 0)
2524
+ throw new Error("Empty sub-selector");
2525
+ subselects.push(tokens);
2526
+ tokens = [];
2527
+ i = stripWS(selector, i + 1);
2528
+ continue;
2529
+ }
2530
+ if (code === 47 && selector.charCodeAt(i + 1) === 42) {
2531
+ const end = selector.indexOf("*/", i + 2);
2532
+ if (end < 0)
2533
+ throw new Error("Unmatched comment");
2534
+ i = stripWS(selector, end + 2);
2535
+ continue;
2536
+ }
2537
+ if (code === 42) {
2538
+ i++;
2539
+ tokens.push({ type: "universal", namespace: null });
2540
+ continue;
2541
+ }
2542
+ if (code === 35) {
2543
+ const r = readName(selector, i + 1);
2544
+ i = r.end;
2545
+ tokens.push({
2546
+ type: "attribute",
2547
+ name: "id",
2548
+ action: "equals",
2549
+ value: r.value,
2550
+ namespace: null,
2551
+ ignoreCase: false
2552
+ });
2553
+ continue;
2554
+ }
2555
+ if (code === 46) {
2556
+ const r = readName(selector, i + 1);
2557
+ i = r.end;
2558
+ tokens.push({
2559
+ type: "attribute",
2560
+ name: "class",
2561
+ action: "element",
2562
+ value: r.value,
2563
+ namespace: null,
2564
+ ignoreCase: false
2565
+ });
2566
+ continue;
2567
+ }
2568
+ if (code === 91) {
2569
+ i = parseAttribute2(selector, i, tokens, options, xmlMode, lowerCaseAttrs);
2570
+ continue;
2571
+ }
2572
+ if (code === 58) {
2573
+ i = parsePseudo2(selector, i, tokens, options);
2574
+ continue;
2575
+ }
2576
+ if (code === 124) {
2577
+ i++;
2578
+ const r = readName(selector, i);
2579
+ i = r.end;
2580
+ tokens.push({ type: "tag", name: lowerCaseTagsFlag ? r.value.toLowerCase() : r.value, namespace: "" });
2581
+ continue;
2582
+ }
2583
+ {
2584
+ const r1 = readName(selector, i);
2585
+ i = r1.end;
2586
+ if (i < len && selector.charCodeAt(i) === 124 && selector.charCodeAt(i + 1) !== 61) {
2587
+ i++;
2588
+ const r2 = readName(selector, i);
2589
+ i = r2.end;
2590
+ tokens.push({ type: "tag", name: lowerCaseTagsFlag ? r2.value.toLowerCase() : r2.value, namespace: r1.value });
2591
+ } else {
2592
+ tokens.push({ type: "tag", name: lowerCaseTagsFlag ? r1.value.toLowerCase() : r1.value, namespace: null });
2593
+ }
2594
+ }
2595
+ }
2596
+ if (tokens.length > 0)
2597
+ subselects.push(tokens);
2598
+ return i;
2599
+ }
2600
+ function parseAttribute2(selector, idx, tokens, options, xmlMode, lowerCaseAttrs) {
2601
+ let i = idx + 1;
2602
+ const len = selector.length;
2603
+ let attribute;
2604
+ if (selector.charCodeAt(i) === 124)
2605
+ throw new Error("Empty namespace not supported");
2606
+ if (selector.charCodeAt(i) === 42 && selector.charCodeAt(i + 1) === 124) {
2607
+ i += 2;
2608
+ const r = readName(selector, i);
2609
+ i = r.end;
2610
+ attribute = r.value;
2611
+ } else {
2612
+ const r = readName(selector, i);
2613
+ i = r.end;
2614
+ attribute = r.value;
2615
+ if (selector.charCodeAt(i) === 124 && selector.charCodeAt(i + 1) !== 61) {
2616
+ i++;
2617
+ const r2 = readName(selector, i);
2618
+ i = r2.end;
2619
+ attribute = r2.value;
2620
+ }
2621
+ }
2622
+ i = stripWS(selector, i);
2623
+ let action = "exists";
2624
+ let value = "";
2625
+ let ignoreCase = null;
2626
+ const opCode = selector.charCodeAt(i);
2627
+ if (opCode === 61) {
2628
+ action = "equals";
2629
+ i++;
2630
+ } else if (opCode === 33 && selector.charCodeAt(i + 1) === 61) {
2631
+ action = "not";
2632
+ i += 2;
2633
+ } else {
2634
+ const a = actionFromChar(opCode);
2635
+ if (a !== null && selector.charCodeAt(i + 1) === 61) {
2636
+ action = a;
2637
+ i += 2;
2638
+ }
2639
+ }
2640
+ if (action !== "exists") {
2641
+ i = stripWS(selector, i);
2642
+ const q = selector.charCodeAt(i);
2643
+ if (q === 34 || q === 39) {
2644
+ const end = findEndOfString(selector, i + 1, q);
2645
+ value = unescapeIfNeeded(selector.slice(i + 1, end));
2646
+ i = end + 1;
2647
+ } else {
2648
+ const r = readName(selector, i);
2649
+ value = r.value;
2650
+ i = r.end;
2651
+ }
2652
+ i = stripWS(selector, i);
2653
+ const flag = selector.charCodeAt(i);
2654
+ if (flag === 105 || flag === 73) {
2655
+ ignoreCase = true;
2656
+ i++;
2657
+ } else if (flag === 115 || flag === 83) {
2658
+ ignoreCase = false;
2659
+ i++;
2660
+ }
2661
+ }
2662
+ if (selector.charCodeAt(i) !== 93)
2663
+ throw new Error("Expected ]");
2664
+ i++;
2665
+ if (ignoreCase === null && !xmlMode && ATTRIBUTES_QUIRKS.has(attribute.toLowerCase()))
2666
+ ignoreCase = "quirks";
2667
+ tokens.push({
2668
+ type: "attribute",
2669
+ name: lowerCaseAttrs ? attribute.toLowerCase() : attribute,
2670
+ action,
2671
+ value,
2672
+ namespace: null,
2673
+ ignoreCase
2674
+ });
2675
+ return i;
2676
+ }
2677
+ function parsePseudo2(selector, idx, tokens, options) {
2678
+ if (selector.charCodeAt(idx + 1) === 58) {
2679
+ let i2 = idx + 2;
2680
+ const r2 = readName(selector, i2);
2681
+ i2 = r2.end;
2682
+ const name2 = r2.value.toLowerCase();
2683
+ let data = null;
2684
+ if (selector.charCodeAt(i2) === 40) {
2685
+ const end = findClose(selector, i2);
2686
+ data = selector.slice(i2 + 1, end).trim();
2687
+ i2 = end + 1;
2688
+ }
2689
+ tokens.push({ type: "pseudo-element", name: name2, data });
2690
+ return i2;
2691
+ }
2692
+ let i = idx + 1;
2693
+ const r = readName(selector, i);
2694
+ i = r.end;
2695
+ const name = r.value.toLowerCase();
2696
+ if (selector.charCodeAt(i) === 40) {
2697
+ const end = findClose(selector, i);
2698
+ const inner = selector.slice(i + 1, end);
2699
+ i = end + 1;
2700
+ if (name === "is" || name === "not" || name === "where" || name === "has" || name === "matches" || name === "-moz-any" || name === "-webkit-any") {
2701
+ const sub = [];
2702
+ parseSelectorImpl(sub, inner.trim(), options, 0);
2703
+ tokens.push({ type: "pseudo", name, data: sub });
2704
+ } else {
2705
+ tokens.push({ type: "pseudo", name, data: inner.trim() });
2706
+ }
2707
+ } else {
2708
+ tokens.push({ type: "pseudo", name, data: null });
2709
+ }
2710
+ return i;
2711
+ }
2712
+ function addTraversal(tokens, type) {
2713
+ if (tokens.length > 0 && tokens[tokens.length - 1].type === "descendant" && type !== "descendant")
2714
+ tokens.pop();
2715
+ if (tokens.length > 0 && tokens[tokens.length - 1].type === type)
2716
+ return;
2717
+ tokens.push({ type });
2718
+ }
2719
+ function findEndOfString(selector, start, qCode) {
2720
+ let i = start;
2721
+ const len = selector.length;
2722
+ while (i < len) {
2723
+ const c = selector.charCodeAt(i);
2724
+ if (c === 92) {
2725
+ i += 2;
2726
+ continue;
2727
+ }
2728
+ if (c === qCode)
2729
+ return i;
2730
+ i++;
2731
+ }
2732
+ throw new Error("Unterminated string");
2733
+ }
2734
+ function findClose(selector, openParen) {
2735
+ let depth = 1;
2736
+ let i = openParen + 1;
2737
+ const len = selector.length;
2738
+ while (i < len) {
2739
+ const c = selector.charCodeAt(i);
2740
+ if (c === 92) {
2741
+ i += 2;
2742
+ continue;
2743
+ }
2744
+ if (c === 34 || c === 39) {
2745
+ i = findEndOfString(selector, i + 1, c) + 1;
2746
+ continue;
2747
+ }
2748
+ if (c === 40)
2749
+ depth++;
2750
+ else if (c === 41) {
2751
+ depth--;
2752
+ if (depth === 0)
2753
+ return i;
2754
+ }
2755
+ i++;
2756
+ }
2757
+ throw new Error("Unterminated parenthesis");
2758
+ }
2759
+ // src/what/stringify.ts
2760
+ var COMBINATORS = {
2761
+ child: " > ",
2762
+ parent: " < ",
2763
+ sibling: " ~ ",
2764
+ adjacent: " + ",
2765
+ descendant: " ",
2766
+ "column-combinator": " || "
2767
+ };
2768
+ function stringify(selector) {
2769
+ return selector.map(stringifySegments).join(", ");
2770
+ }
2771
+ function stringifySegments(tokens) {
2772
+ return tokens.map((t, i) => stringifyOne(t, tokens[i - 1])).join("");
2773
+ }
2774
+ function stringifyOne(token, _prev) {
2775
+ switch (token.type) {
2776
+ case "tag":
2777
+ return `${nsPrefix(token.namespace)}${escapeIdent(token.name)}`;
2778
+ case "universal":
2779
+ return `${nsPrefix(token.namespace)}*`;
2780
+ case "attribute": {
2781
+ if (token.name === "id" && token.action === "equals" && !token.ignoreCase && !token.namespace)
2782
+ return `#${escapeIdent(token.value)}`;
2783
+ if (token.name === "class" && token.action === "element" && !token.ignoreCase && !token.namespace)
2784
+ return `.${escapeIdent(token.value)}`;
2785
+ let out = `[${nsPrefix(token.namespace)}${escapeIdent(token.name)}`;
2786
+ if (token.action !== "exists") {
2787
+ const op = ACTION_OP[token.action] ?? "=";
2788
+ out += op;
2789
+ out += `"${token.value.replace(/"/g, "\\\"")}"`;
2790
+ if (token.ignoreCase === true)
2791
+ out += " i";
2792
+ else if (token.ignoreCase === false)
2793
+ out += " s";
2794
+ }
2795
+ out += "]";
2796
+ return out;
2797
+ }
2798
+ case "pseudo":
2799
+ if (token.data === null)
2800
+ return `:${token.name}`;
2801
+ if (typeof token.data === "string")
2802
+ return `:${token.name}(${token.data})`;
2803
+ return `:${token.name}(${stringify(token.data)})`;
2804
+ case "pseudo-element":
2805
+ return token.data === null ? `::${token.name}` : `::${token.name}(${token.data})`;
2806
+ case "descendant":
2807
+ case "child":
2808
+ case "parent":
2809
+ case "sibling":
2810
+ case "adjacent":
2811
+ case "column-combinator":
2812
+ return COMBINATORS[token.type] ?? " ";
2813
+ }
2814
+ return "";
2815
+ }
2816
+ var ACTION_OP = {
2817
+ equals: "=",
2818
+ element: "~=",
2819
+ start: "^=",
2820
+ end: "$=",
2821
+ any: "*=",
2822
+ not: "!=",
2823
+ hyphen: "|="
2824
+ };
2825
+ function nsPrefix(ns) {
2826
+ if (ns === null)
2827
+ return "";
2828
+ if (ns === "")
2829
+ return "|";
2830
+ return `${escapeIdent(ns)}|`;
2831
+ }
2832
+ var RE_INVALID_ID_CHAR = /[^\w\u00B0-\uFFFF-]/g;
2833
+ function escapeIdent(name) {
2834
+ if (name === "")
2835
+ return "";
2836
+ return name.replace(RE_INVALID_ID_CHAR, (m) => `\\${m}`);
2837
+ }
2838
+ // src/what/traversal.ts
2839
+ var TRAVERSAL_TYPES = new Set(["adjacent", "child", "descendant", "parent", "sibling", "column-combinator"]);
2840
+ function isTraversal(token) {
2841
+ return TRAVERSAL_TYPES.has(token.type);
2842
+ }
2843
+ // src/what/types.ts
2844
+ var IgnoreCaseMode = {
2845
+ Unknown: null,
2846
+ QuirksMode: "quirks",
2847
+ IgnoreCase: true,
2848
+ CaseSensitive: false
2849
+ };
2850
+ // src/optimize/index.ts
2851
+ var exports_optimize = {};
2852
+ __export(exports_optimize, {
2853
+ syntax: () => syntax,
2854
+ specificityToString: () => specificityToString,
2855
+ specificity: () => specificity,
2856
+ removeComments: () => removeComments,
2857
+ minifyBlock: () => minifyBlock,
2858
+ minify: () => minify,
2859
+ dedupeDeclarations: () => dedupeDeclarations,
2860
+ compressTree: () => compressTree
2861
+ });
2862
+
2863
+ // src/optimize/clean/comment.ts
2864
+ function removeComments(ast, options = {}) {
2865
+ const exclamation = options.exclamation ?? false;
2866
+ let firstSeen = false;
2867
+ walk(ast, (node, item, list) => {
2868
+ if (node.type !== "Comment")
2869
+ return;
2870
+ const isExclamation = node.value.startsWith("!");
2871
+ if (exclamation === true && isExclamation)
2872
+ return;
2873
+ if (exclamation === "first-exclamation" && isExclamation && !firstSeen) {
2874
+ firstSeen = true;
2875
+ return;
2876
+ }
2877
+ if (item && list)
2878
+ list.remove(item);
2879
+ });
2880
+ }
2881
+ // src/optimize/clean/declaration.ts
2882
+ function dedupeDeclarations(ast) {
2883
+ walk(ast, (node) => {
2884
+ if (node.type !== "Block" && node.type !== "DeclarationList")
2885
+ return;
2886
+ if (!("children" in node) || !node.children)
2887
+ return;
2888
+ const list = node.children;
2889
+ let head = list.head;
2890
+ if (head == null || head.next == null)
2891
+ return;
2892
+ let declCount = 0;
2893
+ for (let it = head;it != null; it = it.next) {
2894
+ if (it.data.type === "Declaration") {
2895
+ declCount++;
2896
+ if (declCount >= 2)
2897
+ break;
2898
+ }
2899
+ }
2900
+ if (declCount < 2)
2901
+ return;
2902
+ const seen = new Map;
2903
+ const toRemove = [];
2904
+ for (let item = head;item != null; item = item.next) {
2905
+ const data = item.data;
2906
+ if (data.type !== "Declaration")
2907
+ continue;
2908
+ const key = data.property;
2909
+ const prev = seen.get(key);
2910
+ if (prev) {
2911
+ const prevImp = !!prev.decl.important;
2912
+ const curImp = !!data.important;
2913
+ if (curImp || prevImp === curImp) {
2914
+ toRemove.push(prev.item);
2915
+ seen.set(key, { item, decl: data });
2916
+ } else {
2917
+ toRemove.push(item);
2918
+ }
2919
+ } else {
2920
+ seen.set(key, { item, decl: data });
2921
+ }
2922
+ }
2923
+ for (const it of toRemove)
2924
+ list.remove(it);
2925
+ });
2926
+ }
2927
+ // src/optimize/compress/color.ts
2928
+ var NAMED_TO_HEX = {
2929
+ black: "#000",
2930
+ fuchsia: "#f0f",
2931
+ white: "#fff",
2932
+ red: "#f00",
2933
+ cyan: "#0ff",
2934
+ blue: "#00f",
2935
+ yellow: "#ff0",
2936
+ magenta: "#f0f",
2937
+ lime: "#0f0",
2938
+ silver: "#c0c0c0",
2939
+ gray: "#808080",
2940
+ maroon: "#800000",
2941
+ olive: "#808000",
2942
+ green: "#008000",
2943
+ purple: "#800080",
2944
+ teal: "#008080",
2945
+ navy: "#000080"
2946
+ };
2947
+ var HEX_TO_SHORT_NAME = {
2948
+ "#f00": "red",
2949
+ "#ff0000": "red",
2950
+ "#000080": "navy",
2951
+ "#008080": "teal"
2952
+ };
2953
+ function shortenHex(hex) {
2954
+ if (!hex.startsWith("#"))
2955
+ return hex;
2956
+ const body = hex.slice(1);
2957
+ if (body.length === 6) {
2958
+ if (body[0] === body[1] && body[2] === body[3] && body[4] === body[5])
2959
+ return `#${body[0]}${body[2]}${body[4]}`;
2960
+ }
2961
+ if (body.length === 8) {
2962
+ if (body[0] === body[1] && body[2] === body[3] && body[4] === body[5] && body[6] === body[7])
2963
+ return `#${body[0]}${body[2]}${body[4]}${body[6]}`;
2964
+ }
2965
+ return hex;
2966
+ }
2967
+ function colorNameToHex(name) {
2968
+ const lower = name.toLowerCase();
2969
+ return NAMED_TO_HEX[lower] ?? null;
2970
+ }
2971
+ function hexToShortName(hex) {
2972
+ const lower = hex.toLowerCase();
2973
+ return HEX_TO_SHORT_NAME[lower] ?? null;
2974
+ }
2975
+ function rgbToHex(r, g, b) {
2976
+ const hex = (r << 16 | g << 8 | b).toString(16).padStart(6, "0");
2977
+ return shortenHex(`#${hex}`);
2978
+ }
2979
+ var RGB_RE = /^rgba?\(\s*([+-]?\d*\.?\d+%?)\s*[,\s]\s*([+-]?\d*\.?\d+%?)\s*[,\s]\s*([+-]?\d*\.?\d+%?)\s*(?:[,/]\s*([+-]?\d*\.?\d+%?)\s*)?\)$/;
2980
+ function compressRgbToHex(value) {
2981
+ const m = RGB_RE.exec(value.trim());
2982
+ if (!m)
2983
+ return value;
2984
+ const r = parseChannel(m[1]);
2985
+ const g = parseChannel(m[2]);
2986
+ const b = parseChannel(m[3]);
2987
+ if (m[4] !== undefined && !isAlphaOne(m[4])) {
2988
+ return value;
2989
+ }
2990
+ return rgbToHex(r, g, b);
2991
+ }
2992
+ function isAlphaOne(s) {
2993
+ if (s.endsWith("%"))
2994
+ return Number.parseFloat(s) >= 100;
2995
+ return Number.parseFloat(s) >= 1;
2996
+ }
2997
+ function parseChannel(s) {
2998
+ if (s.endsWith("%"))
2999
+ return Math.max(0, Math.min(255, Math.round(Number.parseFloat(s) * 2.55)));
3000
+ return Math.max(0, Math.min(255, Math.round(Number.parseFloat(s))));
3001
+ }
3002
+
3003
+ // src/optimize/compress/number.ts
3004
+ var ZERO_UNITS = new Set([
3005
+ "px",
3006
+ "pt",
3007
+ "pc",
3008
+ "in",
3009
+ "cm",
3010
+ "mm",
3011
+ "q",
3012
+ "em",
3013
+ "rem",
3014
+ "ex",
3015
+ "ch",
3016
+ "cap",
3017
+ "ic",
3018
+ "lh",
3019
+ "rlh",
3020
+ "vw",
3021
+ "vh",
3022
+ "vi",
3023
+ "vb",
3024
+ "vmin",
3025
+ "vmax",
3026
+ "svw",
3027
+ "svh",
3028
+ "svi",
3029
+ "svb",
3030
+ "svmin",
3031
+ "svmax",
3032
+ "lvw",
3033
+ "lvh",
3034
+ "lvi",
3035
+ "lvb",
3036
+ "lvmin",
3037
+ "lvmax",
3038
+ "dvw",
3039
+ "dvh",
3040
+ "dvi",
3041
+ "dvb",
3042
+ "dvmin",
3043
+ "dvmax",
3044
+ "cqw",
3045
+ "cqh",
3046
+ "cqi",
3047
+ "cqb",
3048
+ "cqmin",
3049
+ "cqmax"
3050
+ ]);
3051
+ function compressNumber(value) {
3052
+ if (value.charCodeAt(0) === 43)
3053
+ value = value.slice(1);
3054
+ if (value.includes(".")) {
3055
+ let v = value.replace(/(\.\d*?)0+($|[eE])/, "$1$2");
3056
+ v = v.replace(/\.($|[eE])/, "$1");
3057
+ value = v;
3058
+ }
3059
+ if (value.startsWith("0.") && value.length > 2)
3060
+ value = value.slice(1);
3061
+ else if (value.startsWith("-0.") && value.length > 3)
3062
+ value = `-${value.slice(2)}`;
3063
+ if (value === "-0" || value === "-.0" || value === "-0.0")
3064
+ value = "0";
3065
+ return value;
3066
+ }
3067
+ function compressDimension(value, unit) {
3068
+ const compressed = compressNumber(value);
3069
+ if ((compressed === "0" || compressed === "-0") && ZERO_UNITS.has(unit.toLowerCase()))
3070
+ return { value: "0", unit: "" };
3071
+ return { value: compressed, unit };
3072
+ }
3073
+ function compressPercentage(value) {
3074
+ const compressed = compressNumber(value);
3075
+ return compressed;
3076
+ }
3077
+ function roundNumberString(value, precision) {
3078
+ const n = Number.parseFloat(value);
3079
+ if (!Number.isFinite(n))
3080
+ return value;
3081
+ const p = precision < 0 ? 0 : precision;
3082
+ return n.toFixed(p);
3083
+ }
3084
+
3085
+ // src/optimize/compress/index.ts
3086
+ var COLOR_PROPERTIES = new Set([
3087
+ "color",
3088
+ "background",
3089
+ "background-color",
3090
+ "border",
3091
+ "border-color",
3092
+ "border-top",
3093
+ "border-top-color",
3094
+ "border-right",
3095
+ "border-right-color",
3096
+ "border-bottom",
3097
+ "border-bottom-color",
3098
+ "border-left",
3099
+ "border-left-color",
3100
+ "border-block",
3101
+ "border-block-color",
3102
+ "border-block-start-color",
3103
+ "border-block-end-color",
3104
+ "border-inline",
3105
+ "border-inline-color",
3106
+ "border-inline-start-color",
3107
+ "border-inline-end-color",
3108
+ "outline",
3109
+ "outline-color",
3110
+ "caret-color",
3111
+ "fill",
3112
+ "stroke",
3113
+ "flood-color",
3114
+ "lighting-color",
3115
+ "stop-color",
3116
+ "column-rule",
3117
+ "column-rule-color",
3118
+ "text-decoration",
3119
+ "text-decoration-color",
3120
+ "text-emphasis",
3121
+ "text-emphasis-color",
3122
+ "text-shadow",
3123
+ "box-shadow",
3124
+ "accent-color",
3125
+ "scrollbar-color"
3126
+ ]);
3127
+ function isCompactableOperator(node) {
3128
+ if (!node || node.type !== "Operator")
3129
+ return false;
3130
+ const v = node.value;
3131
+ return v === ":" || v === "," || v === "/";
3132
+ }
3133
+ function compactContainerWhitespace(node) {
3134
+ const list = node.children;
3135
+ if (!list)
3136
+ return;
3137
+ while (list.head && list.head.data.type === "WhiteSpace")
3138
+ list.remove(list.head);
3139
+ while (list.tail && list.tail.data.type === "WhiteSpace")
3140
+ list.remove(list.tail);
3141
+ let cur = list.head;
3142
+ while (cur) {
3143
+ const nxt = cur.next;
3144
+ if (cur.data.type === "WhiteSpace") {
3145
+ const prevIsOp = cur.prev && isCompactableOperator(cur.prev.data);
3146
+ const nextIsOp = nxt && isCompactableOperator(nxt.data);
3147
+ if (prevIsOp || nextIsOp)
3148
+ list.remove(cur);
3149
+ }
3150
+ cur = nxt;
3151
+ }
3152
+ }
3153
+ function compressTree(ast, options = {}) {
3154
+ const fp = options.floatPrecision ?? null;
3155
+ const round = fp === null ? null : (s) => roundNumberString(s, fp);
3156
+ walk(ast, {
3157
+ enter(node, item, list) {
3158
+ switch (node.type) {
3159
+ case "Number": {
3160
+ const v = round ? round(node.value) : node.value;
3161
+ node.value = compressNumber(v);
3162
+ return;
3163
+ }
3164
+ case "Percentage": {
3165
+ const v = round ? round(node.value) : node.value;
3166
+ node.value = compressPercentage(v);
3167
+ return;
3168
+ }
3169
+ case "Dimension": {
3170
+ const v = round ? round(node.value) : node.value;
3171
+ const c = compressDimension(v, node.unit);
3172
+ node.value = c.value;
3173
+ node.unit = c.unit;
3174
+ return;
3175
+ }
3176
+ case "Hash": {
3177
+ const newName = shortenHex(`#${node.name}`).slice(1);
3178
+ node.name = newName;
3179
+ if (item && list && this.declaration && COLOR_PROPERTIES.has(this.declaration.property.toLowerCase())) {
3180
+ const short = hexToShortName(`#${newName}`);
3181
+ if (short && short.length < newName.length + 1) {
3182
+ const ident = { type: "Identifier", name: short, loc: node.loc };
3183
+ list.replace(item, list.createItem(ident));
3184
+ }
3185
+ }
3186
+ return;
3187
+ }
3188
+ case "Identifier": {
3189
+ if (!item || !list || !this.declaration)
3190
+ return;
3191
+ if (!COLOR_PROPERTIES.has(this.declaration.property.toLowerCase()))
3192
+ return;
3193
+ const hex = colorNameToHex(node.name);
3194
+ if (hex && hex.length < node.name.length) {
3195
+ const hashNode = { type: "Hash", name: hex.slice(1), loc: node.loc };
3196
+ list.replace(item, list.createItem(hashNode));
3197
+ }
3198
+ return;
3199
+ }
3200
+ case "Url":
3201
+ return;
3202
+ case "Function": {
3203
+ const lname = node.name.toLowerCase();
3204
+ if ((lname === "rgb" || lname === "rgba") && item && list)
3205
+ node.__rgbReplaceCandidate = true;
3206
+ }
3207
+ }
3208
+ },
3209
+ leave(node, item, list) {
3210
+ if (node.type === "Parentheses" || node.type === "Function" || node.type === "Value")
3211
+ compactContainerWhitespace(node);
3212
+ if (node.type === "Function" && node.__rgbReplaceCandidate && item && list) {
3213
+ const text = generate(node);
3214
+ const replacement = compressRgbToHex(text);
3215
+ if (replacement !== text && replacement.startsWith("#")) {
3216
+ const hashNode = { type: "Hash", name: replacement.slice(1), loc: node.loc };
3217
+ list.replace(item, list.createItem(hashNode));
3218
+ }
3219
+ }
3220
+ }
3221
+ });
3222
+ }
3223
+ // src/optimize/minify.ts
3224
+ function minify(source, options = {}) {
3225
+ const ast = parse(source, { context: "stylesheet" });
3226
+ return runPipeline(ast, options);
3227
+ }
3228
+ function minifyBlock(source, options = {}) {
3229
+ const ast = parse(source, { context: "declarationList" });
3230
+ return runPipeline(ast, options);
3231
+ }
3232
+ function runPipeline(ast, options) {
3233
+ if (options.comments === false) {
3234
+ removeComments(ast, { exclamation: false });
3235
+ } else if (options.comments === "first-exclamation") {
3236
+ removeComments(ast, { exclamation: "first-exclamation" });
3237
+ } else {
3238
+ removeComments(ast, { exclamation: true });
3239
+ }
3240
+ compressTree(ast, { floatPrecision: options.floatPrecision ?? null });
3241
+ dedupeDeclarations(ast);
3242
+ return { css: generate(ast), ast };
3243
+ }
3244
+ // src/optimize/specificity.ts
3245
+ function specificity(input) {
3246
+ const result = [0, 0, 0];
3247
+ if (typeof input === "string") {
3248
+ const ast = parse2(input);
3249
+ visitWhat(ast, result);
3250
+ return result;
3251
+ }
3252
+ if (Array.isArray(input)) {
3253
+ if (input.length === 0)
3254
+ return result;
3255
+ if (Array.isArray(input[0]))
3256
+ visitWhat(input, result);
3257
+ else
3258
+ visitWhatGroup(input, result);
3259
+ return result;
3260
+ }
3261
+ visit(input, result);
3262
+ return result;
3263
+ }
3264
+ function visit(node, result) {
3265
+ switch (node.type) {
3266
+ case "IdSelector":
3267
+ result[0]++;
3268
+ return;
3269
+ case "ClassSelector":
3270
+ case "AttributeSelector":
3271
+ result[1]++;
3272
+ return;
3273
+ case "TypeSelector":
3274
+ if (node.name !== "*")
3275
+ result[2]++;
3276
+ return;
3277
+ case "PseudoClassSelector": {
3278
+ const name = node.name.toLowerCase();
3279
+ if (name === "is" || name === "matches" || name === "-moz-any" || name === "-webkit-any" || name === "not" || name === "has") {
3280
+ if (node.children) {
3281
+ const selectors = [];
3282
+ for (const inner of node.children) {
3283
+ if (inner.type === "SelectorList" && "children" in inner && inner.children) {
3284
+ for (const s of inner.children)
3285
+ selectors.push(s);
3286
+ } else if (inner.type === "Selector") {
3287
+ selectors.push(inner);
3288
+ }
3289
+ }
3290
+ let max = [0, 0, 0];
3291
+ for (const sel of selectors) {
3292
+ const s = specificity(sel);
3293
+ if (compareSpec(s, max) > 0)
3294
+ max = s;
3295
+ }
3296
+ result[0] += max[0];
3297
+ result[1] += max[1];
3298
+ result[2] += max[2];
3299
+ }
3300
+ return;
3301
+ }
3302
+ if (name === "where")
3303
+ return;
3304
+ result[1]++;
3305
+ return;
3306
+ }
3307
+ case "PseudoElementSelector":
3308
+ result[2]++;
3309
+ return;
3310
+ case "Selector":
3311
+ case "SelectorList":
3312
+ case "AtrulePrelude":
3313
+ if ("children" in node && node.children) {
3314
+ for (const child of node.children)
3315
+ visit(child, result);
3316
+ }
3317
+ return;
3318
+ case "NestingSelector":
3319
+ return;
3320
+ }
3321
+ }
3322
+ function visitWhat(groups, result) {
3323
+ for (const g of groups)
3324
+ visitWhatGroup(g, result);
3325
+ }
3326
+ function visitWhatGroup(tokens, result) {
3327
+ for (const t of tokens) {
3328
+ switch (t.type) {
3329
+ case "tag":
3330
+ if (t.name !== "*")
3331
+ result[2]++;
3332
+ break;
3333
+ case "attribute":
3334
+ if (t.name === "id" && t.action === "equals")
3335
+ result[0]++;
3336
+ else
3337
+ result[1]++;
3338
+ break;
3339
+ case "pseudo": {
3340
+ const name = t.name.toLowerCase();
3341
+ if (name === "is" || name === "matches" || name === "not" || name === "has" || name === "-moz-any" || name === "-webkit-any") {
3342
+ if (Array.isArray(t.data)) {
3343
+ let max = [0, 0, 0];
3344
+ for (const inner of t.data) {
3345
+ const s = [0, 0, 0];
3346
+ visitWhatGroup(inner, s);
3347
+ if (compareSpec(s, max) > 0)
3348
+ max = s;
3349
+ }
3350
+ result[0] += max[0];
3351
+ result[1] += max[1];
3352
+ result[2] += max[2];
3353
+ }
3354
+ break;
3355
+ }
3356
+ if (name === "where")
3357
+ break;
3358
+ result[1]++;
3359
+ break;
3360
+ }
3361
+ case "pseudo-element":
3362
+ result[2]++;
3363
+ break;
3364
+ }
3365
+ }
3366
+ }
3367
+ function compareSpec(a, b) {
3368
+ for (let i = 0;i < 3; i++) {
3369
+ if (a[i] !== b[i])
3370
+ return a[i] - b[i];
3371
+ }
3372
+ return 0;
3373
+ }
3374
+ function specificityToString(s) {
3375
+ return s.join(",");
3376
+ }
3377
+ // src/optimize/index.ts
3378
+ var syntax = {
3379
+ specificity
3380
+ };
3381
+ export {
3382
+ syntax,
3383
+ specificityToString,
3384
+ specificity,
3385
+ removeComments,
3386
+ minifyBlock,
3387
+ minify,
3388
+ dedupeDeclarations,
3389
+ compressTree
3390
+ };