@tbela99/css-parser 0.0.1-alpha4 → 0.0.1-rc1

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,796 @@
1
+ import { isIdentStart, isIdent, isFunction, isWhiteSpace } from '../parser/utils/syntax.js';
2
+ import { PropertyList } from '../parser/declaration/list.js';
3
+ import { eq } from '../parser/utils/eq.js';
4
+ import { render } from '../renderer/render.js';
5
+ import '../renderer/utils/color.js';
6
+
7
+ const combinators = ['+', '>', '~'];
8
+ const notEndingWith = ['(', '['].concat(combinators);
9
+ function minify(ast, options = {}, recursive = false) {
10
+ function wrapNodes(previous, node, match, ast, i, nodeIndex) {
11
+ // @ts-ignore
12
+ let pSel = match.selector1.reduce(reducer, []).join(',');
13
+ // @ts-ignore
14
+ let nSel = match.selector2.reduce(reducer, []).join(',');
15
+ // @ts-ignore
16
+ const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
17
+ // @ts-ignore
18
+ Object.defineProperty(wrapper, 'raw', {
19
+ enumerable: false,
20
+ writable: true,
21
+ // @ts-ignore
22
+ value: match.match.map(t => t.slice())
23
+ });
24
+ if (pSel == '&' || pSel === '') {
25
+ // @ts-ignore
26
+ wrapper.chi.push(...previous.chi);
27
+ // @ts-ignore
28
+ if ((nSel == '&' || nSel === '') && hasOnlyDeclarations(previous)) {
29
+ // @ts-ignore
30
+ wrapper.chi.push(...node.chi);
31
+ }
32
+ else {
33
+ // @ts-ignore
34
+ wrapper.chi.push(node);
35
+ }
36
+ }
37
+ else {
38
+ // @ts-ignore
39
+ wrapper.chi.push(previous, node);
40
+ }
41
+ // @ts-ignore
42
+ ast.chi.splice(i, 1, wrapper);
43
+ // @ts-ignore
44
+ ast.chi.splice(nodeIndex, 1);
45
+ // @ts-ignore
46
+ previous.sel = pSel;
47
+ // @ts-ignore
48
+ previous.raw = match.selector1;
49
+ // @ts-ignore
50
+ node.sel = nSel;
51
+ // @ts-ignore
52
+ node.raw = match.selector2;
53
+ reduceRuleSelector(wrapper);
54
+ return wrapper;
55
+ }
56
+ function reducer(acc, curr, index, array) {
57
+ // trim :is()
58
+ if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
59
+ curr = curr.slice(1, -1);
60
+ }
61
+ if (curr[0] == '&') {
62
+ if (curr[1] == ' ' && !isIdent(curr[2]) && !isFunction(curr[2])) {
63
+ curr.splice(0, 2);
64
+ }
65
+ else if (combinators.includes(curr[1])) {
66
+ curr.splice(0, 1);
67
+ }
68
+ }
69
+ else if (ast.typ == 'Rule' && (isIdent(curr[0]) || isFunction(curr[0]))) {
70
+ curr.unshift('&', ' ');
71
+ }
72
+ acc.push(curr.join(''));
73
+ return acc;
74
+ }
75
+ function diff(n1, n2, options = {}) {
76
+ let node1 = n1;
77
+ let node2 = n2;
78
+ let exchanged = false;
79
+ if (node1.chi.length > node2.chi.length) {
80
+ const t = node1;
81
+ node1 = node2;
82
+ node2 = t;
83
+ exchanged = true;
84
+ }
85
+ let i = node1.chi.length;
86
+ let j = node2.chi.length;
87
+ if (i == 0 || j == 0) {
88
+ // @ts-ignore
89
+ return null;
90
+ }
91
+ // @ts-ignore
92
+ const raw1 = node1.raw;
93
+ // @ts-ignore
94
+ const raw2 = node2.raw;
95
+ // @ts-ignore
96
+ node1 = { ...node1, chi: node1.chi.slice() };
97
+ node2 = { ...node2, chi: node2.chi.slice() };
98
+ if (raw1 != null) {
99
+ Object.defineProperty(node1, 'raw', { enumerable: false, writable: true, value: raw1 });
100
+ }
101
+ if (raw2 != null) {
102
+ Object.defineProperty(node2, 'raw', { enumerable: false, writable: true, value: raw2 });
103
+ }
104
+ const intersect = [];
105
+ while (i--) {
106
+ if (node1.chi[i].typ == 'Comment') {
107
+ continue;
108
+ }
109
+ j = node2.chi.length;
110
+ if (j == 0) {
111
+ break;
112
+ }
113
+ while (j--) {
114
+ if (node2.chi[j].typ == 'Comment') {
115
+ continue;
116
+ }
117
+ if (node1.chi[i].nam == node2.chi[j].nam) {
118
+ if (eq(node1.chi[i], node2.chi[j])) {
119
+ intersect.push(node1.chi[i]);
120
+ node1.chi.splice(i, 1);
121
+ node2.chi.splice(j, 1);
122
+ break;
123
+ }
124
+ }
125
+ }
126
+ }
127
+ // @ts-ignore
128
+ const result = (intersect.length == 0 ? null : {
129
+ ...node1,
130
+ // @ts-ignore
131
+ sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(','),
132
+ chi: intersect.reverse()
133
+ });
134
+ if (result == null || [n1, n2].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0) <= [node1, node2, result].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0)) {
135
+ // @ts-ignore
136
+ return null;
137
+ }
138
+ return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node2 : node2 };
139
+ }
140
+ function matchSelectors(selector1, selector2, parentType) {
141
+ let match = [[]];
142
+ const j = Math.min(selector1.reduce((acc, curr) => Math.min(acc, curr.length), selector1.length > 0 ? selector1[0].length : 0), selector2.reduce((acc, curr) => Math.min(acc, curr.length), selector2.length > 0 ? selector2[0].length : 0));
143
+ let i = 0;
144
+ let k;
145
+ let l;
146
+ let token;
147
+ let matching = true;
148
+ let matchFunction = 0;
149
+ let inAttr = 0;
150
+ for (; i < j; i++) {
151
+ k = 0;
152
+ token = selector1[0][i];
153
+ for (; k < selector1.length; k++) {
154
+ if (selector1[k][i] != token) {
155
+ matching = false;
156
+ break;
157
+ }
158
+ }
159
+ if (matching) {
160
+ l = 0;
161
+ for (; l < selector2.length; l++) {
162
+ if (selector2[l][i] != token) {
163
+ matching = false;
164
+ break;
165
+ }
166
+ }
167
+ }
168
+ if (!matching) {
169
+ break;
170
+ }
171
+ if (token == ',') {
172
+ match.push([]);
173
+ }
174
+ else {
175
+ if (token.endsWith('(')) {
176
+ matchFunction++;
177
+ }
178
+ if (token.endsWith('[')) {
179
+ inAttr++;
180
+ }
181
+ else if (token == ')') {
182
+ matchFunction--;
183
+ }
184
+ else if (token == ']') {
185
+ inAttr--;
186
+ }
187
+ match.at(-1).push(token);
188
+ }
189
+ }
190
+ // invalid function
191
+ if (matchFunction != 0 || inAttr != 0) {
192
+ return null;
193
+ }
194
+ if (parentType != 'Rule') {
195
+ for (const part of match) {
196
+ if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
197
+ return null;
198
+ }
199
+ }
200
+ }
201
+ if (match.length > 1) {
202
+ console.error(`unsupported multilevel matching`);
203
+ console.error({ match, selector1, selector2 });
204
+ return null;
205
+ }
206
+ for (const part of match) {
207
+ while (part.length > 0) {
208
+ const token = part.at(-1);
209
+ if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
210
+ part.pop();
211
+ continue;
212
+ }
213
+ break;
214
+ }
215
+ }
216
+ if (match.every(t => t.length == 0)) {
217
+ return null;
218
+ }
219
+ if (eq([['&']], match)) {
220
+ return null;
221
+ }
222
+ function reduce(acc, curr) {
223
+ if (acc === null) {
224
+ return null;
225
+ }
226
+ let hasCompoundSelector = true;
227
+ curr = curr.slice(match[0].length);
228
+ while (curr.length > 0) {
229
+ if (curr[0] == ' ') {
230
+ hasCompoundSelector = false;
231
+ curr.unshift('&');
232
+ continue;
233
+ }
234
+ break;
235
+ }
236
+ // invalid function match
237
+ if (curr.length > 0 && curr[0].endsWith('(') && curr.at(-1) != ')') {
238
+ return null;
239
+ }
240
+ if (curr.length == 1 && combinators.includes(curr[0].charAt(0))) {
241
+ return null;
242
+ }
243
+ if (hasCompoundSelector && curr.length > 0) {
244
+ hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
245
+ }
246
+ if (curr[0] == ':is(') {
247
+ let inFunction = 0;
248
+ let canReduce = true;
249
+ const isCompound = curr.reduce((acc, token, index) => {
250
+ if (index == 0) {
251
+ inFunction++;
252
+ canReduce = curr[1] == '&';
253
+ }
254
+ else if (token.endsWith('(')) {
255
+ if (inFunction == 0) {
256
+ canReduce = false;
257
+ }
258
+ inFunction++;
259
+ }
260
+ else if (token == ')') {
261
+ inFunction--;
262
+ }
263
+ else if (token == ',') {
264
+ if (!canReduce) {
265
+ canReduce = curr[index + 1] == '&';
266
+ }
267
+ acc.push([]);
268
+ }
269
+ else
270
+ acc.at(-1)?.push(token);
271
+ return acc;
272
+ }, [[]]);
273
+ if (inFunction > 0) {
274
+ canReduce = false;
275
+ }
276
+ if (canReduce) {
277
+ curr = isCompound.reduce((acc, curr) => {
278
+ if (acc.length > 0) {
279
+ acc.push(',');
280
+ }
281
+ acc.push(...curr);
282
+ return acc;
283
+ }, []);
284
+ }
285
+ }
286
+ // @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
287
+ acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
288
+ return acc;
289
+ }
290
+ // @ts-ignore
291
+ selector1 = selector1.reduce(reduce, []);
292
+ // @ts-ignore
293
+ selector2 = selector2.reduce(reduce, []);
294
+ return selector1 == null || selector2 == null ? null : {
295
+ eq: eq(selector1, selector2),
296
+ match,
297
+ selector1,
298
+ selector2
299
+ };
300
+ }
301
+ // @ts-ignore
302
+ if (('chi' in ast) && ast.chi?.length > 0) {
303
+ let i = 0;
304
+ let previous;
305
+ let node;
306
+ let nodeIndex;
307
+ // @ts-ignore
308
+ for (; i < ast.chi.length; i++) {
309
+ // @ts-ignore
310
+ if (ast.chi[i].typ == 'Comment') {
311
+ continue;
312
+ }
313
+ // @ts-ignore
314
+ node = ast.chi[i];
315
+ // @ts-ignore
316
+ if (previous == node) {
317
+ // console.error('idem!');
318
+ // @ts-ignore
319
+ ast.chi.splice(i, 1);
320
+ i--;
321
+ continue;
322
+ }
323
+ if (node.typ == 'AtRule' && node.nam == 'font-face') {
324
+ continue;
325
+ }
326
+ if (node.typ == 'AtRule' && node.val == 'all') {
327
+ // @ts-ignore
328
+ ast.chi?.splice(i, 1, ...node.chi);
329
+ i--;
330
+ continue;
331
+ }
332
+ // @ts-ignore
333
+ if (node.typ == 'Rule') {
334
+ reduceRuleSelector(node);
335
+ let wrapper;
336
+ let match;
337
+ // @ts-ignore
338
+ if (options.nestingRules) {
339
+ // @ts-ignore
340
+ if (previous?.typ == 'Rule') {
341
+ // @ts-ignore
342
+ reduceRuleSelector(previous);
343
+ // @ts-ignore
344
+ match = matchSelectors(previous.raw, node.raw, ast.typ);
345
+ // @ts-ignore
346
+ if (match != null) {
347
+ // @ts-ignore
348
+ wrapper = wrapNodes(previous, node, match, ast, i, nodeIndex);
349
+ nodeIndex = i - 1;
350
+ // @ts-ignore
351
+ previous = ast.chi[nodeIndex];
352
+ }
353
+ }
354
+ // @ts-ignore
355
+ if (wrapper != null) {
356
+ // @ts-ignore
357
+ while (i < ast.chi.length) {
358
+ // @ts-ignore
359
+ const nextNode = ast.chi[i];
360
+ // @ts-ignore
361
+ if (nextNode.typ != 'Rule') {
362
+ // i--;
363
+ // previous = wrapper;
364
+ // nodeIndex = i;
365
+ break;
366
+ }
367
+ reduceRuleSelector(nextNode);
368
+ // @ts-ignore
369
+ match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ);
370
+ // @ts-ignore
371
+ if (match == null) {
372
+ break;
373
+ }
374
+ // @ts-ignore
375
+ wrapper = wrapNodes(wrapper, nextNode, match, ast, i, nodeIndex);
376
+ }
377
+ nodeIndex = --i;
378
+ // @ts-ignore
379
+ previous = ast.chi[nodeIndex];
380
+ minify(wrapper, options, recursive);
381
+ continue;
382
+ }
383
+ // @ts-ignore
384
+ else if (node.optimized != null &&
385
+ // @ts-ignore
386
+ node.optimized.match &&
387
+ // @ts-ignore
388
+ node.optimized.selector.length > 1) {
389
+ // @ts-ignore
390
+ wrapper = { ...node, chi: [], sel: node.optimized.optimized[0] };
391
+ // @ts-ignore
392
+ Object.defineProperty(wrapper, 'raw', {
393
+ enumerable: false,
394
+ writable: true,
395
+ // @ts-ignore
396
+ value: [[node.optimized.optimized[0]]]
397
+ });
398
+ // @ts-ignore
399
+ node.sel = node.optimized.selector.reduce(reducer, []).join(',');
400
+ // @ts-ignore
401
+ node.raw = node.optimized.selector.slice();
402
+ // @ts-ignore
403
+ wrapper.chi.push(node);
404
+ // @ts-ignore
405
+ ast.chi.splice(i, 1, wrapper);
406
+ node = wrapper;
407
+ }
408
+ }
409
+ // @ts-ignore
410
+ else if (node.optimized?.match) {
411
+ let wrap = true;
412
+ // @ts-ignore
413
+ const selector = node.optimized.selector.reduce((acc, curr) => {
414
+ if (curr[0] == '&') {
415
+ if (curr[1] == ' ') {
416
+ curr.splice(0, 2);
417
+ }
418
+ else {
419
+ if (ast.typ != 'Rule' && combinators.includes(curr[1])) {
420
+ wrap = false;
421
+ }
422
+ else {
423
+ curr.splice(0, 1);
424
+ }
425
+ }
426
+ }
427
+ else if (combinators.includes(curr[0])) {
428
+ curr.unshift('&');
429
+ wrap = false;
430
+ }
431
+ // @ts-ignore
432
+ acc.push(curr);
433
+ return acc;
434
+ }, []);
435
+ if (!wrap) {
436
+ wrap = selector.some(s => s[0] != '&');
437
+ }
438
+ const rule = selector.map(s => {
439
+ if (s[0] == '&') {
440
+ // @ts-ignore
441
+ s[0] = node.optimized.optimized[0];
442
+ }
443
+ return s.join('');
444
+ }).join(',');
445
+ // @ts-ignore
446
+ node.sel = wrap ? node.optimized.optimized[0] + `:is(${rule})` : rule;
447
+ }
448
+ }
449
+ // @ts-ignore
450
+ if (previous != null && 'chi' in previous && ('chi' in node)) {
451
+ // @ts-ignore
452
+ if (previous.typ == node.typ) {
453
+ let shouldMerge = true;
454
+ // @ts-ignore
455
+ let k = previous.chi.length;
456
+ while (k-- > 0) {
457
+ // @ts-ignore
458
+ if (previous.chi[k].typ == 'Comment') {
459
+ continue;
460
+ }
461
+ // @ts-ignore
462
+ shouldMerge = previous.chi[k].typ == 'Declaration';
463
+ break;
464
+ }
465
+ if (shouldMerge) {
466
+ // @ts-ignore
467
+ if ((node.typ == 'Rule' && node.sel == previous.sel) ||
468
+ // @ts-ignore
469
+ (node.typ == 'AtRule') && node.val != 'font-face' && node.val == previous.val) {
470
+ // @ts-ignore
471
+ node.chi.unshift(...previous.chi);
472
+ // @ts-ignore
473
+ ast.chi.splice(nodeIndex, 1);
474
+ // @ts-ignore
475
+ if (hasDeclaration(node)) {
476
+ // @ts-ignore
477
+ minifyRule(node);
478
+ }
479
+ else {
480
+ minify(node, options, recursive);
481
+ }
482
+ i--;
483
+ previous = node;
484
+ nodeIndex = i;
485
+ continue;
486
+ }
487
+ else if (node.typ == 'Rule' && previous?.typ == 'Rule') {
488
+ const intersect = diff(previous, node, options);
489
+ if (intersect != null) {
490
+ if (intersect.node1.chi.length == 0) {
491
+ // @ts-ignore
492
+ ast.chi.splice(i--, 1);
493
+ // @ts-ignore
494
+ node = ast.chi[i];
495
+ }
496
+ else {
497
+ // @ts-ignore
498
+ ast.chi.splice(i, 1, intersect.node1);
499
+ node = intersect.node1;
500
+ }
501
+ if (intersect.node2.chi.length == 0) {
502
+ // @ts-ignore
503
+ ast.chi.splice(nodeIndex, 1, intersect.result);
504
+ previous = intersect.result;
505
+ }
506
+ else {
507
+ // @ts-ignore
508
+ ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
509
+ previous = intersect.result;
510
+ // @ts-ignore
511
+ i = nodeIndex;
512
+ }
513
+ }
514
+ }
515
+ }
516
+ }
517
+ // @ts-ignore
518
+ if (recursive && previous != node) {
519
+ // @ts-ignore
520
+ if (hasDeclaration(previous)) {
521
+ // @ts-ignore
522
+ minifyRule(previous);
523
+ }
524
+ else {
525
+ minify(previous, options, recursive);
526
+ }
527
+ }
528
+ }
529
+ previous = node;
530
+ nodeIndex = i;
531
+ }
532
+ // @ts-ignore
533
+ if (recursive && node != null && ('chi' in node)) {
534
+ // @ts-ignore
535
+ if (node.chi.some(n => n.typ == 'Declaration')) {
536
+ minifyRule(node);
537
+ }
538
+ else {
539
+ // @ts-ignore
540
+ if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
541
+ minify(node, options, recursive);
542
+ }
543
+ }
544
+ }
545
+ }
546
+ return ast;
547
+ }
548
+ function reduceSelector(selector) {
549
+ if (selector.length == 0) {
550
+ return null;
551
+ }
552
+ const optimized = [];
553
+ const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
554
+ let i = 0;
555
+ let j;
556
+ let match;
557
+ for (; i < k; i++) {
558
+ const item = selector[0][i];
559
+ match = true;
560
+ for (j = 1; j < selector.length; j++) {
561
+ if (item != selector[j][i]) {
562
+ match = false;
563
+ break;
564
+ }
565
+ }
566
+ if (!match) {
567
+ break;
568
+ }
569
+ optimized.push(item);
570
+ }
571
+ while (optimized.length > 0) {
572
+ const last = optimized.at(-1);
573
+ if ((last == ' ' || combinators.includes(last))) {
574
+ optimized.pop();
575
+ continue;
576
+ }
577
+ break;
578
+ }
579
+ selector.forEach((selector) => selector.splice(0, optimized.length));
580
+ // combinator
581
+ if (combinators.includes(optimized.at(-1))) {
582
+ const combinator = optimized.pop();
583
+ selector.forEach(selector => selector.unshift(combinator));
584
+ }
585
+ let reducible = optimized.length == 1;
586
+ if (optimized[0] == '&' && optimized[1] == ' ') {
587
+ optimized.splice(0, 2);
588
+ }
589
+ if (optimized.length == 0 ||
590
+ (optimized[0].charAt(0) == '&' ||
591
+ selector.length == 1)) {
592
+ return {
593
+ match: false,
594
+ optimized,
595
+ selector: selector.map(selector => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : selector),
596
+ reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0]))
597
+ };
598
+ }
599
+ return {
600
+ match: true,
601
+ optimized,
602
+ selector: selector.reduce((acc, curr) => {
603
+ let hasCompound = true;
604
+ if (hasCompound && curr.length > 0) {
605
+ hasCompound = !['&'].concat(combinators).includes(curr[0].charAt(0));
606
+ }
607
+ // @ts-ignore
608
+ if (hasCompound && curr[0] == ' ') {
609
+ hasCompound = false;
610
+ curr.unshift('&');
611
+ }
612
+ if (curr.length == 0) {
613
+ curr.push('&');
614
+ hasCompound = false;
615
+ }
616
+ if (reducible) {
617
+ const chr = curr[0].charAt(0);
618
+ // @ts-ignore
619
+ reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
620
+ }
621
+ acc.push(hasCompound ? ['&'].concat(curr) : curr);
622
+ return acc;
623
+ }, []),
624
+ reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
625
+ };
626
+ }
627
+ function hasOnlyDeclarations(node) {
628
+ let k = node.chi.length;
629
+ while (k--) {
630
+ if (node.chi[k].typ == 'Comment') {
631
+ continue;
632
+ }
633
+ return node.chi[k].typ == 'Declaration';
634
+ }
635
+ return true;
636
+ }
637
+ function hasDeclaration(node) {
638
+ // @ts-ignore
639
+ for (let i = 0; i < node.chi?.length; i++) {
640
+ // @ts-ignore
641
+ if (node.chi[i].typ == 'Comment') {
642
+ continue;
643
+ }
644
+ // @ts-ignore
645
+ return node.chi[i].typ == 'Declaration';
646
+ }
647
+ return true;
648
+ }
649
+ function minifyRule(ast) {
650
+ // @ts-ignore
651
+ if (!('chi' in ast) || ast.chi?.length <= 1) {
652
+ return ast;
653
+ }
654
+ // @ts-ignore
655
+ const j = ast.chi.length;
656
+ let k = 0;
657
+ let properties = new PropertyList();
658
+ // @ts-ignore
659
+ for (; k < j; k++) {
660
+ // @ts-ignore
661
+ const node = ast.chi[k];
662
+ if (node.typ == 'Comment' || node.typ == 'Declaration') {
663
+ properties.add(node);
664
+ continue;
665
+ }
666
+ break;
667
+ }
668
+ // @ts-ignore
669
+ ast.chi = [...properties].concat(ast.chi.slice(k));
670
+ return ast;
671
+ }
672
+ function splitRule(buffer) {
673
+ const result = [[]];
674
+ let str = '';
675
+ for (let i = 0; i < buffer.length; i++) {
676
+ let chr = buffer.charAt(i);
677
+ if (isWhiteSpace(chr.charCodeAt(0))) {
678
+ let k = i;
679
+ while (k + 1 < buffer.length) {
680
+ if (isWhiteSpace(buffer[k + 1].charCodeAt(0))) {
681
+ k++;
682
+ continue;
683
+ }
684
+ break;
685
+ }
686
+ if (str !== '') {
687
+ // @ts-ignore
688
+ result.at(-1).push(str);
689
+ str = '';
690
+ }
691
+ // @ts-ignore
692
+ if (result.at(-1).length > 0) {
693
+ // @ts-ignore
694
+ result.at(-1).push(' ');
695
+ }
696
+ i = k;
697
+ continue;
698
+ }
699
+ if (chr == ',') {
700
+ if (str !== '') {
701
+ // @ts-ignore
702
+ result.at(-1).push(str);
703
+ str = '';
704
+ }
705
+ result.push([]);
706
+ continue;
707
+ }
708
+ str += chr;
709
+ if (chr == '\\') {
710
+ str += buffer.charAt(++i);
711
+ continue;
712
+ }
713
+ if (chr == '"' || chr == "'") {
714
+ let k = i;
715
+ while (++k < buffer.length) {
716
+ chr = buffer.charAt(k);
717
+ str += chr;
718
+ if (chr == '//') {
719
+ str += buffer.charAt(++k);
720
+ continue;
721
+ }
722
+ if (chr == buffer.charAt(i)) {
723
+ break;
724
+ }
725
+ }
726
+ continue;
727
+ }
728
+ if (chr == '(' || chr == '[') {
729
+ const open = chr;
730
+ const close = chr == '(' ? ')' : ']';
731
+ let inParens = 1;
732
+ let k = i;
733
+ while (++k < buffer.length) {
734
+ chr = buffer.charAt(k);
735
+ if (chr == '\\') {
736
+ str += buffer.slice(k, k + 2);
737
+ k++;
738
+ continue;
739
+ }
740
+ str += chr;
741
+ if (chr == open) {
742
+ inParens++;
743
+ }
744
+ else if (chr == close) {
745
+ inParens--;
746
+ }
747
+ if (inParens == 0) {
748
+ break;
749
+ }
750
+ }
751
+ i = k;
752
+ }
753
+ }
754
+ if (str !== '') {
755
+ // @ts-ignore
756
+ result.at(-1).push(str);
757
+ }
758
+ return result;
759
+ }
760
+ function reduceRuleSelector(node) {
761
+ if (node.raw == null) {
762
+ Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: splitRule(node.sel) });
763
+ }
764
+ // @ts-ignore
765
+ // if (node.raw != null) {
766
+ // @ts-ignore
767
+ let optimized = reduceSelector(node.raw.reduce((acc, curr) => {
768
+ acc.push(curr.slice());
769
+ return acc;
770
+ }, []));
771
+ if (optimized != null) {
772
+ Object.defineProperty(node, 'optimized', { enumerable: false, writable: true, value: optimized });
773
+ }
774
+ if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
775
+ const raw = [
776
+ [
777
+ optimized.optimized[0], ':is('
778
+ ].concat(optimized.selector.reduce((acc, curr) => {
779
+ if (acc.length > 0) {
780
+ acc.push(',');
781
+ }
782
+ acc.push(...curr);
783
+ return acc;
784
+ }, [])).concat(')')
785
+ ];
786
+ const sel = raw[0].join('');
787
+ if (sel.length < node.sel.length) {
788
+ node.sel = sel;
789
+ // node.raw = raw;
790
+ Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
791
+ }
792
+ }
793
+ // }
794
+ }
795
+
796
+ export { combinators, hasDeclaration, minify, minifyRule, reduceSelector };