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

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 = {
@@ -1468,18 +1473,21 @@ function render(data, opt = {}) {
1468
1473
  return acc;
1469
1474
  }
1470
1475
  }
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
- }
1476
+ // if (options.compress && curr.typ == 'Whitespace') {
1477
+ //
1478
+ // if (original[index + 1]?.typ == 'Start-parens' ||
1479
+ // (index > 0 && (original[index - 1].typ == 'Pseudo-class-func' ||
1480
+ // original[index - 1].typ == 'End-parens' ||
1481
+ // original[index - 1].typ == 'UrlFunc' ||
1482
+ // original[index - 1].typ == 'Func' ||
1483
+ // (
1484
+ // original[index - 1].typ == 'Color' &&
1485
+ // (<ColorToken>original[index - 1]).kin != 'hex' &&
1486
+ // (<ColorToken>original[index - 1]).kin != 'lit')))) {
1487
+ //
1488
+ // return acc;
1489
+ // }
1490
+ // }
1483
1491
  return acc + renderToken(curr, options);
1484
1492
  }
1485
1493
  return { code: doRender(data, options, reducer) };
@@ -1587,11 +1595,15 @@ function renderToken(token, options = {}) {
1587
1595
  if (token.kin == 'hex' || token.kin == 'lit') {
1588
1596
  return token.val;
1589
1597
  }
1598
+ case 'Start-parens':
1599
+ if (!('chi' in token)) {
1600
+ return '(';
1601
+ }
1590
1602
  case 'Func':
1591
1603
  case 'UrlFunc':
1592
1604
  case 'Pseudo-class-func':
1593
1605
  // @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) => {
1606
+ 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
1607
  if (options.removeComments && curr.typ == 'Comment') {
1596
1608
  if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
1597
1609
  return acc;
@@ -1607,8 +1619,6 @@ function renderToken(token, options = {}) {
1607
1619
  return '<';
1608
1620
  case 'Gt':
1609
1621
  return '>';
1610
- case 'Start-parens':
1611
- return '(';
1612
1622
  case 'End-parens':
1613
1623
  return ')';
1614
1624
  case 'Attr-start':
@@ -1684,7 +1694,7 @@ function renderToken(token, options = {}) {
1684
1694
  case 'String':
1685
1695
  case 'Iden':
1686
1696
  case 'Delim':
1687
- return options.compress && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : token.val;
1697
+ return /* options.compress && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
1688
1698
  }
1689
1699
  throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
1690
1700
  }
@@ -2270,6 +2280,125 @@ function deduplicate(ast, options = {}, recursive = false) {
2270
2280
  continue;
2271
2281
  }
2272
2282
  // @ts-ignore
2283
+ if (node.typ == 'Rule') {
2284
+ reduceRuleSelector(node);
2285
+ // @ts-ignore
2286
+ if (options.nestingRules && node.raw != null && previous?.raw != null && node.raw.length == 1 && previous.raw.length == 1) {
2287
+ const match = [];
2288
+ // @ts-ignore
2289
+ while (node.raw[0].length > 0 && previous.raw[0].length > 0) {
2290
+ // @ts-ignore
2291
+ if (node.raw[0][0] != previous.raw[0][0]) {
2292
+ break;
2293
+ }
2294
+ // @ts-ignore
2295
+ match.push(node.raw[0].shift());
2296
+ // @ts-ignore
2297
+ previous.raw[0].shift();
2298
+ }
2299
+ if (match.length > 0) {
2300
+ // @ts-ignore
2301
+ const wrapper = { ...previous, chi: [] };
2302
+ // @ts-ignore
2303
+ if (previous.raw[0].length == 0) {
2304
+ // @ts-ignore
2305
+ wrapper.chi.push(...previous.chi);
2306
+ }
2307
+ else {
2308
+ // @ts-ignore
2309
+ previous.sel = previous.raw.reduce((acc, curr) => {
2310
+ acc.push(curr.join(''));
2311
+ return acc;
2312
+ }, []).join(',');
2313
+ // @ts-ignore
2314
+ wrapper.chi.push(previous);
2315
+ }
2316
+ // @ts-ignore
2317
+ if (node.raw[0].length == 0) {
2318
+ // @ts-ignore
2319
+ if (previous.raw.length == 0) {
2320
+ // @ts-ignore
2321
+ wrapper.chi.push(...node.chi);
2322
+ }
2323
+ else {
2324
+ if (hasOnlyDeclarations(wrapper)) {
2325
+ wrapper.chi.push(...node.chi);
2326
+ }
2327
+ else {
2328
+ // @ts-ignore
2329
+ node.raw[0].push('&');
2330
+ // @ts-ignore
2331
+ node.sel = node.raw.reduce((acc, curr) => {
2332
+ acc.push(curr.join(''));
2333
+ return acc;
2334
+ }, []).join(',');
2335
+ // @ts-ignore
2336
+ wrapper.chi.push(node);
2337
+ }
2338
+ }
2339
+ }
2340
+ else {
2341
+ // @ts-ignore
2342
+ node.sel = node.raw.reduce((acc, curr) => {
2343
+ acc.push(curr.join(''));
2344
+ return acc;
2345
+ }, []).join(',');
2346
+ // @ts-ignore
2347
+ wrapper.chi.push(node);
2348
+ }
2349
+ Object.defineProperty(wrapper, 'raw', { enumerable: false, writable: true, value: [match] });
2350
+ // @ts-ignore
2351
+ ast.chi.splice(i, 1, wrapper);
2352
+ // @ts-ignore
2353
+ ast.chi.splice(nodeIndex, 1);
2354
+ // @ts-ignore
2355
+ while (i < ast.chi.length) {
2356
+ // @ts-ignore
2357
+ const nextNode = ast.chi[i];
2358
+ // @ts-ignore
2359
+ if (nextNode.typ != 'Rule' || nextNode.raw == null) {
2360
+ break;
2361
+ }
2362
+ reduceRuleSelector(nextNode);
2363
+ // @ts-ignore
2364
+ if (nextNode.raw.length != 1 || !eq(wrapper.raw[0], nextNode.raw[0].slice(0, wrapper.raw[0].length))) {
2365
+ break;
2366
+ }
2367
+ // @ts-ignore
2368
+ nextNode.raw[0].splice(0, wrapper.raw[0].length);
2369
+ // @ts-ignore
2370
+ if (nextNode.raw[0].length == 0 ||
2371
+ // @ts-ignore
2372
+ (nextNode.raw.length == 1 && nextNode.raw[0] == '&')) {
2373
+ if (hasOnlyDeclarations(wrapper)) {
2374
+ wrapper.chi.push(...nextNode.chi);
2375
+ // @ts-ignore
2376
+ ast.chi.splice(i, 1);
2377
+ continue;
2378
+ }
2379
+ else {
2380
+ // @ts-ignore
2381
+ nextNode.raw[0].push('&');
2382
+ }
2383
+ }
2384
+ // @ts-ignore
2385
+ nextNode.sel = nextNode.raw.reduce((acc, curr) => {
2386
+ acc.push(curr.join(''));
2387
+ return acc;
2388
+ }, []).join(',');
2389
+ wrapper.chi.push(nextNode);
2390
+ // @ts-ignore
2391
+ ast.chi.splice(i, 1);
2392
+ }
2393
+ deduplicateRule(wrapper);
2394
+ nodeIndex = --i;
2395
+ // @ts-ignore
2396
+ previous = ast.chi[i];
2397
+ continue;
2398
+ }
2399
+ }
2400
+ }
2401
+ // @ts-ignore
2273
2402
  if (previous != null && 'chi' in previous && ('chi' in node)) {
2274
2403
  // @ts-ignore
2275
2404
  if (previous.typ == node.typ) {
@@ -2289,7 +2418,7 @@ function deduplicate(ast, options = {}, recursive = false) {
2289
2418
  // @ts-ignore
2290
2419
  if ((node.typ == 'Rule' && node.sel == previous.sel) ||
2291
2420
  // @ts-ignore
2292
- (node.typ == 'AtRule') && node.val == previous.val) {
2421
+ (node.typ == 'AtRule') && node.val != 'font-face' && node.val == previous.val) {
2293
2422
  // @ts-ignore
2294
2423
  node.chi.unshift(...previous.chi);
2295
2424
  // @ts-ignore
@@ -2311,19 +2440,26 @@ function deduplicate(ast, options = {}, recursive = false) {
2311
2440
  if (intersect != null) {
2312
2441
  if (intersect.node1.chi.length == 0) {
2313
2442
  // @ts-ignore
2314
- ast.chi.splice(i, 1);
2443
+ ast.chi.splice(i--, 1);
2444
+ // @ts-ignore
2445
+ node = ast.chi[i];
2315
2446
  }
2316
2447
  else {
2317
2448
  // @ts-ignore
2318
2449
  ast.chi.splice(i, 1, intersect.node1);
2450
+ node = intersect.node1;
2319
2451
  }
2320
2452
  if (intersect.node2.chi.length == 0) {
2321
2453
  // @ts-ignore
2322
2454
  ast.chi.splice(nodeIndex, 1, intersect.result);
2455
+ previous = intersect.result;
2323
2456
  }
2324
2457
  else {
2325
2458
  // @ts-ignore
2326
2459
  ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
2460
+ previous = intersect.result;
2461
+ // @ts-ignore
2462
+ i = nodeIndex;
2327
2463
  }
2328
2464
  }
2329
2465
  }
@@ -2350,12 +2486,24 @@ function deduplicate(ast, options = {}, recursive = false) {
2350
2486
  deduplicateRule(node);
2351
2487
  }
2352
2488
  else {
2353
- deduplicate(node, options, recursive);
2489
+ if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
2490
+ deduplicate(node, options, recursive);
2491
+ }
2354
2492
  }
2355
2493
  }
2356
2494
  }
2357
2495
  return ast;
2358
2496
  }
2497
+ function hasOnlyDeclarations(node) {
2498
+ let k = node.chi.length;
2499
+ while (k--) {
2500
+ if (node.chi[k].typ == 'Comment') {
2501
+ continue;
2502
+ }
2503
+ return node.chi[k].typ == 'Declaration';
2504
+ }
2505
+ return true;
2506
+ }
2359
2507
  function hasDeclaration(node) {
2360
2508
  // @ts-ignore
2361
2509
  for (let i = 0; i < node.chi?.length; i++) {
@@ -2415,30 +2563,6 @@ function deduplicateRule(ast, options = {}) {
2415
2563
  }
2416
2564
  // @ts-ignore
2417
2565
  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
2566
  return ast;
2443
2567
  }
2444
2568
  function splitRule(buffer) {
@@ -2497,7 +2621,6 @@ function splitRule(buffer) {
2497
2621
  }
2498
2622
  }
2499
2623
  i = k;
2500
- continue;
2501
2624
  }
2502
2625
  }
2503
2626
  if (str !== '') {
@@ -2505,6 +2628,35 @@ function splitRule(buffer) {
2505
2628
  }
2506
2629
  return result;
2507
2630
  }
2631
+ function reduceRuleSelector(node) {
2632
+ // @ts-ignore
2633
+ if (node.raw != null) {
2634
+ // @ts-ignore
2635
+ let optimized = reduceSelector(node.raw);
2636
+ if (optimized != null) {
2637
+ Object.defineProperty(node, 'optimized', { enumerable: false, writable: true, value: optimized });
2638
+ }
2639
+ if (optimized != null && optimized.match && optimized.reducible) {
2640
+ const raw = [
2641
+ [
2642
+ optimized.optimized[0], ':is('
2643
+ ].concat(optimized.selector.reduce((acc, curr) => {
2644
+ if (acc.length > 0) {
2645
+ acc.push(',');
2646
+ }
2647
+ acc.push(...curr);
2648
+ return acc;
2649
+ }, [])).concat(')')
2650
+ ];
2651
+ const sel = raw[0].join('');
2652
+ if (sel.length < node.sel.length) {
2653
+ node.sel = sel;
2654
+ // node.raw = raw;
2655
+ Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
2656
+ }
2657
+ }
2658
+ }
2659
+ }
2508
2660
  function diff(n1, n2, options = {}) {
2509
2661
  let node1 = n1;
2510
2662
  let node2 = n2;
@@ -2521,8 +2673,28 @@ function diff(n1, n2, options = {}) {
2521
2673
  // @ts-ignore
2522
2674
  return null;
2523
2675
  }
2676
+ // @ts-ignore
2677
+ const raw1 = node1.raw;
2678
+ // @ts-ignore
2679
+ const optimized1 = node1.optimized;
2680
+ // @ts-ignore
2681
+ const raw2 = node2.raw;
2682
+ // @ts-ignore
2683
+ const optimized2 = node2.optimized;
2524
2684
  node1 = { ...node1, chi: node1.chi.slice() };
2525
2685
  node2 = { ...node2, chi: node2.chi.slice() };
2686
+ if (raw1 != null) {
2687
+ Object.defineProperty(node1, 'raw', { enumerable: false, writable: true, value: raw1 });
2688
+ }
2689
+ if (optimized1 != null) {
2690
+ Object.defineProperty(node1, 'optimized', { enumerable: false, writable: true, value: optimized1 });
2691
+ }
2692
+ if (raw2 != null) {
2693
+ Object.defineProperty(node2, 'raw', { enumerable: false, writable: true, value: raw2 });
2694
+ }
2695
+ if (optimized2 != null) {
2696
+ Object.defineProperty(node2, 'optimized', { enumerable: false, writable: true, value: optimized2 });
2697
+ }
2526
2698
  const intersect = [];
2527
2699
  while (i--) {
2528
2700
  if (node1.chi[i].typ == 'Comment') {
@@ -2550,7 +2722,7 @@ function diff(n1, n2, options = {}) {
2550
2722
  const result = (intersect.length == 0 ? null : {
2551
2723
  ...node1,
2552
2724
  // @ts-ignore
2553
- sel: [...new Set([...(n1.raw || splitRule(n1.sel)).concat(n2.raw || splitRule(n2.sel))])].join(),
2725
+ sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(),
2554
2726
  chi: intersect.reverse()
2555
2727
  });
2556
2728
  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 +2731,63 @@ function diff(n1, n2, options = {}) {
2559
2731
  }
2560
2732
  return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node2 : node2 };
2561
2733
  }
2734
+ function reduceSelector(selector) {
2735
+ if (selector.length < 2) {
2736
+ return null;
2737
+ }
2738
+ const optimized = [];
2739
+ const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
2740
+ let i = 0;
2741
+ let j;
2742
+ let match;
2743
+ for (; i < k; i++) {
2744
+ const item = selector[0][i];
2745
+ match = true;
2746
+ for (j = 1; j < selector.length; j++) {
2747
+ if (item != selector[j][i]) {
2748
+ match = false;
2749
+ break;
2750
+ }
2751
+ }
2752
+ if (!match) {
2753
+ break;
2754
+ }
2755
+ optimized.push(item);
2756
+ }
2757
+ if (optimized.at(-1) == ' ') {
2758
+ optimized.pop();
2759
+ }
2760
+ let reducible = optimized.length == 1;
2761
+ if (optimized.length == 0) {
2762
+ return { match: false, optimized, selector, reducible };
2763
+ }
2764
+ return {
2765
+ match: true,
2766
+ optimized,
2767
+ selector: selector.reduce((acc, curr) => {
2768
+ const slice = curr.slice(optimized.length);
2769
+ // @ts-ignore
2770
+ if (slice.length > 0 && slice[0] == ' ') {
2771
+ slice.shift();
2772
+ }
2773
+ if (slice.length == 0) {
2774
+ slice.push('&');
2775
+ }
2776
+ if (reducible) {
2777
+ const chr = slice[0].charAt(0);
2778
+ // @ts-ignore
2779
+ reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
2780
+ }
2781
+ acc.push(slice);
2782
+ return acc;
2783
+ }, []),
2784
+ reducible
2785
+ };
2786
+ }
2787
+ function reducer(acc, curr) {
2788
+ acc.push(curr.join(''));
2789
+ return acc;
2790
+ }
2562
2791
 
2563
2792
  const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
2564
2793
  const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
@@ -2568,6 +2797,7 @@ async function parse$1(iterator, opt = {}) {
2568
2797
  src: '',
2569
2798
  sourcemap: false,
2570
2799
  compress: false,
2800
+ nestingRules: false,
2571
2801
  resolveImport: false,
2572
2802
  resolveUrls: false,
2573
2803
  removeEmpty: true,
@@ -2838,11 +3068,16 @@ async function parse$1(iterator, opt = {}) {
2838
3068
  try {
2839
3069
  // @ts-ignore
2840
3070
  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 }));
3071
+ return parse$1(src, Object.assign({}, options, {
3072
+ compress: false,
3073
+ // @ts-ignore
3074
+ src: options.resolve(url, options.src).absolute
3075
+ }));
2844
3076
  });
2845
- context.chi.push(...root.ast.chi);
3077
+ bytesIn += root.bytesIn;
3078
+ if (root.ast.chi.length > 0) {
3079
+ context.chi.push(...root.ast.chi);
3080
+ }
2846
3081
  if (root.errors.length > 0) {
2847
3082
  errors.push(...root.errors);
2848
3083
  }
@@ -2857,20 +3092,16 @@ async function parse$1(iterator, opt = {}) {
2857
3092
  // https://www.w3.org/TR/css-nesting-1/#conditionals
2858
3093
  // allowed nesting at-rules
2859
3094
  // there must be a top level rule in the stack
3095
+ const raw = tokens.reduce((acc, curr, index, array) => {
3096
+ acc.push(renderToken(curr, { removeComments: true }));
3097
+ return acc;
3098
+ }, []);
2860
3099
  const node = {
2861
3100
  typ: 'AtRule',
2862
3101
  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
- }, '')
3102
+ val: raw.join('')
2873
3103
  };
3104
+ Object.defineProperty(node, 'raw', { enumerable: false, writable: false, value: raw });
2874
3105
  if (delim.typ == 'Block-start') {
2875
3106
  node.chi = [];
2876
3107
  }
@@ -2895,23 +3126,28 @@ async function parse$1(iterator, opt = {}) {
2895
3126
  return null;
2896
3127
  }
2897
3128
  }
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;
2905
- }
2906
- return acc;
2907
- }, ['']))];
3129
+ const uniq = new Map;
3130
+ parseTokens(tokens, { compress: options.compress }).reduce((acc, curr) => {
3131
+ let t = renderToken(curr, { compress: true });
3132
+ if (t == ',') {
3133
+ acc.push([]);
3134
+ }
3135
+ else {
3136
+ acc[acc.length - 1].push(t);
3137
+ }
3138
+ return acc;
3139
+ }, [[]]).reduce((acc, curr) => {
3140
+ acc.set(curr.join(''), curr);
3141
+ return acc;
3142
+ }, uniq);
2908
3143
  const node = {
2909
3144
  typ: 'Rule',
2910
3145
  // @ts-ignore
2911
- sel: raw.join(','),
3146
+ sel: [...uniq.keys()].join(','),
2912
3147
  chi: []
2913
3148
  };
2914
- Object.defineProperty(node, 'raw', { enumerable: false, get: () => raw });
3149
+ let raw = [...uniq.values()];
3150
+ Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
2915
3151
  loc = {
2916
3152
  sta: position,
2917
3153
  src
@@ -2935,7 +3171,13 @@ async function parse$1(iterator, opt = {}) {
2935
3171
  }
2936
3172
  if (tokens[i].typ == 'Colon') {
2937
3173
  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 });
3174
+ value = parseTokens(tokens.slice(i + 1), {
3175
+ parseColor: true,
3176
+ src: options.src,
3177
+ resolveUrls: options.resolveUrls,
3178
+ resolve: options.resolve,
3179
+ cwd: options.cwd
3180
+ });
2939
3181
  }
2940
3182
  }
2941
3183
  if (name == null) {
@@ -2954,11 +3196,6 @@ async function parse$1(iterator, opt = {}) {
2954
3196
  }
2955
3197
  }
2956
3198
  }
2957
- // if (name.length == 0) {
2958
- //
2959
- // errors.push({action: 'drop', message: 'invalid declaration', location: {src, ...position}});
2960
- // return null;
2961
- // }
2962
3199
  if (value == null) {
2963
3200
  errors.push({ action: 'drop', message: 'invalid declaration', location: { src, ...position } });
2964
3201
  return null;
@@ -2981,16 +3218,6 @@ async function parse$1(iterator, opt = {}) {
2981
3218
  errors.push({ action: 'drop', message: 'invalid declaration', location: { src, ...position } });
2982
3219
  return null;
2983
3220
  }
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
3221
  // @ts-ignore
2995
3222
  context.chi.push(node);
2996
3223
  return null;
@@ -3215,11 +3442,6 @@ async function parse$1(iterator, opt = {}) {
3215
3442
  }
3216
3443
  }
3217
3444
  }
3218
- // else {
3219
- //
3220
- // pushToken(getType(buffer));
3221
- // buffer = '';
3222
- // }
3223
3445
  break;
3224
3446
  case '<':
3225
3447
  if (buffer.length > 0) {
@@ -3297,6 +3519,10 @@ async function parse$1(iterator, opt = {}) {
3297
3519
  if (tokens[tokens.length - 1]?.typ == 'Whitespace') {
3298
3520
  tokens.pop();
3299
3521
  }
3522
+ if (buffer !== '') {
3523
+ pushToken(getType(buffer));
3524
+ buffer = '';
3525
+ }
3300
3526
  pushToken({ typ: 'Gt' });
3301
3527
  consumeWhiteSpace();
3302
3528
  break;
@@ -3311,10 +3537,6 @@ async function parse$1(iterator, opt = {}) {
3311
3537
  buffer += value + next();
3312
3538
  break;
3313
3539
  }
3314
- // if (value == ',' && tokens[tokens.length - 1]?.typ == 'Whitespace') {
3315
- //
3316
- // tokens.pop();
3317
- // }
3318
3540
  pushToken(getType(value));
3319
3541
  buffer = '';
3320
3542
  while (isWhiteSpace(peek().charCodeAt(0))) {
@@ -3337,7 +3559,7 @@ async function parse$1(iterator, opt = {}) {
3337
3559
  pushToken(getType(buffer));
3338
3560
  buffer = '';
3339
3561
  const token = tokens[tokens.length - 1];
3340
- if (token.typ == 'UrlFunc' /* && token.chi == 'url' */) {
3562
+ if (token.typ == 'UrlFunc') {
3341
3563
  // consume either string or url token
3342
3564
  let whitespace = '';
3343
3565
  value = peek();
@@ -3454,15 +3676,6 @@ async function parse$1(iterator, opt = {}) {
3454
3676
  if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
3455
3677
  context.chi.pop();
3456
3678
  }
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
3679
  tokens.length = 0;
3467
3680
  map.clear();
3468
3681
  buffer = '';
@@ -3497,17 +3710,8 @@ async function parse$1(iterator, opt = {}) {
3497
3710
  await parseNode(tokens);
3498
3711
  }
3499
3712
  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
3713
  if (ast.chi.length > 0) {
3510
- deduplicate(ast, options);
3714
+ deduplicate(ast, options, true);
3511
3715
  }
3512
3716
  }
3513
3717
  return { ast, errors, bytesIn };
@@ -3517,8 +3721,10 @@ function parseTokens(tokens, options = {}) {
3517
3721
  const t = tokens[i];
3518
3722
  if (t.typ == 'Whitespace' && ((i == 0 ||
3519
3723
  i + 1 == tokens.length ||
3520
- ['Comma', 'Start-parens'].includes(tokens[i + 1].typ) ||
3521
- (i > 0 && funcLike.includes(tokens[i - 1].typ))))) {
3724
+ ['Comma'].includes(tokens[i + 1].typ) ||
3725
+ (i > 0 &&
3726
+ funcLike.includes(tokens[i - 1].typ) &&
3727
+ !['var', 'calc'].includes(tokens[i - 1].val))))) {
3522
3728
  tokens.splice(i--, 1);
3523
3729
  continue;
3524
3730
  }
@@ -3616,9 +3822,9 @@ function parseTokens(tokens, options = {}) {
3616
3822
  // @ts-ignore
3617
3823
  t.chi.pop();
3618
3824
  }
3825
+ let isColor = true;
3619
3826
  // @ts-ignore
3620
3827
  if (options.parseColor && ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk'].includes(t.val)) {
3621
- let isColor = true;
3622
3828
  // @ts-ignore
3623
3829
  for (const v of t.chi) {
3624
3830
  if (v.typ == 'Func' && v.val == 'var') {
@@ -3626,37 +3832,38 @@ function parseTokens(tokens, options = {}) {
3626
3832
  break;
3627
3833
  }
3628
3834
  }
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) {
3835
+ if (isColor) {
3836
+ // @ts-ignore
3837
+ t.typ = 'Color';
3838
+ // @ts-ignore
3839
+ t.kin = t.val;
3639
3840
  // @ts-ignore
3640
- if (t.chi[m].typ == 'Literal') {
3841
+ let m = t.chi.length;
3842
+ while (m-- > 0) {
3641
3843
  // @ts-ignore
3642
- if (t.chi[m + 1]?.typ == 'Whitespace') {
3844
+ if (t.chi[m].typ == 'Literal') {
3643
3845
  // @ts-ignore
3644
- t.chi.splice(m + 1, 1);
3645
- }
3646
- // @ts-ignore
3647
- if (t.chi[m - 1]?.typ == 'Whitespace') {
3846
+ if (t.chi[m + 1]?.typ == 'Whitespace') {
3847
+ // @ts-ignore
3848
+ t.chi.splice(m + 1, 1);
3849
+ }
3648
3850
  // @ts-ignore
3649
- t.chi.splice(m - 1, 1);
3650
- m--;
3851
+ if (t.chi[m - 1]?.typ == 'Whitespace') {
3852
+ // @ts-ignore
3853
+ t.chi.splice(m - 1, 1);
3854
+ m--;
3855
+ }
3651
3856
  }
3652
3857
  }
3858
+ continue;
3653
3859
  }
3654
3860
  }
3655
- else if (t.typ == 'UrlFunc') {
3861
+ if (t.typ == 'UrlFunc') {
3656
3862
  // @ts-ignore
3657
3863
  if (t.chi[0]?.typ == 'String') {
3658
3864
  // @ts-ignore
3659
3865
  const value = t.chi[0].val.slice(1, -1);
3866
+ // @ts-ignore
3660
3867
  if (t.chi[0].val.slice(1, 5) != 'data:' && urlTokenMatcher.test(value)) {
3661
3868
  // @ts-ignore
3662
3869
  t.chi[0].typ = 'Url-token';
@@ -3874,12 +4081,10 @@ async function load(url, currentFile) {
3874
4081
  }
3875
4082
 
3876
4083
  function parse(iterator, opt = {}) {
3877
- Object.assign(opt, { load, resolve, cwd: opt.cwd ?? process.cwd() });
3878
- return parse$1(iterator, opt);
4084
+ return parse$1(iterator, Object.assign(opt, { load, resolve, cwd: opt.cwd ?? process.cwd() }));
3879
4085
  }
3880
4086
  function transform(css, options = {}) {
3881
- Object.assign(options, { load, resolve, cwd: options.cwd ?? process.cwd() });
3882
- return transform$1(css, options);
4087
+ return transform$1(css, Object.assign(options, { load, resolve, cwd: options.cwd ?? process.cwd() }));
3883
4088
  }
3884
4089
 
3885
4090
  exports.deduplicate = deduplicate;
@@ -3889,6 +4094,7 @@ exports.hasDeclaration = hasDeclaration;
3889
4094
  exports.load = load;
3890
4095
  exports.matchUrl = matchUrl;
3891
4096
  exports.parse = parse;
4097
+ exports.reduceSelector = reduceSelector;
3892
4098
  exports.render = render;
3893
4099
  exports.renderToken = renderToken;
3894
4100
  exports.resolve = resolve;