@tbela99/css-parser 0.0.1-alpha3 → 0.0.1-alpha5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -53,7 +53,7 @@ function isIdent(name) {
53
53
  // -
54
54
  if (codepoint == 0x2d) {
55
55
  const nextCodepoint = name.charCodeAt(1);
56
- if (nextCodepoint == null) {
56
+ if (Number.isNaN(nextCodepoint)) {
57
57
  return false;
58
58
  }
59
59
  // -
@@ -102,6 +102,9 @@ function isNumber(name) {
102
102
  let codepoint = name.charCodeAt(0);
103
103
  let i = 0;
104
104
  const j = name.length;
105
+ if (j == 1 && !isDigit(codepoint)) {
106
+ return false;
107
+ }
105
108
  // '+' '-'
106
109
  if ([0x2b, 0x2d].includes(codepoint)) {
107
110
  i++;
@@ -245,7 +248,9 @@ function isNewLine(codepoint) {
245
248
  return codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
246
249
  }
247
250
  function isWhiteSpace(codepoint) {
248
- return codepoint == 0x9 || codepoint == 0x20 || isNewLine(codepoint);
251
+ return codepoint == 0x9 || codepoint == 0x20 ||
252
+ // isNewLine
253
+ codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
249
254
  }
250
255
 
251
256
  var properties = {
@@ -1450,7 +1455,6 @@ function hsl2rgb(h, s, l, a = null) {
1450
1455
  return values;
1451
1456
  }
1452
1457
 
1453
- const indents = [];
1454
1458
  function render(data, opt = {}) {
1455
1459
  const options = Object.assign(opt.compress ? {
1456
1460
  indent: '',
@@ -1468,24 +1472,12 @@ function render(data, opt = {}) {
1468
1472
  return acc;
1469
1473
  }
1470
1474
  }
1471
- if (options.compress && curr.typ == 'Whitespace') {
1472
- if (original[index + 1]?.typ == 'Start-parens' ||
1473
- (index > 0 && (original[index - 1].typ == 'Pseudo-class-func' ||
1474
- original[index - 1].typ == 'End-parens' ||
1475
- original[index - 1].typ == 'UrlFunc' ||
1476
- original[index - 1].typ == 'Func' ||
1477
- (original[index - 1].typ == 'Color' &&
1478
- original[index - 1].kin != 'hex' &&
1479
- original[index - 1].kin != 'lit')))) {
1480
- return acc;
1481
- }
1482
- }
1483
1475
  return acc + renderToken(curr, options);
1484
1476
  }
1485
- return { code: doRender(data, options, reducer) };
1477
+ return { code: doRender(data, options, reducer, 0) };
1486
1478
  }
1487
1479
  // @ts-ignore
1488
- function doRender(data, options, reducer, level = 0) {
1480
+ function doRender(data, options, reducer, level = 0, indents = []) {
1489
1481
  if (indents.length < level + 1) {
1490
1482
  indents.push(options.indent.repeat(level));
1491
1483
  }
@@ -1499,7 +1491,7 @@ function doRender(data, options, reducer, level = 0) {
1499
1491
  return options.removeComments ? '' : data.val;
1500
1492
  case 'StyleSheet':
1501
1493
  return data.chi.reduce((css, node) => {
1502
- const str = doRender(node, options, reducer, level);
1494
+ const str = doRender(node, options, reducer, level, indents);
1503
1495
  if (str === '') {
1504
1496
  return css;
1505
1497
  }
@@ -1526,7 +1518,7 @@ function doRender(data, options, reducer, level = 0) {
1526
1518
  str = `@${node.nam} ${node.val};`;
1527
1519
  }
1528
1520
  else {
1529
- str = doRender(node, options, reducer, level + 1);
1521
+ str = doRender(node, options, reducer, level + 1, indents);
1530
1522
  }
1531
1523
  if (css === '') {
1532
1524
  return str;
@@ -1534,8 +1526,7 @@ function doRender(data, options, reducer, level = 0) {
1534
1526
  if (str === '') {
1535
1527
  return css;
1536
1528
  }
1537
- if (str !== '')
1538
- return `${css}${options.newLine}${indentSub}${str}`;
1529
+ return `${css}${options.newLine}${indentSub}${str}`;
1539
1530
  }, '');
1540
1531
  if (children.endsWith(';')) {
1541
1532
  children = children.slice(0, -1);
@@ -1587,11 +1578,15 @@ function renderToken(token, options = {}) {
1587
1578
  if (token.kin == 'hex' || token.kin == 'lit') {
1588
1579
  return token.val;
1589
1580
  }
1581
+ case 'Start-parens':
1582
+ if (!('chi' in token)) {
1583
+ return '(';
1584
+ }
1590
1585
  case 'Func':
1591
1586
  case 'UrlFunc':
1592
1587
  case 'Pseudo-class-func':
1593
1588
  // @ts-ignore
1594
- return (options.compress && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) : token.val) + '(' + token.chi.reduce((acc, curr) => {
1589
+ return ( /* options.compress && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce((acc, curr) => {
1595
1590
  if (options.removeComments && curr.typ == 'Comment') {
1596
1591
  if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1597
1592
  return acc;
@@ -1607,8 +1602,6 @@ function renderToken(token, options = {}) {
1607
1602
  return '<';
1608
1603
  case 'Gt':
1609
1604
  return '>';
1610
- case 'Start-parens':
1611
- return '(';
1612
1605
  case 'End-parens':
1613
1606
  return ')';
1614
1607
  case 'Attr-start':
@@ -1684,7 +1677,7 @@ function renderToken(token, options = {}) {
1684
1677
  case 'String':
1685
1678
  case 'Iden':
1686
1679
  case 'Delim':
1687
- return options.compress && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : token.val;
1680
+ return /* options.compress && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
1688
1681
  }
1689
1682
  throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
1690
1683
  }
@@ -2245,6 +2238,54 @@ class PropertyList {
2245
2238
  }
2246
2239
 
2247
2240
  const configuration = getConfig();
2241
+ const combinators = ['+', '>', '~'];
2242
+ const notEndingWith = ['(', '['].concat(combinators);
2243
+ function wrapNodes(previous, node, match, ast, i, nodeIndex) {
2244
+ // @ts-ignore
2245
+ let pSel = match.selector1.reduce(reducer, []).join(',');
2246
+ // @ts-ignore
2247
+ let nSel = match.selector2.reduce(reducer, []).join(',');
2248
+ // @ts-ignore
2249
+ const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
2250
+ // @ts-ignore
2251
+ Object.defineProperty(wrapper, 'raw', {
2252
+ enumerable: false,
2253
+ writable: true,
2254
+ // @ts-ignore
2255
+ value: match.match.map(t => t.slice())
2256
+ });
2257
+ if (pSel == '&' || pSel === '') {
2258
+ // @ts-ignore
2259
+ wrapper.chi.push(...previous.chi);
2260
+ // @ts-ignore
2261
+ if ((nSel == '&' || nSel === '') && hasOnlyDeclarations(previous)) {
2262
+ // @ts-ignore
2263
+ wrapper.chi.push(...node.chi);
2264
+ }
2265
+ else {
2266
+ // @ts-ignore
2267
+ wrapper.chi.push(node);
2268
+ }
2269
+ }
2270
+ else {
2271
+ // @ts-ignore
2272
+ wrapper.chi.push(previous, node);
2273
+ }
2274
+ // @ts-ignore
2275
+ ast.chi.splice(i, 1, wrapper);
2276
+ // @ts-ignore
2277
+ ast.chi.splice(nodeIndex, 1);
2278
+ // @ts-ignore
2279
+ previous.sel = pSel;
2280
+ // @ts-ignore
2281
+ previous.raw = match.selector1;
2282
+ // @ts-ignore
2283
+ node.sel = nSel;
2284
+ // @ts-ignore
2285
+ node.raw = match.selector2;
2286
+ reduceRuleSelector(wrapper);
2287
+ return wrapper;
2288
+ }
2248
2289
  function deduplicate(ast, options = {}, recursive = false) {
2249
2290
  // @ts-ignore
2250
2291
  if (('chi' in ast) && ast.chi?.length > 0) {
@@ -2260,6 +2301,14 @@ function deduplicate(ast, options = {}, recursive = false) {
2260
2301
  }
2261
2302
  // @ts-ignore
2262
2303
  node = ast.chi[i];
2304
+ // @ts-ignore
2305
+ if (previous == node) {
2306
+ // console.error('idem!');
2307
+ // @ts-ignore
2308
+ ast.chi.splice(i, 1);
2309
+ i--;
2310
+ continue;
2311
+ }
2263
2312
  if (node.typ == 'AtRule' && node.nam == 'font-face') {
2264
2313
  continue;
2265
2314
  }
@@ -2270,6 +2319,111 @@ function deduplicate(ast, options = {}, recursive = false) {
2270
2319
  continue;
2271
2320
  }
2272
2321
  // @ts-ignore
2322
+ if (node.typ == 'Rule') {
2323
+ reduceRuleSelector(node);
2324
+ let wrapper;
2325
+ let match;
2326
+ // @ts-ignore
2327
+ if (options.nestingRules) {
2328
+ // @ts-ignore
2329
+ if (previous != null && previous.typ == 'Rule') {
2330
+ reduceRuleSelector(previous);
2331
+ // @ts-ignore
2332
+ match = matchSelectors(previous.raw, node.raw, ast.typ);
2333
+ // @ts-ignore
2334
+ if (match != null) {
2335
+ // @ts-ignore
2336
+ wrapper = wrapNodes(previous, node, match, ast, i, nodeIndex);
2337
+ nodeIndex = i - 1;
2338
+ // @ts-ignore
2339
+ previous = ast.chi[nodeIndex];
2340
+ }
2341
+ }
2342
+ // @ts-ignore
2343
+ if (wrapper != null) {
2344
+ // @ts-ignore
2345
+ while (i < ast.chi.length) {
2346
+ // @ts-ignore
2347
+ const nextNode = ast.chi[i];
2348
+ // @ts-ignore
2349
+ if (nextNode.typ != 'Rule') {
2350
+ // i--;
2351
+ // previous = wrapper;
2352
+ // nodeIndex = i;
2353
+ break;
2354
+ }
2355
+ reduceRuleSelector(nextNode);
2356
+ // @ts-ignore
2357
+ match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ);
2358
+ // @ts-ignore
2359
+ if (match == null) {
2360
+ break;
2361
+ }
2362
+ // @ts-ignore
2363
+ wrapper = wrapNodes(wrapper, nextNode, match, ast, i, nodeIndex);
2364
+ }
2365
+ nodeIndex = --i;
2366
+ // @ts-ignore
2367
+ previous = ast.chi[nodeIndex];
2368
+ deduplicate(wrapper, options, recursive);
2369
+ continue;
2370
+ }
2371
+ // @ts-ignore
2372
+ else if (node.optimized != null &&
2373
+ // @ts-ignore
2374
+ node.optimized.match &&
2375
+ // @ts-ignore
2376
+ node.optimized.selector.length > 1) {
2377
+ // @ts-ignore
2378
+ wrapper = { ...node, chi: [], sel: node.optimized.optimized[0] };
2379
+ // @ts-ignore
2380
+ Object.defineProperty(wrapper, 'raw', {
2381
+ enumerable: false,
2382
+ writable: true,
2383
+ // @ts-ignore
2384
+ value: [[node.optimized.optimized[0]]]
2385
+ });
2386
+ // @ts-ignore
2387
+ node.sel = node.optimized.selector.reduce(reducer, []).join(',');
2388
+ // @ts-ignore
2389
+ node.raw = node.optimized.selector.slice();
2390
+ // @ts-ignore
2391
+ wrapper.chi.push(node);
2392
+ // @ts-ignore
2393
+ ast.chi.splice(i, 1, wrapper);
2394
+ node = wrapper;
2395
+ }
2396
+ }
2397
+ // @ts-ignore
2398
+ else if (node.optimized?.match) {
2399
+ let wrap = true;
2400
+ // @ts-ignore
2401
+ const selector = node.optimized.selector.reduce((acc, curr) => {
2402
+ if (curr[0] == '&') {
2403
+ if (curr[1] == ' ') {
2404
+ curr.splice(0, 2);
2405
+ }
2406
+ else {
2407
+ if (ast.typ != 'Rule' && combinators.includes(curr[1])) {
2408
+ wrap = false;
2409
+ }
2410
+ else {
2411
+ curr.splice(0, 1);
2412
+ }
2413
+ }
2414
+ }
2415
+ else if (combinators.includes(curr[0])) {
2416
+ curr.unshift('&');
2417
+ }
2418
+ // @ts-ignore
2419
+ acc.push(curr.map(t => t.replaceAll('&', node.optimized.optimized[0])).join(''));
2420
+ return acc;
2421
+ }, []);
2422
+ // @ts-ignore
2423
+ node.sel = (wrap ? node.optimized.optimized[0] : '') + `:is(${selector.join(',')})`;
2424
+ }
2425
+ }
2426
+ // @ts-ignore
2273
2427
  if (previous != null && 'chi' in previous && ('chi' in node)) {
2274
2428
  // @ts-ignore
2275
2429
  if (previous.typ == node.typ) {
@@ -2289,13 +2443,14 @@ function deduplicate(ast, options = {}, recursive = false) {
2289
2443
  // @ts-ignore
2290
2444
  if ((node.typ == 'Rule' && node.sel == previous.sel) ||
2291
2445
  // @ts-ignore
2292
- (node.typ == 'AtRule') && node.val == previous.val) {
2446
+ (node.typ == 'AtRule') && node.val != 'font-face' && node.val == previous.val) {
2293
2447
  // @ts-ignore
2294
2448
  node.chi.unshift(...previous.chi);
2295
2449
  // @ts-ignore
2296
2450
  ast.chi.splice(nodeIndex, 1);
2297
2451
  // @ts-ignore
2298
2452
  if (hasDeclaration(node)) {
2453
+ // @ts-ignore
2299
2454
  deduplicateRule(node);
2300
2455
  }
2301
2456
  else {
@@ -2311,19 +2466,26 @@ function deduplicate(ast, options = {}, recursive = false) {
2311
2466
  if (intersect != null) {
2312
2467
  if (intersect.node1.chi.length == 0) {
2313
2468
  // @ts-ignore
2314
- ast.chi.splice(i, 1);
2469
+ ast.chi.splice(i--, 1);
2470
+ // @ts-ignore
2471
+ node = ast.chi[i];
2315
2472
  }
2316
2473
  else {
2317
2474
  // @ts-ignore
2318
2475
  ast.chi.splice(i, 1, intersect.node1);
2476
+ node = intersect.node1;
2319
2477
  }
2320
2478
  if (intersect.node2.chi.length == 0) {
2321
2479
  // @ts-ignore
2322
2480
  ast.chi.splice(nodeIndex, 1, intersect.result);
2481
+ previous = intersect.result;
2323
2482
  }
2324
2483
  else {
2325
2484
  // @ts-ignore
2326
2485
  ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
2486
+ previous = intersect.result;
2487
+ // @ts-ignore
2488
+ i = nodeIndex;
2327
2489
  }
2328
2490
  }
2329
2491
  }
@@ -2333,6 +2495,7 @@ function deduplicate(ast, options = {}, recursive = false) {
2333
2495
  if (recursive && previous != node) {
2334
2496
  // @ts-ignore
2335
2497
  if (hasDeclaration(previous)) {
2498
+ // @ts-ignore
2336
2499
  deduplicateRule(previous);
2337
2500
  }
2338
2501
  else {
@@ -2350,12 +2513,25 @@ function deduplicate(ast, options = {}, recursive = false) {
2350
2513
  deduplicateRule(node);
2351
2514
  }
2352
2515
  else {
2353
- deduplicate(node, options, recursive);
2516
+ // @ts-ignore
2517
+ if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
2518
+ deduplicate(node, options, recursive);
2519
+ }
2354
2520
  }
2355
2521
  }
2356
2522
  }
2357
2523
  return ast;
2358
2524
  }
2525
+ function hasOnlyDeclarations(node) {
2526
+ let k = node.chi.length;
2527
+ while (k--) {
2528
+ if (node.chi[k].typ == 'Comment') {
2529
+ continue;
2530
+ }
2531
+ return node.chi[k].typ == 'Declaration';
2532
+ }
2533
+ return true;
2534
+ }
2359
2535
  function hasDeclaration(node) {
2360
2536
  // @ts-ignore
2361
2537
  for (let i = 0; i < node.chi?.length; i++) {
@@ -2368,7 +2544,7 @@ function hasDeclaration(node) {
2368
2544
  }
2369
2545
  return true;
2370
2546
  }
2371
- function deduplicateRule(ast, options = {}) {
2547
+ function deduplicateRule(ast) {
2372
2548
  // @ts-ignore
2373
2549
  if (!('chi' in ast) || ast.chi?.length <= 1) {
2374
2550
  return ast;
@@ -2415,42 +2591,42 @@ function deduplicateRule(ast, options = {}) {
2415
2591
  }
2416
2592
  // @ts-ignore
2417
2593
  ast.chi = children.concat(ast.chi?.slice(k));
2418
- /*
2419
- // @ts-ignore
2420
-
2421
- const properties: PropertyList = new PropertyList();
2422
-
2423
- for (; k < j; k++) {
2424
-
2425
- // @ts-ignore
2426
- if ('Comment' == ast.chi[k].typ || 'Declaration' == ast.chi[k].typ) {
2427
-
2428
- // @ts-ignore
2429
- properties.add(ast.chi[k]);
2430
- continue;
2431
- }
2432
-
2433
- break;
2434
- }
2435
-
2436
- // @ts-ignore
2437
- ast.chi = [...properties].concat(ast.chi.slice(k));
2438
- */
2439
- //
2440
- // @ts-ignore
2441
- // ast.chi.splice(0, k - 1, ...properties);
2442
2594
  return ast;
2443
2595
  }
2444
2596
  function splitRule(buffer) {
2445
- const result = [];
2597
+ const result = [[]];
2446
2598
  let str = '';
2447
2599
  for (let i = 0; i < buffer.length; i++) {
2448
2600
  let chr = buffer.charAt(i);
2601
+ if (isWhiteSpace(chr.charCodeAt(0))) {
2602
+ let k = i;
2603
+ while (k + 1 < buffer.length) {
2604
+ if (isWhiteSpace(buffer[k + 1].charCodeAt(0))) {
2605
+ k++;
2606
+ continue;
2607
+ }
2608
+ break;
2609
+ }
2610
+ if (str !== '') {
2611
+ // @ts-ignore
2612
+ result.at(-1).push(str);
2613
+ str = '';
2614
+ }
2615
+ // @ts-ignore
2616
+ if (result.at(-1).length > 0) {
2617
+ // @ts-ignore
2618
+ result.at(-1).push(' ');
2619
+ }
2620
+ i = k;
2621
+ continue;
2622
+ }
2449
2623
  if (chr == ',') {
2450
2624
  if (str !== '') {
2451
- result.push(str);
2625
+ // @ts-ignore
2626
+ result.at(-1).push(str);
2452
2627
  str = '';
2453
2628
  }
2629
+ result.push([]);
2454
2630
  continue;
2455
2631
  }
2456
2632
  str += chr;
@@ -2497,14 +2673,49 @@ function splitRule(buffer) {
2497
2673
  }
2498
2674
  }
2499
2675
  i = k;
2500
- continue;
2501
2676
  }
2502
2677
  }
2503
2678
  if (str !== '') {
2504
- result.push(str);
2679
+ // @ts-ignore
2680
+ result.at(-1).push(str);
2505
2681
  }
2506
2682
  return result;
2507
2683
  }
2684
+ function reduceRuleSelector(node) {
2685
+ if (node.raw == null) {
2686
+ Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: splitRule(node.sel) });
2687
+ }
2688
+ // @ts-ignore
2689
+ // if (node.raw != null) {
2690
+ // @ts-ignore
2691
+ let optimized = reduceSelector(node.raw.reduce((acc, curr) => {
2692
+ acc.push(curr.slice());
2693
+ return acc;
2694
+ }, []));
2695
+ if (optimized != null) {
2696
+ Object.defineProperty(node, 'optimized', { enumerable: false, writable: true, value: optimized });
2697
+ }
2698
+ if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
2699
+ const raw = [
2700
+ [
2701
+ optimized.optimized[0], ':is('
2702
+ ].concat(optimized.selector.reduce((acc, curr) => {
2703
+ if (acc.length > 0) {
2704
+ acc.push(',');
2705
+ }
2706
+ acc.push(...curr);
2707
+ return acc;
2708
+ }, [])).concat(')')
2709
+ ];
2710
+ const sel = raw[0].join('');
2711
+ if (sel.length < node.sel.length) {
2712
+ node.sel = sel;
2713
+ // node.raw = raw;
2714
+ Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
2715
+ }
2716
+ }
2717
+ // }
2718
+ }
2508
2719
  function diff(n1, n2, options = {}) {
2509
2720
  let node1 = n1;
2510
2721
  let node2 = n2;
@@ -2521,8 +2732,28 @@ function diff(n1, n2, options = {}) {
2521
2732
  // @ts-ignore
2522
2733
  return null;
2523
2734
  }
2735
+ // @ts-ignore
2736
+ const raw1 = node1.raw;
2737
+ // @ts-ignore
2738
+ // const optimized1 = node1.optimized;
2739
+ // @ts-ignore
2740
+ const raw2 = node2.raw;
2741
+ // @ts-ignore
2742
+ // const optimized2 = node2.optimized;
2524
2743
  node1 = { ...node1, chi: node1.chi.slice() };
2525
2744
  node2 = { ...node2, chi: node2.chi.slice() };
2745
+ if (raw1 != null) {
2746
+ Object.defineProperty(node1, 'raw', { enumerable: false, writable: true, value: raw1 });
2747
+ }
2748
+ // if (optimized1 != null) {
2749
+ // Object.defineProperty(node1, 'optimized', {enumerable: false, writable: true, value: optimized1});
2750
+ // }
2751
+ if (raw2 != null) {
2752
+ Object.defineProperty(node2, 'raw', { enumerable: false, writable: true, value: raw2 });
2753
+ }
2754
+ // if (optimized2 != null) {
2755
+ // Object.defineProperty(node2, 'optimized', {enumerable: false, writable: true, value: optimized2});
2756
+ // }
2526
2757
  const intersect = [];
2527
2758
  while (i--) {
2528
2759
  if (node1.chi[i].typ == 'Comment') {
@@ -2550,7 +2781,7 @@ function diff(n1, n2, options = {}) {
2550
2781
  const result = (intersect.length == 0 ? null : {
2551
2782
  ...node1,
2552
2783
  // @ts-ignore
2553
- sel: [...new Set([...(n1.raw || splitRule(n1.sel)).concat(n2.raw || splitRule(n2.sel))])].join(),
2784
+ sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(','),
2554
2785
  chi: intersect.reverse()
2555
2786
  });
2556
2787
  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)) {
@@ -2559,6 +2790,262 @@ function diff(n1, n2, options = {}) {
2559
2790
  }
2560
2791
  return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node2 : node2 };
2561
2792
  }
2793
+ function matchSelectors(selector1, selector2, parentType) {
2794
+ let match = [[]];
2795
+ 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));
2796
+ let i = 0;
2797
+ let k;
2798
+ let l;
2799
+ let token;
2800
+ let matching = true;
2801
+ let matchFunction = 0;
2802
+ let inAttr = 0;
2803
+ for (; i < j; i++) {
2804
+ k = 0;
2805
+ token = selector1[0][i];
2806
+ for (; k < selector1.length; k++) {
2807
+ if (selector1[k][i] != token) {
2808
+ matching = false;
2809
+ break;
2810
+ }
2811
+ }
2812
+ if (matching) {
2813
+ l = 0;
2814
+ for (; l < selector2.length; l++) {
2815
+ if (selector2[l][i] != token) {
2816
+ matching = false;
2817
+ break;
2818
+ }
2819
+ }
2820
+ }
2821
+ if (!matching) {
2822
+ break;
2823
+ }
2824
+ if (token == ',') {
2825
+ match.push([]);
2826
+ }
2827
+ else {
2828
+ if (token.endsWith('(')) {
2829
+ matchFunction++;
2830
+ }
2831
+ if (token.endsWith('[')) {
2832
+ inAttr++;
2833
+ }
2834
+ else if (token == ')') {
2835
+ matchFunction--;
2836
+ }
2837
+ else if (token == ']') {
2838
+ inAttr--;
2839
+ }
2840
+ match.at(-1).push(token);
2841
+ }
2842
+ }
2843
+ // invalid function
2844
+ if (matchFunction != 0 || inAttr != 0) {
2845
+ return null;
2846
+ }
2847
+ if (parentType != 'Rule') {
2848
+ for (const part of match) {
2849
+ if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
2850
+ return null;
2851
+ }
2852
+ }
2853
+ }
2854
+ if (match.length > 1) {
2855
+ console.error(`unsupported multilevel matching`);
2856
+ console.error({ match, selector1, selector2 });
2857
+ return null;
2858
+ }
2859
+ for (const part of match) {
2860
+ while (part.length > 0) {
2861
+ const token = part.at(-1);
2862
+ if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
2863
+ part.pop();
2864
+ continue;
2865
+ }
2866
+ break;
2867
+ }
2868
+ }
2869
+ if (match.every(t => t.length == 0)) {
2870
+ return null;
2871
+ }
2872
+ if (eq([['&']], match)) {
2873
+ return null;
2874
+ }
2875
+ function reduce(acc, curr) {
2876
+ if (acc === null) {
2877
+ return null;
2878
+ }
2879
+ let hasCompoundSelector = true;
2880
+ curr = curr.slice(match[0].length);
2881
+ while (curr.length > 0) {
2882
+ if (curr[0] == ' ') {
2883
+ hasCompoundSelector = false;
2884
+ curr.unshift('&');
2885
+ continue;
2886
+ }
2887
+ break;
2888
+ }
2889
+ // invalid function match
2890
+ if (curr.length > 0 && curr[0].endsWith('(') && curr.at(-1) != ')') {
2891
+ return null;
2892
+ }
2893
+ if (curr.length == 1 && combinators.includes(curr[0].charAt(0))) {
2894
+ return null;
2895
+ }
2896
+ if (hasCompoundSelector && curr.length > 0) {
2897
+ hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
2898
+ }
2899
+ if (curr[0] == ':is(') {
2900
+ let inFunction = 0;
2901
+ let canReduce = true;
2902
+ const isCompound = curr.reduce((acc, token, index) => {
2903
+ if (index == 0) {
2904
+ inFunction++;
2905
+ canReduce = curr[1] == '&';
2906
+ }
2907
+ else if (token.endsWith('(')) {
2908
+ if (inFunction == 0) {
2909
+ canReduce = false;
2910
+ }
2911
+ inFunction++;
2912
+ }
2913
+ else if (token == ')') {
2914
+ inFunction--;
2915
+ }
2916
+ else if (token == ',') {
2917
+ if (!canReduce) {
2918
+ canReduce = curr[index + 1] == '&';
2919
+ }
2920
+ acc.push([]);
2921
+ }
2922
+ else
2923
+ acc.at(-1)?.push(token);
2924
+ return acc;
2925
+ }, [[]]);
2926
+ if (inFunction > 0) {
2927
+ canReduce = false;
2928
+ }
2929
+ if (canReduce) {
2930
+ curr = isCompound.reduce((acc, curr) => {
2931
+ if (acc.length > 0) {
2932
+ acc.push(',');
2933
+ }
2934
+ acc.push(...curr);
2935
+ return acc;
2936
+ }, []);
2937
+ }
2938
+ }
2939
+ // @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
2940
+ acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
2941
+ return acc;
2942
+ }
2943
+ // @ts-ignore
2944
+ selector1 = selector1.reduce(reduce, []);
2945
+ // @ts-ignore
2946
+ selector2 = selector2.reduce(reduce, []);
2947
+ return selector1 == null || selector2 == null ? null : {
2948
+ eq: eq(selector1, selector2),
2949
+ match,
2950
+ selector1,
2951
+ selector2
2952
+ };
2953
+ }
2954
+ function reduceSelector(selector) {
2955
+ if (selector.length == 0) {
2956
+ return null;
2957
+ }
2958
+ const optimized = [];
2959
+ const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
2960
+ let i = 0;
2961
+ let j;
2962
+ let match;
2963
+ for (; i < k; i++) {
2964
+ const item = selector[0][i];
2965
+ match = true;
2966
+ for (j = 1; j < selector.length; j++) {
2967
+ if (item != selector[j][i]) {
2968
+ match = false;
2969
+ break;
2970
+ }
2971
+ }
2972
+ if (!match) {
2973
+ break;
2974
+ }
2975
+ optimized.push(item);
2976
+ }
2977
+ while (optimized.length > 0) {
2978
+ const last = optimized.at(-1);
2979
+ if ((last == ' ' || combinators.includes(last))) {
2980
+ optimized.pop();
2981
+ continue;
2982
+ }
2983
+ break;
2984
+ }
2985
+ selector.forEach((selector) => selector.splice(0, optimized.length));
2986
+ // combinator
2987
+ if (combinators.includes(optimized.at(-1))) {
2988
+ const combinator = optimized.pop();
2989
+ selector.forEach(selector => selector.unshift(combinator));
2990
+ }
2991
+ let reducible = optimized.length == 1;
2992
+ if (optimized[0] == '&' && optimized[1] == ' ') {
2993
+ optimized.splice(0, 2);
2994
+ }
2995
+ if (optimized.length == 0 ||
2996
+ (optimized[0].charAt(0) == '&' ||
2997
+ selector.length == 1)) {
2998
+ return {
2999
+ match: false,
3000
+ optimized,
3001
+ selector: selector.map(selector => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : selector),
3002
+ reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0]))
3003
+ };
3004
+ }
3005
+ return {
3006
+ match: true,
3007
+ optimized,
3008
+ selector: selector.reduce((acc, curr) => {
3009
+ let hasCompound = true;
3010
+ if (hasCompound && curr.length > 0) {
3011
+ hasCompound = !['&'].concat(combinators).includes(curr[0].charAt(0));
3012
+ }
3013
+ // @ts-ignore
3014
+ if (hasCompound && curr[0] == ' ') {
3015
+ hasCompound = false;
3016
+ curr.unshift('&');
3017
+ }
3018
+ if (curr.length == 0) {
3019
+ curr.push('&');
3020
+ hasCompound = false;
3021
+ }
3022
+ if (reducible) {
3023
+ const chr = curr[0].charAt(0);
3024
+ // @ts-ignore
3025
+ reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
3026
+ }
3027
+ acc.push(hasCompound ? ['&'].concat(curr) : curr);
3028
+ return acc;
3029
+ }, []),
3030
+ reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
3031
+ };
3032
+ }
3033
+ function reducer(acc, curr, index, array) {
3034
+ // trim :is()
3035
+ if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
3036
+ curr = curr.slice(1, -1);
3037
+ }
3038
+ if (curr[0] == '&') {
3039
+ if (curr[1] == ' ') {
3040
+ curr.splice(0, 2);
3041
+ }
3042
+ else if (combinators.includes(curr[1])) {
3043
+ curr.splice(0, 1);
3044
+ }
3045
+ }
3046
+ acc.push(curr.join(''));
3047
+ return acc;
3048
+ }
2562
3049
 
2563
3050
  const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
2564
3051
  const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
@@ -2568,6 +3055,7 @@ async function parse$1(iterator, opt = {}) {
2568
3055
  src: '',
2569
3056
  sourcemap: false,
2570
3057
  compress: false,
3058
+ nestingRules: false,
2571
3059
  resolveImport: false,
2572
3060
  resolveUrls: false,
2573
3061
  removeEmpty: true,
@@ -2838,11 +3326,16 @@ async function parse$1(iterator, opt = {}) {
2838
3326
  try {
2839
3327
  // @ts-ignore
2840
3328
  const root = await options.load(url, options.src).then((src) => {
2841
- bytesIn += src.length;
2842
- // @ts-ignore
2843
- return parse$1(src, Object.assign({}, options, { src: options.resolve(url, options.src).absolute }));
3329
+ return parse$1(src, Object.assign({}, options, {
3330
+ compress: false,
3331
+ // @ts-ignore
3332
+ src: options.resolve(url, options.src).absolute
3333
+ }));
2844
3334
  });
2845
- context.chi.push(...root.ast.chi);
3335
+ bytesIn += root.bytesIn;
3336
+ if (root.ast.chi.length > 0) {
3337
+ context.chi.push(...root.ast.chi);
3338
+ }
2846
3339
  if (root.errors.length > 0) {
2847
3340
  errors.push(...root.errors);
2848
3341
  }
@@ -2857,20 +3350,16 @@ async function parse$1(iterator, opt = {}) {
2857
3350
  // https://www.w3.org/TR/css-nesting-1/#conditionals
2858
3351
  // allowed nesting at-rules
2859
3352
  // there must be a top level rule in the stack
3353
+ const raw = tokens.reduce((acc, curr) => {
3354
+ acc.push(renderToken(curr, { removeComments: true }));
3355
+ return acc;
3356
+ }, []);
2860
3357
  const node = {
2861
3358
  typ: 'AtRule',
2862
3359
  nam: renderToken(atRule, { removeComments: true }),
2863
- val: tokens.reduce((acc, curr, index, array) => {
2864
- if (curr.typ == 'Whitespace') {
2865
- if (array[index + 1]?.typ == 'Start-parens' ||
2866
- array[index - 1]?.typ == 'End-parens' ||
2867
- array[index - 1]?.typ == 'Func') {
2868
- return acc;
2869
- }
2870
- }
2871
- return acc + renderToken(curr, { removeComments: true });
2872
- }, '')
3360
+ val: raw.join('')
2873
3361
  };
3362
+ Object.defineProperty(node, 'raw', { enumerable: false, writable: false, value: raw });
2874
3363
  if (delim.typ == 'Block-start') {
2875
3364
  node.chi = [];
2876
3365
  }
@@ -2895,23 +3384,33 @@ async function parse$1(iterator, opt = {}) {
2895
3384
  return null;
2896
3385
  }
2897
3386
  }
2898
- const sel = parseTokens(tokens, { compress: options.compress }).map(curr => renderToken(curr, { compress: true }));
2899
- const raw = [...new Set(sel.reduce((acc, curr) => {
2900
- if (curr == ',') {
2901
- acc.push('');
2902
- }
2903
- else {
2904
- acc[acc.length - 1] += curr;
3387
+ const uniq = new Map;
3388
+ parseTokens(tokens, 'Rule', { compress: options.compress }).reduce((acc, curr, index, array) => {
3389
+ if (curr.typ == 'Whitespace') {
3390
+ if (array[index - 1]?.val == '+' || array[index + 1]?.val == '+') {
3391
+ return acc;
2905
3392
  }
2906
- return acc;
2907
- }, ['']))];
3393
+ }
3394
+ let t = renderToken(curr, { compress: true });
3395
+ if (t == ',') {
3396
+ acc.push([]);
3397
+ }
3398
+ else {
3399
+ acc[acc.length - 1].push(t);
3400
+ }
3401
+ return acc;
3402
+ }, [[]]).reduce((acc, curr) => {
3403
+ acc.set(curr.join(''), curr);
3404
+ return acc;
3405
+ }, uniq);
2908
3406
  const node = {
2909
3407
  typ: 'Rule',
2910
3408
  // @ts-ignore
2911
- sel: raw.join(','),
3409
+ sel: [...uniq.keys()].join(','),
2912
3410
  chi: []
2913
3411
  };
2914
- Object.defineProperty(node, 'raw', { enumerable: false, get: () => raw });
3412
+ let raw = [...uniq.values()];
3413
+ Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
2915
3414
  loc = {
2916
3415
  sta: position,
2917
3416
  src
@@ -2935,7 +3434,13 @@ async function parse$1(iterator, opt = {}) {
2935
3434
  }
2936
3435
  if (tokens[i].typ == 'Colon') {
2937
3436
  name = tokens.slice(0, i);
2938
- value = parseTokens(tokens.slice(i + 1), { parseColor: true, src: options.src, resolveUrls: options.resolveUrls, resolve: options.resolve, cwd: options.cwd });
3437
+ value = parseTokens(tokens.slice(i + 1), 'Declaration', {
3438
+ parseColor: true,
3439
+ src: options.src,
3440
+ resolveUrls: options.resolveUrls,
3441
+ resolve: options.resolve,
3442
+ cwd: options.cwd
3443
+ });
2939
3444
  }
2940
3445
  }
2941
3446
  if (name == null) {
@@ -2954,11 +3459,6 @@ async function parse$1(iterator, opt = {}) {
2954
3459
  }
2955
3460
  }
2956
3461
  }
2957
- // if (name.length == 0) {
2958
- //
2959
- // errors.push({action: 'drop', message: 'invalid declaration', location: {src, ...position}});
2960
- // return null;
2961
- // }
2962
3462
  if (value == null) {
2963
3463
  errors.push({ action: 'drop', message: 'invalid declaration', location: { src, ...position } });
2964
3464
  return null;
@@ -2981,16 +3481,6 @@ async function parse$1(iterator, opt = {}) {
2981
3481
  errors.push({ action: 'drop', message: 'invalid declaration', location: { src, ...position } });
2982
3482
  return null;
2983
3483
  }
2984
- // // location not needed for declaration
2985
- // loc = <Location>{
2986
- // sta: position,
2987
- // src
2988
- // };
2989
- //
2990
- // if (options.sourcemap) {
2991
- //
2992
- // node.loc = loc
2993
- // }
2994
3484
  // @ts-ignore
2995
3485
  context.chi.push(node);
2996
3486
  return null;
@@ -3033,7 +3523,6 @@ async function parse$1(iterator, opt = {}) {
3033
3523
  position.ind = ind;
3034
3524
  position.lin = lin;
3035
3525
  position.col = col == 0 ? 1 : col;
3036
- // }
3037
3526
  }
3038
3527
  function consumeWhiteSpace() {
3039
3528
  let count = 0;
@@ -3215,11 +3704,6 @@ async function parse$1(iterator, opt = {}) {
3215
3704
  }
3216
3705
  }
3217
3706
  }
3218
- // else {
3219
- //
3220
- // pushToken(getType(buffer));
3221
- // buffer = '';
3222
- // }
3223
3707
  break;
3224
3708
  case '<':
3225
3709
  if (buffer.length > 0) {
@@ -3270,6 +3754,9 @@ async function parse$1(iterator, opt = {}) {
3270
3754
  break;
3271
3755
  case '~':
3272
3756
  case '|':
3757
+ if (tokens.at(-1)?.typ == 'Whitespace') {
3758
+ tokens.pop();
3759
+ }
3273
3760
  if (buffer.length > 0) {
3274
3761
  pushToken(getType(buffer));
3275
3762
  buffer = '';
@@ -3291,15 +3778,32 @@ async function parse$1(iterator, opt = {}) {
3291
3778
  break;
3292
3779
  }
3293
3780
  pushToken(getType(buffer));
3781
+ while (isWhiteSpace(value.charCodeAt(0))) {
3782
+ value = next();
3783
+ }
3294
3784
  buffer = value;
3295
3785
  break;
3296
3786
  case '>':
3787
+ if (buffer !== '') {
3788
+ pushToken(getType(buffer));
3789
+ buffer = '';
3790
+ }
3297
3791
  if (tokens[tokens.length - 1]?.typ == 'Whitespace') {
3298
3792
  tokens.pop();
3299
3793
  }
3300
3794
  pushToken({ typ: 'Gt' });
3301
3795
  consumeWhiteSpace();
3302
3796
  break;
3797
+ case '.':
3798
+ const codepoint = peek().charCodeAt(0);
3799
+ if (!isDigit(codepoint) && buffer !== '') {
3800
+ pushToken(getType(buffer));
3801
+ buffer = value;
3802
+ break;
3803
+ }
3804
+ buffer += value;
3805
+ break;
3806
+ case '+':
3303
3807
  case ':':
3304
3808
  case ',':
3305
3809
  case '=':
@@ -3311,12 +3815,11 @@ async function parse$1(iterator, opt = {}) {
3311
3815
  buffer += value + next();
3312
3816
  break;
3313
3817
  }
3314
- // if (value == ',' && tokens[tokens.length - 1]?.typ == 'Whitespace') {
3315
- //
3316
- // tokens.pop();
3317
- // }
3318
3818
  pushToken(getType(value));
3319
3819
  buffer = '';
3820
+ if (value == '+' && isWhiteSpace(peek().charCodeAt(0))) {
3821
+ pushToken(getType(next()));
3822
+ }
3320
3823
  while (isWhiteSpace(peek().charCodeAt(0))) {
3321
3824
  next();
3322
3825
  }
@@ -3337,7 +3840,7 @@ async function parse$1(iterator, opt = {}) {
3337
3840
  pushToken(getType(buffer));
3338
3841
  buffer = '';
3339
3842
  const token = tokens[tokens.length - 1];
3340
- if (token.typ == 'UrlFunc' /* && token.chi == 'url' */) {
3843
+ if (token.typ == 'UrlFunc') {
3341
3844
  // consume either string or url token
3342
3845
  let whitespace = '';
3343
3846
  value = peek();
@@ -3454,15 +3957,6 @@ async function parse$1(iterator, opt = {}) {
3454
3957
  if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
3455
3958
  context.chi.pop();
3456
3959
  }
3457
- else if (previousNode != null && previousNode != ast && options.compress) {
3458
- // @ts-ignore
3459
- if (hasDeclaration(previousNode)) {
3460
- deduplicateRule(previousNode);
3461
- }
3462
- else {
3463
- deduplicate(previousNode, options);
3464
- }
3465
- }
3466
3960
  tokens.length = 0;
3467
3961
  map.clear();
3468
3962
  buffer = '';
@@ -3497,28 +3991,22 @@ async function parse$1(iterator, opt = {}) {
3497
3991
  await parseNode(tokens);
3498
3992
  }
3499
3993
  if (options.compress) {
3500
- while (stack.length > 0) {
3501
- const node = stack.pop();
3502
- if (hasDeclaration(node)) {
3503
- deduplicateRule(node, options);
3504
- }
3505
- else {
3506
- deduplicate(node, options);
3507
- }
3508
- }
3509
3994
  if (ast.chi.length > 0) {
3510
- deduplicate(ast, options);
3995
+ deduplicate(ast, options, true);
3511
3996
  }
3512
3997
  }
3513
3998
  return { ast, errors, bytesIn };
3514
3999
  }
3515
- function parseTokens(tokens, options = {}) {
4000
+ function parseTokens(tokens, nodeType, options = {}) {
3516
4001
  for (let i = 0; i < tokens.length; i++) {
3517
4002
  const t = tokens[i];
3518
4003
  if (t.typ == 'Whitespace' && ((i == 0 ||
3519
4004
  i + 1 == tokens.length ||
3520
- ['Comma', 'Start-parens'].includes(tokens[i + 1].typ) ||
3521
- (i > 0 && funcLike.includes(tokens[i - 1].typ))))) {
4005
+ ['Comma'].includes(tokens[i + 1].typ) ||
4006
+ (i > 0 &&
4007
+ tokens[i + 1]?.typ != 'Literal' &&
4008
+ funcLike.includes(tokens[i - 1].typ) &&
4009
+ !['var', 'calc'].includes(tokens[i - 1].val))))) {
3522
4010
  tokens.splice(i--, 1);
3523
4011
  continue;
3524
4012
  }
@@ -3563,7 +4051,7 @@ function parseTokens(tokens, options = {}) {
3563
4051
  if (t.chi.length > 1) {
3564
4052
  /*(<AttrToken>t).chi =*/
3565
4053
  // @ts-ignore
3566
- parseTokens(t.chi, options);
4054
+ parseTokens(t.chi, t.typ, options);
3567
4055
  }
3568
4056
  // @ts-ignore
3569
4057
  t.chi.forEach(val => {
@@ -3616,9 +4104,9 @@ function parseTokens(tokens, options = {}) {
3616
4104
  // @ts-ignore
3617
4105
  t.chi.pop();
3618
4106
  }
4107
+ let isColor = true;
3619
4108
  // @ts-ignore
3620
4109
  if (options.parseColor && ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk'].includes(t.val)) {
3621
- let isColor = true;
3622
4110
  // @ts-ignore
3623
4111
  for (const v of t.chi) {
3624
4112
  if (v.typ == 'Func' && v.val == 'var') {
@@ -3626,37 +4114,38 @@ function parseTokens(tokens, options = {}) {
3626
4114
  break;
3627
4115
  }
3628
4116
  }
3629
- if (!isColor) {
3630
- continue;
3631
- }
3632
- // @ts-ignore
3633
- t.typ = 'Color';
3634
- // @ts-ignore
3635
- t.kin = t.val;
3636
- // @ts-ignore
3637
- let m = t.chi.length;
3638
- while (m-- > 0) {
4117
+ if (isColor) {
4118
+ // @ts-ignore
4119
+ t.typ = 'Color';
3639
4120
  // @ts-ignore
3640
- if (t.chi[m].typ == 'Literal') {
4121
+ t.kin = t.val;
4122
+ // @ts-ignore
4123
+ let m = t.chi.length;
4124
+ while (m-- > 0) {
3641
4125
  // @ts-ignore
3642
- if (t.chi[m + 1]?.typ == 'Whitespace') {
4126
+ if (t.chi[m].typ == 'Literal') {
3643
4127
  // @ts-ignore
3644
- t.chi.splice(m + 1, 1);
3645
- }
3646
- // @ts-ignore
3647
- if (t.chi[m - 1]?.typ == 'Whitespace') {
4128
+ if (t.chi[m + 1]?.typ == 'Whitespace') {
4129
+ // @ts-ignore
4130
+ t.chi.splice(m + 1, 1);
4131
+ }
3648
4132
  // @ts-ignore
3649
- t.chi.splice(m - 1, 1);
3650
- m--;
4133
+ if (t.chi[m - 1]?.typ == 'Whitespace') {
4134
+ // @ts-ignore
4135
+ t.chi.splice(m - 1, 1);
4136
+ m--;
4137
+ }
3651
4138
  }
3652
4139
  }
4140
+ continue;
3653
4141
  }
3654
4142
  }
3655
- else if (t.typ == 'UrlFunc') {
4143
+ if (t.typ == 'UrlFunc') {
3656
4144
  // @ts-ignore
3657
4145
  if (t.chi[0]?.typ == 'String') {
3658
4146
  // @ts-ignore
3659
4147
  const value = t.chi[0].val.slice(1, -1);
4148
+ // @ts-ignore
3660
4149
  if (t.chi[0].val.slice(1, 5) != 'data:' && urlTokenMatcher.test(value)) {
3661
4150
  // @ts-ignore
3662
4151
  t.chi[0].typ = 'Url-token';
@@ -3674,7 +4163,7 @@ function parseTokens(tokens, options = {}) {
3674
4163
  // @ts-ignore
3675
4164
  if (t.chi.length > 0) {
3676
4165
  // @ts-ignore
3677
- parseTokens(t.chi, options);
4166
+ parseTokens(t.chi, t.typ, options);
3678
4167
  if (t.typ == 'Pseudo-class-func' && t.val == ':is' && options.compress) {
3679
4168
  //
3680
4169
  const count = t.chi.filter(t => t.typ != 'Comment').length;
@@ -3740,7 +4229,7 @@ function* doWalk(node, parent, root) {
3740
4229
  yield { node, parent, root };
3741
4230
  if ('chi' in node) {
3742
4231
  for (const child of node.chi) {
3743
- yield* doWalk(child, node, (root == null ? node : root));
4232
+ yield* doWalk(child, node, (root ?? node));
3744
4233
  }
3745
4234
  }
3746
4235
  }
@@ -3874,12 +4363,10 @@ async function load(url, currentFile) {
3874
4363
  }
3875
4364
 
3876
4365
  function parse(iterator, opt = {}) {
3877
- Object.assign(opt, { load, resolve, cwd: opt.cwd ?? process.cwd() });
3878
- return parse$1(iterator, opt);
4366
+ return parse$1(iterator, Object.assign(opt, { load, resolve, cwd: opt.cwd ?? process.cwd() }));
3879
4367
  }
3880
4368
  function transform(css, options = {}) {
3881
- Object.assign(options, { load, resolve, cwd: options.cwd ?? process.cwd() });
3882
- return transform$1(css, options);
4369
+ return transform$1(css, Object.assign(options, { load, resolve, cwd: options.cwd ?? process.cwd() }));
3883
4370
  }
3884
4371
 
3885
4372
  exports.deduplicate = deduplicate;
@@ -3889,6 +4376,7 @@ exports.hasDeclaration = hasDeclaration;
3889
4376
  exports.load = load;
3890
4377
  exports.matchUrl = matchUrl;
3891
4378
  exports.parse = parse;
4379
+ exports.reduceSelector = reduceSelector;
3892
4380
  exports.render = render;
3893
4381
  exports.renderToken = renderToken;
3894
4382
  exports.resolve = resolve;