@blotch/rsbuild-plugin-angular-lynx 22.2.3 → 22.2.5

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.js CHANGED
@@ -12,6 +12,7 @@ import { availableParallelism } from "node:os";
12
12
  import { workspaces } from "@angular-devkit/core";
13
13
  import { NodeJsSyncHost } from "@angular-devkit/core/node";
14
14
  import { access, constants } from "node:fs/promises";
15
+ import postcss_value_parser from "postcss-value-parser";
15
16
  import * as __rspack_external_typescript from "typescript";
16
17
  import * as __rspack_external_node_path_c5b9b54f from "node:path";
17
18
  const ANGULAR_CLI_CONTEXT = Symbol.for('@blotch/rsbuild-plugin-angular-lynx:angular-cli-context');
@@ -527,7 +528,7 @@ const checkThresholds = (thresholds, size, label)=>thresholds.flatMap(({ limit,
527
528
  }
528
529
  ];
529
530
  });
530
- const sum = (sizes)=>sizes.reduce((total, { size })=>total + size, 0);
531
+ const budgets_sum = (sizes)=>sizes.reduce((total, { size })=>total + size, 0);
531
532
  const calculateSizes = (budget, assets, componentStyles)=>{
532
533
  switch(budget.type){
533
534
  case 'initial':
@@ -541,21 +542,21 @@ const calculateSizes = (budget, assets, componentStyles)=>{
541
542
  case 'bundle':
542
543
  return budget.name ? [
543
544
  {
544
- size: sum(assets.filter((asset)=>asset.entryName === budget.name)),
545
+ size: budgets_sum(assets.filter((asset)=>asset.entryName === budget.name)),
545
546
  label: budget.name
546
547
  }
547
548
  ] : [];
548
549
  case 'all':
549
550
  return [
550
551
  {
551
- size: sum(assets),
552
+ size: budgets_sum(assets),
552
553
  label: 'total'
553
554
  }
554
555
  ];
555
556
  case 'allScript':
556
557
  return [
557
558
  {
558
- size: sum(assets),
559
+ size: budgets_sum(assets),
559
560
  label: "total scripts"
560
561
  }
561
562
  ];
@@ -1153,6 +1154,11 @@ const buildTransformedCode = (params)=>{
1153
1154
  compiled: params.code
1154
1155
  });
1155
1156
  };
1157
+ const nativeOutputPattern = (rootPath, distPath)=>{
1158
+ const root = 'string' == typeof distPath ? distPath : distPath?.root;
1159
+ const dist = node_path.resolve(rootPath, root ?? 'dist').replaceAll(node_path.sep, '/').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1160
+ return new RegExp(`^${dist}/(?:ios|android)$`);
1161
+ };
1156
1162
  const applyAngularConfig = (api, buildOptions)=>{
1157
1163
  const __dirname = node_path.dirname(fileURLToPath(import.meta.url));
1158
1164
  api.modifyRsbuildConfig((config)=>{
@@ -1161,7 +1167,12 @@ const applyAngularConfig = (api, buildOptions)=>{
1161
1167
  ...'object' == typeof config.output.distPath ? config.output.distPath : {},
1162
1168
  root: buildOptions.outputPath
1163
1169
  };
1164
- config.output.cleanDistPath = true;
1170
+ config.output.cleanDistPath = {
1171
+ enable: true,
1172
+ keep: [
1173
+ nativeOutputPattern(api.context.rootPath, config.output.distPath)
1174
+ ]
1175
+ };
1165
1176
  config.source ??= {};
1166
1177
  if ('string' == typeof config.source.preEntry) config.source.preEntry = [
1167
1178
  config.source.preEntry
@@ -2287,6 +2298,1830 @@ const applySplitChunksRule = (api, options)=>{
2287
2298
  return rspackConfig;
2288
2299
  });
2289
2300
  };
2301
+ const foldCalc = (value)=>{
2302
+ if (!value.includes('calc(')) return value;
2303
+ const parsed = postcss_value_parser(value);
2304
+ foldNodes(parsed.nodes);
2305
+ return parsed.toString();
2306
+ };
2307
+ const foldNodes = (nodes)=>{
2308
+ for (const node of nodes){
2309
+ if ('function' !== node.type) continue;
2310
+ const folded = 'calc' === node.value.toLowerCase() ? evaluate(node.nodes) : void 0;
2311
+ if (folded) Object.assign(node, {
2312
+ type: 'word',
2313
+ value: formatDimension(folded)
2314
+ });
2315
+ else foldNodes(node.nodes);
2316
+ }
2317
+ };
2318
+ const INFINITY_VALUE = 9999;
2319
+ const formatDimension = ({ value, unit })=>`${Number(value.toFixed(6))}${unit}`;
2320
+ const evaluate = (nodes)=>{
2321
+ const tokens = tokenize(nodes);
2322
+ if (!tokens) return;
2323
+ let position = 0;
2324
+ const peek = ()=>tokens[position];
2325
+ const factor = ()=>{
2326
+ const token = tokens[position++];
2327
+ return 'object' == typeof token ? token : void 0;
2328
+ };
2329
+ const term = ()=>{
2330
+ let left = factor();
2331
+ while(left && ('*' === peek() || '/' === peek())){
2332
+ const operator = tokens[position++];
2333
+ const right = factor();
2334
+ left = right && ('*' === operator ? multiply(left, right) : divide(left, right));
2335
+ }
2336
+ return left;
2337
+ };
2338
+ const expression = ()=>{
2339
+ let left = term();
2340
+ while(left && ('+' === peek() || '-' === peek())){
2341
+ const operator = tokens[position++];
2342
+ const right = term();
2343
+ left = right && add(left, '-' === operator ? negate(right) : right);
2344
+ }
2345
+ return left;
2346
+ };
2347
+ const result = expression();
2348
+ return position === tokens.length ? result : void 0;
2349
+ };
2350
+ const tokenize = (nodes)=>{
2351
+ const tokens = [];
2352
+ for (const node of nodes){
2353
+ if ('space' === node.type || 'comment' === node.type) continue;
2354
+ if ('function' === node.type) {
2355
+ const name = node.value.toLowerCase();
2356
+ const group = 'calc' === name || '' === name ? evaluate(node.nodes) : void 0;
2357
+ if (!group) return;
2358
+ tokens.push(group);
2359
+ continue;
2360
+ }
2361
+ if ('word' !== node.type) return;
2362
+ if ([
2363
+ '+',
2364
+ '-',
2365
+ '*',
2366
+ '/'
2367
+ ].includes(node.value)) {
2368
+ tokens.push(node.value);
2369
+ continue;
2370
+ }
2371
+ if (/^-?infinity$/i.test(node.value)) {
2372
+ tokens.push({
2373
+ value: node.value.startsWith('-') ? -INFINITY_VALUE : INFINITY_VALUE,
2374
+ unit: ''
2375
+ });
2376
+ continue;
2377
+ }
2378
+ const unit = postcss_value_parser.unit(node.value);
2379
+ if (!unit) return;
2380
+ tokens.push({
2381
+ value: Number(unit.number),
2382
+ unit: unit.unit.toLowerCase()
2383
+ });
2384
+ }
2385
+ return tokens;
2386
+ };
2387
+ const negate = ({ value, unit })=>({
2388
+ value: -value,
2389
+ unit
2390
+ });
2391
+ const add = (a, b)=>a.unit === b.unit ? {
2392
+ value: a.value + b.value,
2393
+ unit: a.unit
2394
+ } : void 0;
2395
+ const multiply = (a, b)=>{
2396
+ if (a.unit && b.unit) return;
2397
+ return {
2398
+ value: a.value * b.value,
2399
+ unit: a.unit || b.unit
2400
+ };
2401
+ };
2402
+ const divide = (a, b)=>b.unit || 0 === b.value ? void 0 : {
2403
+ value: a.value / b.value,
2404
+ unit: a.unit
2405
+ };
2406
+ const clampHugeNumbers = (value)=>value.replace(/(-?)\d*\.?\d+e\+?(\d+)([a-z%]*)/gi, (match, sign, exponent, unit)=>Number(exponent) >= 7 ? `${sign}${INFINITY_VALUE}${unit}` : match);
2407
+ const COLOR_FUNCTIONS = new Set([
2408
+ 'rgb',
2409
+ 'rgba',
2410
+ 'hsl',
2411
+ 'hsla',
2412
+ 'hwb',
2413
+ 'lab',
2414
+ 'lch',
2415
+ 'oklab',
2416
+ 'oklch',
2417
+ 'color-mix'
2418
+ ]);
2419
+ const LOWERED_FUNCTIONS = new Set([
2420
+ ...COLOR_FUNCTIONS
2421
+ ].filter((name)=>'rgb' !== name && 'rgba' !== name));
2422
+ const NAMED_COLORS = {
2423
+ aliceblue: 'f0f8ff',
2424
+ antiquewhite: 'faebd7',
2425
+ aqua: '00ffff',
2426
+ aquamarine: '7fffd4',
2427
+ azure: 'f0ffff',
2428
+ beige: 'f5f5dc',
2429
+ bisque: 'ffe4c4',
2430
+ black: '000000',
2431
+ blanchedalmond: 'ffebcd',
2432
+ blue: '0000ff',
2433
+ blueviolet: '8a2be2',
2434
+ brown: 'a52a2a',
2435
+ burlywood: 'deb887',
2436
+ cadetblue: '5f9ea0',
2437
+ chartreuse: '7fff00',
2438
+ chocolate: 'd2691e',
2439
+ coral: 'ff7f50',
2440
+ cornflowerblue: '6495ed',
2441
+ cornsilk: 'fff8dc',
2442
+ crimson: 'dc143c',
2443
+ cyan: '00ffff',
2444
+ darkblue: '00008b',
2445
+ darkcyan: '008b8b',
2446
+ darkgoldenrod: 'b8860b',
2447
+ darkgray: 'a9a9a9',
2448
+ darkgreen: '006400',
2449
+ darkgrey: 'a9a9a9',
2450
+ darkkhaki: 'bdb76b',
2451
+ darkmagenta: '8b008b',
2452
+ darkolivegreen: '556b2f',
2453
+ darkorange: 'ff8c00',
2454
+ darkorchid: '9932cc',
2455
+ darkred: '8b0000',
2456
+ darksalmon: 'e9967a',
2457
+ darkseagreen: '8fbc8f',
2458
+ darkslateblue: '483d8b',
2459
+ darkslategray: '2f4f4f',
2460
+ darkslategrey: '2f4f4f',
2461
+ darkturquoise: '00ced1',
2462
+ darkviolet: '9400d3',
2463
+ deeppink: 'ff1493',
2464
+ deepskyblue: '00bfff',
2465
+ dimgray: '696969',
2466
+ dimgrey: '696969',
2467
+ dodgerblue: '1e90ff',
2468
+ firebrick: 'b22222',
2469
+ floralwhite: 'fffaf0',
2470
+ forestgreen: '228b22',
2471
+ fuchsia: 'ff00ff',
2472
+ gainsboro: 'dcdcdc',
2473
+ ghostwhite: 'f8f8ff',
2474
+ gold: 'ffd700',
2475
+ goldenrod: 'daa520',
2476
+ gray: '808080',
2477
+ green: '008000',
2478
+ greenyellow: 'adff2f',
2479
+ grey: '808080',
2480
+ honeydew: 'f0fff0',
2481
+ hotpink: 'ff69b4',
2482
+ indianred: 'cd5c5c',
2483
+ indigo: '4b0082',
2484
+ ivory: 'fffff0',
2485
+ khaki: 'f0e68c',
2486
+ lavender: 'e6e6fa',
2487
+ lavenderblush: 'fff0f5',
2488
+ lawngreen: '7cfc00',
2489
+ lemonchiffon: 'fffacd',
2490
+ lightblue: 'add8e6',
2491
+ lightcoral: 'f08080',
2492
+ lightcyan: 'e0ffff',
2493
+ lightgoldenrodyellow: 'fafad2',
2494
+ lightgray: 'd3d3d3',
2495
+ lightgreen: '90ee90',
2496
+ lightgrey: 'd3d3d3',
2497
+ lightpink: 'ffb6c1',
2498
+ lightsalmon: 'ffa07a',
2499
+ lightseagreen: '20b2aa',
2500
+ lightskyblue: '87cefa',
2501
+ lightslategray: '778899',
2502
+ lightslategrey: '778899',
2503
+ lightsteelblue: 'b0c4de',
2504
+ lightyellow: 'ffffe0',
2505
+ lime: '00ff00',
2506
+ limegreen: '32cd32',
2507
+ linen: 'faf0e6',
2508
+ magenta: 'ff00ff',
2509
+ maroon: '800000',
2510
+ mediumaquamarine: '66cdaa',
2511
+ mediumblue: '0000cd',
2512
+ mediumorchid: 'ba55d3',
2513
+ mediumpurple: '9370db',
2514
+ mediumseagreen: '3cb371',
2515
+ mediumslateblue: '7b68ee',
2516
+ mediumspringgreen: '00fa9a',
2517
+ mediumturquoise: '48d1cc',
2518
+ mediumvioletred: 'c71585',
2519
+ midnightblue: '191970',
2520
+ mintcream: 'f5fffa',
2521
+ mistyrose: 'ffe4e1',
2522
+ moccasin: 'ffe4b5',
2523
+ navajowhite: 'ffdead',
2524
+ navy: '000080',
2525
+ oldlace: 'fdf5e6',
2526
+ olive: '808000',
2527
+ olivedrab: '6b8e23',
2528
+ orange: 'ffa500',
2529
+ orangered: 'ff4500',
2530
+ orchid: 'da70d6',
2531
+ palegoldenrod: 'eee8aa',
2532
+ palegreen: '98fb98',
2533
+ paleturquoise: 'afeeee',
2534
+ palevioletred: 'db7093',
2535
+ papayawhip: 'ffefd5',
2536
+ peachpuff: 'ffdab9',
2537
+ peru: 'cd853f',
2538
+ pink: 'ffc0cb',
2539
+ plum: 'dda0dd',
2540
+ powderblue: 'b0e0e6',
2541
+ purple: '800080',
2542
+ rebeccapurple: '663399',
2543
+ red: 'ff0000',
2544
+ rosybrown: 'bc8f8f',
2545
+ royalblue: '4169e1',
2546
+ saddlebrown: '8b4513',
2547
+ salmon: 'fa8072',
2548
+ sandybrown: 'f4a460',
2549
+ seagreen: '2e8b57',
2550
+ seashell: 'fff5ee',
2551
+ sienna: 'a0522d',
2552
+ silver: 'c0c0c0',
2553
+ skyblue: '87ceeb',
2554
+ slateblue: '6a5acd',
2555
+ slategray: '708090',
2556
+ slategrey: '708090',
2557
+ snow: 'fffafa',
2558
+ springgreen: '00ff7f',
2559
+ steelblue: '4682b4',
2560
+ tan: 'd2b48c',
2561
+ teal: '008080',
2562
+ thistle: 'd8bfd8',
2563
+ tomato: 'ff6347',
2564
+ turquoise: '40e0d0',
2565
+ violet: 'ee82ee',
2566
+ wheat: 'f5deb3',
2567
+ white: 'ffffff',
2568
+ whitesmoke: 'f5f5f5',
2569
+ yellow: 'ffff00',
2570
+ yellowgreen: '9acd32'
2571
+ };
2572
+ const lowerColors = (value, channelVariables = new Set())=>{
2573
+ if (![
2574
+ ...LOWERED_FUNCTIONS
2575
+ ].some((name)=>value.includes(`${name}(`))) return value;
2576
+ const parsed = postcss_value_parser(value);
2577
+ rewriteColorFunctions(parsed.nodes, channelVariables);
2578
+ return parsed.toString();
2579
+ };
2580
+ const rewriteColorFunctions = (nodes, channelVariables)=>{
2581
+ for (const node of nodes){
2582
+ if ('function' !== node.type) continue;
2583
+ const name = node.value.toLowerCase();
2584
+ const color = LOWERED_FUNCTIONS.has(name) ? parseColor(node) : void 0;
2585
+ if (color) {
2586
+ Object.assign(node, {
2587
+ type: 'word',
2588
+ value: formatRgb(color)
2589
+ });
2590
+ continue;
2591
+ }
2592
+ rewriteColorFunctions(node.nodes, channelVariables);
2593
+ const mixed = 'color-mix' === name ? mixWithChannels(node.nodes, channelVariables) : void 0;
2594
+ if (mixed) Object.assign(node, {
2595
+ type: 'word',
2596
+ value: mixed
2597
+ });
2598
+ }
2599
+ };
2600
+ const mixWithChannels = (nodes, channelVariables)=>{
2601
+ const parts = splitByComma(nodes);
2602
+ if (3 !== parts.length) return;
2603
+ const [, first, second] = parts;
2604
+ const variable = first.find((node)=>'function' === node.type && 'var' === node.value.toLowerCase());
2605
+ const name = variable?.nodes[0]?.value;
2606
+ const percentage = first.filter((node)=>node !== variable).map((node)=>postcss_value_parser.unit(node.value) || {
2607
+ number: '',
2608
+ unit: ''
2609
+ });
2610
+ const isTransparent = 1 === second.length && 'transparent' === second[0].value.toLowerCase();
2611
+ if (!name || !channelVariables.has(name) || 1 !== variable.nodes.length || !isTransparent || percentage.length > 1 || 1 === percentage.length && percentage[0]?.unit !== '%') return;
2612
+ const alpha = percentage[0] ? Number(percentage[0].number) / 100 : 0.5;
2613
+ return `rgba(var(${name}-rgb), ${Number(alpha.toFixed(4))})`;
2614
+ };
2615
+ const formatRgb = ({ r, g, b, alpha })=>{
2616
+ const channel = (value)=>Math.round(255 * clamp01(value));
2617
+ const channels = `${channel(r)}, ${channel(g)}, ${channel(b)}`;
2618
+ const a = Number(clamp01(alpha).toFixed(4));
2619
+ return 1 === a ? `rgb(${channels})` : `rgba(${channels}, ${a})`;
2620
+ };
2621
+ const clamp01 = (value)=>Math.min(1, Math.max(0, value));
2622
+ const parseColor = (node)=>{
2623
+ if ('word' === node.type) {
2624
+ const word = node.value.toLowerCase();
2625
+ if ('transparent' === word) return {
2626
+ r: 0,
2627
+ g: 0,
2628
+ b: 0,
2629
+ alpha: 0
2630
+ };
2631
+ const named = NAMED_COLORS[word];
2632
+ return parseHex('string' == typeof named ? `#${named}` : word);
2633
+ }
2634
+ if ('function' !== node.type) return;
2635
+ const name = node.value.toLowerCase();
2636
+ if (!COLOR_FUNCTIONS.has(name)) return;
2637
+ if ('color-mix' === name) return parseColorMix(node.nodes);
2638
+ const args = colorArguments(node.nodes);
2639
+ if (!args) return;
2640
+ const { channels, alpha } = args;
2641
+ switch(name){
2642
+ case 'rgb':
2643
+ case 'rgba':
2644
+ return withAlpha(rgbFromChannels(channels.map((c)=>colors_channel(c, 255))), alpha);
2645
+ case 'hsl':
2646
+ case 'hsla':
2647
+ return withAlpha(hslToRgb(angle(channels[0]), percent(channels[1]), percent(channels[2])), alpha);
2648
+ case 'hwb':
2649
+ return withAlpha(hwbToRgb(angle(channels[0]), percent(channels[1]), percent(channels[2])), alpha);
2650
+ case 'lab':
2651
+ return withAlpha(labToRgb([
2652
+ colors_channel(channels[0], 100),
2653
+ colors_channel(channels[1], 125),
2654
+ colors_channel(channels[2], 125)
2655
+ ]), alpha);
2656
+ case 'lch':
2657
+ return withAlpha(labToRgb(polarToRectangular([
2658
+ colors_channel(channels[0], 100),
2659
+ colors_channel(channels[1], 150),
2660
+ angle(channels[2])
2661
+ ])), alpha);
2662
+ case 'oklab':
2663
+ return withAlpha(oklabToRgb([
2664
+ colors_channel(channels[0], 1),
2665
+ colors_channel(channels[1], 0.4),
2666
+ colors_channel(channels[2], 0.4)
2667
+ ]), alpha);
2668
+ default:
2669
+ return withAlpha(oklabToRgb(polarToRectangular([
2670
+ colors_channel(channels[0], 1),
2671
+ colors_channel(channels[1], 0.4),
2672
+ angle(channels[2])
2673
+ ])), alpha);
2674
+ }
2675
+ };
2676
+ const rgbFromChannels = ([r, g, b])=>({
2677
+ r: r / 255,
2678
+ g: g / 255,
2679
+ b: b / 255,
2680
+ alpha: 1
2681
+ });
2682
+ const withAlpha = (color, alpha)=>({
2683
+ ...color,
2684
+ alpha: void 0 === alpha ? 1 : colors_channel(alpha, 1)
2685
+ });
2686
+ const parseHex = (word)=>{
2687
+ const match = /^#([\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/i.exec(word);
2688
+ if (!match) return;
2689
+ let hex = match[1];
2690
+ if (hex.length <= 4) hex = [
2691
+ ...hex
2692
+ ].map((digit)=>digit + digit).join('');
2693
+ const byte = (index)=>Number.parseInt(hex.slice(2 * index, 2 * index + 2), 16) / 255;
2694
+ return {
2695
+ r: byte(0),
2696
+ g: byte(1),
2697
+ b: byte(2),
2698
+ alpha: 8 === hex.length ? byte(3) : 1
2699
+ };
2700
+ };
2701
+ const colorArguments = (nodes)=>{
2702
+ const words = [];
2703
+ let alpha;
2704
+ let afterSlash = false;
2705
+ for (const node of nodes)if ('space' !== node.type && 'comment' !== node.type) {
2706
+ if ('div' === node.type) {
2707
+ afterSlash ||= '/' === node.value;
2708
+ continue;
2709
+ }
2710
+ if ('word' !== node.type) return;
2711
+ if (afterSlash) alpha = node.value;
2712
+ else words.push(node.value);
2713
+ }
2714
+ if (void 0 === alpha && 4 === words.length) alpha = words.pop();
2715
+ if (3 !== words.length || ![
2716
+ ...words,
2717
+ ...void 0 === alpha ? [] : [
2718
+ alpha
2719
+ ]
2720
+ ].every(isNumeric)) return;
2721
+ return {
2722
+ channels: words,
2723
+ alpha
2724
+ };
2725
+ };
2726
+ const isNumeric = (word)=>'none' === word.toLowerCase() || false !== postcss_value_parser.unit(word);
2727
+ const colors_channel = (word, full)=>{
2728
+ const { number, unit } = postcss_value_parser.unit(word) || {
2729
+ number: '0',
2730
+ unit: ''
2731
+ };
2732
+ return '%' === unit ? Number(number) / 100 * full : Number(number);
2733
+ };
2734
+ const percent = (word)=>colors_channel(word, 100) / 100;
2735
+ const angle = (word)=>{
2736
+ const { number, unit } = postcss_value_parser.unit(word) || {
2737
+ number: '0',
2738
+ unit: ''
2739
+ };
2740
+ const value = Number(number);
2741
+ switch(unit.toLowerCase()){
2742
+ case 'rad':
2743
+ return 180 * value / Math.PI;
2744
+ case 'grad':
2745
+ return 0.9 * value;
2746
+ case 'turn':
2747
+ return 360 * value;
2748
+ default:
2749
+ return value;
2750
+ }
2751
+ };
2752
+ const hslToRgb = (hue, saturation, lightness)=>{
2753
+ const h = (hue % 360 + 360) % 360;
2754
+ const f = (n)=>{
2755
+ const k = (n + h / 30) % 12;
2756
+ const a = saturation * Math.min(lightness, 1 - lightness);
2757
+ return lightness - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
2758
+ };
2759
+ return {
2760
+ r: f(0),
2761
+ g: f(8),
2762
+ b: f(4),
2763
+ alpha: 1
2764
+ };
2765
+ };
2766
+ const hwbToRgb = (hue, whiteness, blackness)=>{
2767
+ if (whiteness + blackness >= 1) {
2768
+ const gray = whiteness / (whiteness + blackness);
2769
+ return {
2770
+ r: gray,
2771
+ g: gray,
2772
+ b: gray,
2773
+ alpha: 1
2774
+ };
2775
+ }
2776
+ const { r, g, b } = hslToRgb(hue, 1, 0.5);
2777
+ const scale = (value)=>value * (1 - whiteness - blackness) + whiteness;
2778
+ return {
2779
+ r: scale(r),
2780
+ g: scale(g),
2781
+ b: scale(b),
2782
+ alpha: 1
2783
+ };
2784
+ };
2785
+ const polarToRectangular = ([lightness, chroma, hue])=>{
2786
+ const radians = hue * Math.PI / 180;
2787
+ return [
2788
+ lightness,
2789
+ chroma * Math.cos(radians),
2790
+ chroma * Math.sin(radians)
2791
+ ];
2792
+ };
2793
+ const rectangularToPolar = ([lightness, a, b])=>{
2794
+ const hue = 180 * Math.atan2(b, a) / Math.PI;
2795
+ return [
2796
+ lightness,
2797
+ Math.hypot(a, b),
2798
+ (hue + 360) % 360
2799
+ ];
2800
+ };
2801
+ const gammaEncode = (value)=>{
2802
+ const sign = value < 0 ? -1 : 1;
2803
+ const abs = Math.abs(value);
2804
+ return abs > 0.0031308 ? sign * (1.055 * abs ** (1 / 2.4) - 0.055) : 12.92 * value;
2805
+ };
2806
+ const gammaDecode = (value)=>{
2807
+ const sign = value < 0 ? -1 : 1;
2808
+ const abs = Math.abs(value);
2809
+ return abs > 0.04045 ? sign * ((abs + 0.055) / 1.055) ** 2.4 : value / 12.92;
2810
+ };
2811
+ const oklabToLinearRgb = ([l, a, b])=>{
2812
+ const lms = [
2813
+ (l + 0.3963377773761749 * a + 0.2158037573099136 * b) ** 3,
2814
+ (l - 0.1055613458156586 * a - 0.0638541728258133 * b) ** 3,
2815
+ (l - 0.0894841775298119 * a - 1.2914855480194092 * b) ** 3
2816
+ ];
2817
+ return [
2818
+ 4.0767416360759583 * lms[0] - 3.3077115392580629 * lms[1] + 0.2309699031821043 * lms[2],
2819
+ -1.2684379732850315 * lms[0] + 2.6097573492876882 * lms[1] - 0.341319376002657 * lms[2],
2820
+ -0.0041960761386756 * lms[0] - 0.7034186179359363 * lms[1] + 1.7076146940746117 * lms[2]
2821
+ ];
2822
+ };
2823
+ const linearRgbToOklab = ([r, g, b])=>{
2824
+ const lms = [
2825
+ Math.cbrt(0.4122214694707629 * r + 0.5363325372617349 * g + 0.0514459932675022 * b),
2826
+ Math.cbrt(0.2119034958178251 * r + 0.6806995506452344 * g + 0.1073969535369406 * b),
2827
+ Math.cbrt(0.0883024591900564 * r + 0.2817188391361215 * g + 0.6299787016738223 * b)
2828
+ ];
2829
+ return [
2830
+ 0.2104542553 * lms[0] + 0.793617785 * lms[1] - 0.0040720468 * lms[2],
2831
+ 1.9779984951 * lms[0] - 2.428592205 * lms[1] + 0.4505937099 * lms[2],
2832
+ 0.0259040371 * lms[0] + 0.7827717662 * lms[1] - 0.808675766 * lms[2]
2833
+ ];
2834
+ };
2835
+ const encodeRgb = ([r, g, b])=>({
2836
+ r: gammaEncode(r),
2837
+ g: gammaEncode(g),
2838
+ b: gammaEncode(b),
2839
+ alpha: 1
2840
+ });
2841
+ const rgbToOklab = ({ r, g, b })=>linearRgbToOklab([
2842
+ gammaDecode(r),
2843
+ gammaDecode(g),
2844
+ gammaDecode(b)
2845
+ ]);
2846
+ const isInGamut = ({ r, g, b })=>[
2847
+ r,
2848
+ g,
2849
+ b
2850
+ ].every((value)=>value >= -0.000001 && value <= 1 + 1e-6);
2851
+ const clip = ({ r, g, b, alpha })=>({
2852
+ r: clamp01(r),
2853
+ g: clamp01(g),
2854
+ b: clamp01(b),
2855
+ alpha
2856
+ });
2857
+ const oklabToRgb = (oklab)=>{
2858
+ const color = encodeRgb(oklabToLinearRgb(oklab));
2859
+ if (isInGamut(color)) return color;
2860
+ const [lightness, chroma, hue] = rectangularToPolar(oklab);
2861
+ if (lightness >= 1) return {
2862
+ r: 1,
2863
+ g: 1,
2864
+ b: 1,
2865
+ alpha: 1
2866
+ };
2867
+ if (lightness <= 0) return {
2868
+ r: 0,
2869
+ g: 0,
2870
+ b: 0,
2871
+ alpha: 1
2872
+ };
2873
+ const JND = 0.02;
2874
+ const EPSILON = 0.0001;
2875
+ const atChroma = (c)=>encodeRgb(oklabToLinearRgb(polarToRectangular([
2876
+ lightness,
2877
+ c,
2878
+ hue
2879
+ ])));
2880
+ const deltaE = (a, b)=>Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]);
2881
+ let clipped = clip(color);
2882
+ if (deltaE(rgbToOklab(clipped), oklab) < JND) return clipped;
2883
+ let min = 0;
2884
+ let max = chroma;
2885
+ let minInGamut = true;
2886
+ while(max - min > EPSILON){
2887
+ const c = (min + max) / 2;
2888
+ const current = atChroma(c);
2889
+ if (minInGamut && isInGamut(current)) {
2890
+ min = c;
2891
+ continue;
2892
+ }
2893
+ clipped = clip(current);
2894
+ const e = deltaE(rgbToOklab(clipped), polarToRectangular([
2895
+ lightness,
2896
+ c,
2897
+ hue
2898
+ ]));
2899
+ if (e < JND) {
2900
+ if (JND - e < EPSILON) break;
2901
+ minInGamut = false;
2902
+ min = c;
2903
+ } else max = c;
2904
+ }
2905
+ return clipped;
2906
+ };
2907
+ const labToRgb = ([l, a, b])=>{
2908
+ const k = 24389 / 27;
2909
+ const e = 216 / 24389;
2910
+ const fy = (l + 16) / 116;
2911
+ const fx = a / 500 + fy;
2912
+ const fz = fy - b / 200;
2913
+ const xyz = [
2914
+ (fx ** 3 > e ? fx ** 3 : (116 * fx - 16) / k) * 0.3457 / 0.3585,
2915
+ l > k * e ? fy ** 3 : l / k,
2916
+ (fz ** 3 > e ? fz ** 3 : (116 * fz - 16) / k) * 0.2958 / 0.3585
2917
+ ];
2918
+ const d65 = [
2919
+ 0.955473421488075 * xyz[0] - 0.02309845494876471 * xyz[1] + 0.06325924320057072 * xyz[2],
2920
+ -0.0283697093338637 * xyz[0] + 1.0099953980813041 * xyz[1] + 0.021041441191917323 * xyz[2],
2921
+ 0.012314014864481998 * xyz[0] - 0.020507649298898964 * xyz[1] + 1.330365926242124 * xyz[2]
2922
+ ];
2923
+ const linear = [
2924
+ 3.2409699419045226 * d65[0] - 1.537383177570094 * d65[1] - 0.4986107602930034 * d65[2],
2925
+ -0.9692436362808796 * d65[0] + 1.8759675015077202 * d65[1] + 0.04155505740717559 * d65[2],
2926
+ 0.05563007969699366 * d65[0] - 0.20397695888897652 * d65[1] + 1.0569715142428786 * d65[2]
2927
+ ];
2928
+ const color = encodeRgb(linear);
2929
+ return isInGamut(color) ? color : oklabToRgb(linearRgbToOklab(linear));
2930
+ };
2931
+ const parseColorMix = (nodes)=>{
2932
+ const parts = splitByComma(nodes);
2933
+ if (3 !== parts.length) return;
2934
+ const space = mixSpace(parts[0]);
2935
+ const first = mixColor(parts[1]);
2936
+ const second = mixColor(parts[2]);
2937
+ if (!space || !first || !second) return;
2938
+ let p1 = first.percentage;
2939
+ let p2 = second.percentage;
2940
+ if (void 0 === p1 && void 0 === p2) p1 = p2 = 50;
2941
+ else if (void 0 === p1) p1 = 100 - p2;
2942
+ else if (void 0 === p2) p2 = 100 - p1;
2943
+ const sum = p1 + p2;
2944
+ if (sum <= 0) return;
2945
+ const mixed = interpolate(space, first.color, second.color, p2 / sum);
2946
+ return {
2947
+ ...mixed,
2948
+ alpha: mixed.alpha * Math.min(sum, 100) / 100
2949
+ };
2950
+ };
2951
+ const splitByComma = (nodes)=>{
2952
+ const parts = [
2953
+ []
2954
+ ];
2955
+ for (const node of nodes)if ('div' === node.type && ',' === node.value) parts.push([]);
2956
+ else if ('space' !== node.type && 'comment' !== node.type) parts[parts.length - 1].push(node);
2957
+ return parts;
2958
+ };
2959
+ const MIX_SPACES = new Set([
2960
+ 'srgb',
2961
+ 'srgb-linear',
2962
+ 'oklab',
2963
+ 'oklch'
2964
+ ]);
2965
+ const mixSpace = (nodes)=>{
2966
+ const words = nodes.map((node)=>node.value.toLowerCase());
2967
+ const [keyword, space, ...hue] = words;
2968
+ const defaultHue = 0 === hue.length || 'shorter' === hue[0] && 'hue' === hue[1];
2969
+ return 'in' === keyword && MIX_SPACES.has(space) && defaultHue ? space : void 0;
2970
+ };
2971
+ const mixColor = (nodes)=>{
2972
+ let color;
2973
+ let percentage;
2974
+ for (const node of nodes){
2975
+ const unit = 'word' === node.type && postcss_value_parser.unit(node.value);
2976
+ if (unit && '%' === unit.unit && void 0 === percentage) percentage = Number(unit.number);
2977
+ else {
2978
+ if (color) return;
2979
+ color = parseColor(node);
2980
+ if (!color) return;
2981
+ }
2982
+ }
2983
+ return color && {
2984
+ color,
2985
+ percentage
2986
+ };
2987
+ };
2988
+ const interpolate = (space, from, to, weight)=>{
2989
+ const alpha = from.alpha * (1 - weight) + to.alpha * weight;
2990
+ if (0 === alpha) return {
2991
+ r: 0,
2992
+ g: 0,
2993
+ b: 0,
2994
+ alpha: 0
2995
+ };
2996
+ const blend = (a, b)=>(a * from.alpha * (1 - weight) + b * to.alpha * weight) / alpha;
2997
+ switch(space){
2998
+ case 'srgb':
2999
+ return {
3000
+ r: blend(from.r, to.r),
3001
+ g: blend(from.g, to.g),
3002
+ b: blend(from.b, to.b),
3003
+ alpha
3004
+ };
3005
+ case 'srgb-linear':
3006
+ return {
3007
+ ...encodeRgb([
3008
+ blend(gammaDecode(from.r), gammaDecode(to.r)),
3009
+ blend(gammaDecode(from.g), gammaDecode(to.g)),
3010
+ blend(gammaDecode(from.b), gammaDecode(to.b))
3011
+ ]),
3012
+ alpha
3013
+ };
3014
+ case 'oklab':
3015
+ {
3016
+ const a = rgbToOklab(from);
3017
+ const b = rgbToOklab(to);
3018
+ return {
3019
+ ...oklabToRgb([
3020
+ blend(a[0], b[0]),
3021
+ blend(a[1], b[1]),
3022
+ blend(a[2], b[2])
3023
+ ]),
3024
+ alpha
3025
+ };
3026
+ }
3027
+ default:
3028
+ {
3029
+ const a = rectangularToPolar(rgbToOklab(from));
3030
+ const b = rectangularToPolar(rgbToOklab(to));
3031
+ const powerless = (color, source)=>color[1] < 1e-4 || 0 === source.alpha;
3032
+ const hueA = powerless(a, from) ? b[2] : a[2];
3033
+ const hueB = powerless(b, to) ? a[2] : b[2];
3034
+ let delta = hueB - hueA;
3035
+ if (delta > 180) delta -= 360;
3036
+ else if (delta < -180) delta += 360;
3037
+ const hue = hueA + delta * weight;
3038
+ return {
3039
+ ...oklabToRgb(polarToRectangular([
3040
+ blend(a[0], b[0]),
3041
+ blend(a[1], b[1]),
3042
+ hue
3043
+ ])),
3044
+ alpha
3045
+ };
3046
+ }
3047
+ }
3048
+ };
3049
+ const LYNX_PROPERTIES = new Set([
3050
+ '-x-animation-color-interpolation',
3051
+ '-x-app-region',
3052
+ '-x-auto-font-size',
3053
+ '-x-auto-font-size-line-ranges',
3054
+ '-x-auto-font-size-preset-sizes',
3055
+ '-x-box-match-parent-size',
3056
+ '-x-box-propagate-min-constraints',
3057
+ '-x-caret-gradient',
3058
+ '-x-caret-height',
3059
+ '-x-caret-radius',
3060
+ '-x-caret-width',
3061
+ '-x-handle-color',
3062
+ '-x-handle-size',
3063
+ '-x-placeholder-color',
3064
+ '-x-placeholder-font-family',
3065
+ '-x-placeholder-font-size',
3066
+ '-x-placeholder-font-style',
3067
+ '-x-placeholder-font-weight',
3068
+ '-x-text-decoration-gap',
3069
+ '-x-text-decoration-width',
3070
+ 'adapt-font-size',
3071
+ 'align-content',
3072
+ 'align-items',
3073
+ 'align-self',
3074
+ 'animation',
3075
+ 'animation-delay',
3076
+ 'animation-direction',
3077
+ 'animation-duration',
3078
+ 'animation-fill-mode',
3079
+ 'animation-iteration-count',
3080
+ 'animation-name',
3081
+ 'animation-play-state',
3082
+ 'animation-timing-function',
3083
+ 'aspect-ratio',
3084
+ 'background',
3085
+ 'background-clip',
3086
+ 'background-color',
3087
+ 'background-image',
3088
+ 'background-origin',
3089
+ 'background-position',
3090
+ 'background-repeat',
3091
+ 'background-size',
3092
+ 'border',
3093
+ 'border-bottom',
3094
+ 'border-bottom-color',
3095
+ 'border-bottom-left-radius',
3096
+ 'border-bottom-right-radius',
3097
+ 'border-bottom-style',
3098
+ 'border-bottom-width',
3099
+ 'border-color',
3100
+ 'border-end-end-radius',
3101
+ 'border-end-start-radius',
3102
+ 'border-inline-end-color',
3103
+ 'border-inline-end-style',
3104
+ 'border-inline-end-width',
3105
+ 'border-inline-start-color',
3106
+ 'border-inline-start-style',
3107
+ 'border-inline-start-width',
3108
+ 'border-left',
3109
+ 'border-left-color',
3110
+ 'border-left-style',
3111
+ 'border-left-width',
3112
+ 'border-radius',
3113
+ 'border-right',
3114
+ 'border-right-color',
3115
+ 'border-right-style',
3116
+ 'border-right-width',
3117
+ 'border-start-end-radius',
3118
+ 'border-start-start-radius',
3119
+ 'border-style',
3120
+ 'border-top',
3121
+ 'border-top-color',
3122
+ 'border-top-left-radius',
3123
+ 'border-top-right-radius',
3124
+ 'border-top-style',
3125
+ 'border-top-width',
3126
+ 'border-width',
3127
+ 'bottom',
3128
+ 'box-shadow',
3129
+ 'box-sizing',
3130
+ 'caret-color',
3131
+ 'clip-path',
3132
+ 'color',
3133
+ 'column-gap',
3134
+ 'content',
3135
+ 'cursor',
3136
+ 'direction',
3137
+ 'display',
3138
+ 'enter-transition-name',
3139
+ 'exit-transition-name',
3140
+ 'filter',
3141
+ 'flex',
3142
+ 'flex-basis',
3143
+ 'flex-direction',
3144
+ 'flex-flow',
3145
+ 'flex-grow',
3146
+ 'flex-shrink',
3147
+ 'flex-wrap',
3148
+ 'font-family',
3149
+ 'font-feature-settings',
3150
+ 'font-optical-sizing',
3151
+ 'font-size',
3152
+ 'font-style',
3153
+ 'font-variation-settings',
3154
+ 'font-weight',
3155
+ 'gap',
3156
+ 'grid-auto-columns',
3157
+ 'grid-auto-flow',
3158
+ 'grid-auto-rows',
3159
+ 'grid-column',
3160
+ 'grid-column-end',
3161
+ 'grid-column-gap',
3162
+ 'grid-column-span',
3163
+ 'grid-column-start',
3164
+ 'grid-row',
3165
+ 'grid-row-end',
3166
+ 'grid-row-gap',
3167
+ 'grid-row-span',
3168
+ 'grid-row-start',
3169
+ 'grid-template-columns',
3170
+ 'grid-template-rows',
3171
+ 'height',
3172
+ 'hyphens',
3173
+ 'image-rendering',
3174
+ 'implicit-animation',
3175
+ 'inset-inline-end',
3176
+ 'inset-inline-start',
3177
+ 'justify-content',
3178
+ 'justify-items',
3179
+ 'justify-self',
3180
+ 'layout-animation-create-delay',
3181
+ 'layout-animation-create-duration',
3182
+ 'layout-animation-create-property',
3183
+ 'layout-animation-create-timing-function',
3184
+ 'layout-animation-delete-delay',
3185
+ 'layout-animation-delete-duration',
3186
+ 'layout-animation-delete-property',
3187
+ 'layout-animation-delete-timing-function',
3188
+ 'layout-animation-update-delay',
3189
+ 'layout-animation-update-duration',
3190
+ 'layout-animation-update-timing-function',
3191
+ 'left',
3192
+ 'letter-spacing',
3193
+ 'line-height',
3194
+ 'line-spacing',
3195
+ 'linear-cross-gravity',
3196
+ 'linear-direction',
3197
+ 'linear-gravity',
3198
+ 'linear-layout-gravity',
3199
+ 'linear-orientation',
3200
+ 'linear-weight',
3201
+ 'linear-weight-sum',
3202
+ 'list-cross-axis-gap',
3203
+ 'list-main-axis-gap',
3204
+ 'margin',
3205
+ 'margin-bottom',
3206
+ 'margin-inline-end',
3207
+ 'margin-inline-start',
3208
+ 'margin-left',
3209
+ 'margin-right',
3210
+ 'margin-top',
3211
+ 'mask',
3212
+ 'mask-clip',
3213
+ 'mask-composite',
3214
+ 'mask-image',
3215
+ 'mask-origin',
3216
+ 'mask-position',
3217
+ 'mask-repeat',
3218
+ 'mask-size',
3219
+ 'max-height',
3220
+ 'max-width',
3221
+ 'min-height',
3222
+ 'min-width',
3223
+ 'offset-distance',
3224
+ 'offset-path',
3225
+ 'offset-rotate',
3226
+ 'opacity',
3227
+ 'order',
3228
+ 'outline',
3229
+ 'outline-color',
3230
+ 'outline-style',
3231
+ 'outline-width',
3232
+ 'overflow',
3233
+ 'overflow-x',
3234
+ 'overflow-y',
3235
+ 'padding',
3236
+ 'padding-bottom',
3237
+ 'padding-inline-end',
3238
+ 'padding-inline-start',
3239
+ 'padding-left',
3240
+ 'padding-right',
3241
+ 'padding-top',
3242
+ 'pause-transition-name',
3243
+ 'perspective',
3244
+ 'pointer-events',
3245
+ 'position',
3246
+ 'relative-align-bottom',
3247
+ 'relative-align-inline-end',
3248
+ 'relative-align-inline-start',
3249
+ 'relative-align-left',
3250
+ 'relative-align-right',
3251
+ 'relative-align-top',
3252
+ 'relative-bottom-of',
3253
+ 'relative-center',
3254
+ 'relative-id',
3255
+ 'relative-inline-end-of',
3256
+ 'relative-inline-start-of',
3257
+ 'relative-layout-once',
3258
+ 'relative-left-of',
3259
+ 'relative-right-of',
3260
+ 'relative-top-of',
3261
+ 'resume-transition-name',
3262
+ 'right',
3263
+ 'row-gap',
3264
+ 'text-align',
3265
+ 'text-decoration',
3266
+ 'text-decoration-color',
3267
+ 'text-decoration-thickness',
3268
+ 'text-indent',
3269
+ 'text-overflow',
3270
+ 'text-shadow',
3271
+ 'text-stroke',
3272
+ 'text-stroke-color',
3273
+ 'text-stroke-width',
3274
+ 'top',
3275
+ 'transform',
3276
+ 'transform-origin',
3277
+ 'transition',
3278
+ 'transition-delay',
3279
+ 'transition-duration',
3280
+ 'transition-property',
3281
+ 'transition-timing-function',
3282
+ 'vertical-align',
3283
+ 'visibility',
3284
+ 'white-space',
3285
+ 'width',
3286
+ 'word-break',
3287
+ 'z-index'
3288
+ ]);
3289
+ const LYNX_KEYWORDS = new Map(Object.entries({
3290
+ '-x-animation-color-interpolation': [
3291
+ 'auto',
3292
+ 'srgb',
3293
+ 'linearrgb'
3294
+ ],
3295
+ '-x-app-region': [
3296
+ 'none',
3297
+ 'drag',
3298
+ 'no-drag'
3299
+ ],
3300
+ '-x-placeholder-font-style': [
3301
+ 'normal',
3302
+ 'italic',
3303
+ 'oblique'
3304
+ ],
3305
+ '-x-placeholder-font-weight': [
3306
+ 'normal',
3307
+ 'bold',
3308
+ '100',
3309
+ '200',
3310
+ '300',
3311
+ '400',
3312
+ '500',
3313
+ '600',
3314
+ '700',
3315
+ '800',
3316
+ '900'
3317
+ ],
3318
+ 'align-content': [
3319
+ 'flex-start',
3320
+ 'flex-end',
3321
+ 'center',
3322
+ 'stretch',
3323
+ 'space-between',
3324
+ 'space-around',
3325
+ 'start',
3326
+ 'end'
3327
+ ],
3328
+ 'box-sizing': [
3329
+ 'border-box',
3330
+ 'content-box',
3331
+ 'auto'
3332
+ ],
3333
+ direction: [
3334
+ 'normal',
3335
+ 'lynx-rtl',
3336
+ 'rtl',
3337
+ 'ltr'
3338
+ ],
3339
+ display: [
3340
+ 'none',
3341
+ 'flex',
3342
+ 'grid',
3343
+ 'linear',
3344
+ 'relative',
3345
+ 'block',
3346
+ 'auto',
3347
+ '-x-box'
3348
+ ],
3349
+ 'flex-direction': [
3350
+ 'column',
3351
+ 'row',
3352
+ 'row-reverse',
3353
+ 'column-reverse'
3354
+ ],
3355
+ 'flex-wrap': [
3356
+ 'wrap',
3357
+ 'nowrap',
3358
+ 'wrap-reverse'
3359
+ ],
3360
+ 'font-optical-sizing': [
3361
+ 'none',
3362
+ 'auto'
3363
+ ],
3364
+ 'font-style': [
3365
+ 'normal',
3366
+ 'italic',
3367
+ 'oblique'
3368
+ ],
3369
+ 'font-weight': [
3370
+ 'normal',
3371
+ 'bold',
3372
+ '100',
3373
+ '200',
3374
+ '300',
3375
+ '400',
3376
+ '500',
3377
+ '600',
3378
+ '700',
3379
+ '800',
3380
+ '900'
3381
+ ],
3382
+ hyphens: [
3383
+ 'none',
3384
+ 'manual',
3385
+ 'auto'
3386
+ ],
3387
+ 'image-rendering': [
3388
+ 'auto',
3389
+ 'crisp-edges',
3390
+ 'pixelated'
3391
+ ],
3392
+ 'justify-content': [
3393
+ 'flex-start',
3394
+ 'center',
3395
+ 'flex-end',
3396
+ 'space-between',
3397
+ 'space-around',
3398
+ 'space-evenly',
3399
+ 'stretch',
3400
+ 'start',
3401
+ 'end'
3402
+ ],
3403
+ 'linear-cross-gravity': [
3404
+ 'none',
3405
+ 'start',
3406
+ 'end',
3407
+ 'center',
3408
+ 'stretch'
3409
+ ],
3410
+ 'linear-gravity': [
3411
+ 'none',
3412
+ 'top',
3413
+ 'bottom',
3414
+ 'left',
3415
+ 'right',
3416
+ 'center-vertical',
3417
+ 'center-horizontal',
3418
+ 'space-between',
3419
+ 'start',
3420
+ 'end',
3421
+ 'center'
3422
+ ],
3423
+ 'linear-layout-gravity': [
3424
+ 'none',
3425
+ 'top',
3426
+ 'bottom',
3427
+ 'left',
3428
+ 'right',
3429
+ 'center-vertical',
3430
+ 'center-horizontal',
3431
+ 'fill-vertical',
3432
+ 'fill-horizontal',
3433
+ 'center',
3434
+ 'stretch',
3435
+ 'start',
3436
+ 'end'
3437
+ ],
3438
+ 'linear-orientation': [
3439
+ 'horizontal',
3440
+ 'vertical',
3441
+ 'horizontal-reverse',
3442
+ 'vertical-reverse',
3443
+ 'row',
3444
+ 'column',
3445
+ 'row-reverse',
3446
+ 'column-reverse'
3447
+ ],
3448
+ 'pointer-events': [
3449
+ 'auto',
3450
+ 'none'
3451
+ ],
3452
+ position: [
3453
+ 'absolute',
3454
+ 'relative',
3455
+ 'fixed',
3456
+ 'sticky'
3457
+ ],
3458
+ 'relative-center': [
3459
+ 'none',
3460
+ 'vertical',
3461
+ 'horizontal',
3462
+ 'both'
3463
+ ],
3464
+ 'text-align': [
3465
+ 'left',
3466
+ 'center',
3467
+ 'right',
3468
+ 'start',
3469
+ 'end',
3470
+ 'justify'
3471
+ ],
3472
+ 'text-overflow': [
3473
+ 'clip',
3474
+ 'ellipsis'
3475
+ ],
3476
+ visibility: [
3477
+ 'hidden',
3478
+ 'visible',
3479
+ 'none',
3480
+ 'collapse'
3481
+ ],
3482
+ 'white-space': [
3483
+ 'normal',
3484
+ 'nowrap'
3485
+ ],
3486
+ 'word-break': [
3487
+ 'normal',
3488
+ 'break-all',
3489
+ 'keep-all'
3490
+ ]
3491
+ }).map(([property, keywords])=>[
3492
+ property,
3493
+ new Set(keywords)
3494
+ ]));
3495
+ const COMPOSED_TRANSFORM = "translate3d(var(--tw-translate-x), var(--tw-translate-y), var(--tw-translate-z)) rotate(var(--tw-rotate)) scale(var(--tw-scale-x), var(--tw-scale-y)) var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)";
3496
+ const TRANSFORM_DEFAULTS = new Map([
3497
+ [
3498
+ '--tw-translate-x',
3499
+ '0'
3500
+ ],
3501
+ [
3502
+ '--tw-translate-y',
3503
+ '0'
3504
+ ],
3505
+ [
3506
+ '--tw-translate-z',
3507
+ '0'
3508
+ ],
3509
+ [
3510
+ '--tw-rotate',
3511
+ '0deg'
3512
+ ],
3513
+ [
3514
+ '--tw-scale-x',
3515
+ '1'
3516
+ ],
3517
+ [
3518
+ '--tw-scale-y',
3519
+ '1'
3520
+ ]
3521
+ ]);
3522
+ const lowerDeclarations = (rule, channelVariables = new Set())=>{
3523
+ const composed = [];
3524
+ for (const declaration of rule.nodes.slice())if ('decl' === declaration.type) {
3525
+ declaration.value = lowerColors(declaration.value, channelVariables);
3526
+ if (lowerTransformProperty(declaration)) {
3527
+ composed.push(declaration);
3528
+ continue;
3529
+ }
3530
+ lowerValue(declaration);
3531
+ expandLogical(declaration);
3532
+ }
3533
+ if (composed.length > 0) {
3534
+ composed[composed.length - 1].before({
3535
+ prop: 'transform',
3536
+ value: COMPOSED_TRANSFORM
3537
+ });
3538
+ for (const declaration of composed)declaration.remove();
3539
+ }
3540
+ dropUnsupportedProperties(rule);
3541
+ return {
3542
+ composesTransform: composed.length > 0
3543
+ };
3544
+ };
3545
+ const TRANSFORM_VARIABLES = /^--tw-(?:translate-[xyz]|rotate(?:-[xyz])?|skew-[xy]|scale-[xyz])$/;
3546
+ const lowerTransformVariables = (root)=>{
3547
+ root.walkDecls(TRANSFORM_VARIABLES, (declaration)=>{
3548
+ declaration.value = transformValue(declaration.prop, declaration.value);
3549
+ });
3550
+ };
3551
+ const lowerTransformProperty = (declaration)=>{
3552
+ const { prop } = declaration;
3553
+ const values = splitSpaces(declaration.value);
3554
+ switch(prop){
3555
+ case 'translate':
3556
+ if (!isTailwindComposition(values, '--tw-translate-')) {
3557
+ const [x, y = '0', z = '0'] = 'none' === values[0] ? [
3558
+ '0',
3559
+ '0',
3560
+ '0'
3561
+ ] : values;
3562
+ setVariables(declaration, {
3563
+ '--tw-translate-x': x,
3564
+ '--tw-translate-y': y,
3565
+ '--tw-translate-z': z
3566
+ });
3567
+ }
3568
+ break;
3569
+ case 'rotate':
3570
+ if (1 !== values.length) return false;
3571
+ setVariables(declaration, {
3572
+ '--tw-rotate': 'none' === values[0] ? '0deg' : values[0]
3573
+ });
3574
+ break;
3575
+ case 'scale':
3576
+ if (!isTailwindComposition(values, '--tw-scale-')) {
3577
+ const [x, y = x] = 'none' === values[0] ? [
3578
+ '1',
3579
+ '1'
3580
+ ] : values;
3581
+ setVariables(declaration, {
3582
+ '--tw-scale-x': x,
3583
+ '--tw-scale-y': y
3584
+ });
3585
+ }
3586
+ break;
3587
+ case 'transform':
3588
+ if (!isTailwindComposition(values, '--tw-')) return false;
3589
+ break;
3590
+ default:
3591
+ return false;
3592
+ }
3593
+ return true;
3594
+ };
3595
+ const isTailwindComposition = (values, prefix)=>values.length > 0 && values.every((value)=>value.startsWith(`var(${prefix}`));
3596
+ const setVariables = (declaration, variables)=>{
3597
+ for (const [prop, value] of Object.entries(variables))declaration.before({
3598
+ prop,
3599
+ value: transformValue(prop, value)
3600
+ });
3601
+ };
3602
+ const transformValue = (prop, value)=>{
3603
+ const folded = foldCalc(value);
3604
+ if (!prop.startsWith('--tw-scale-')) return folded;
3605
+ const unit = postcss_value_parser.unit(folded);
3606
+ return unit && '%' === unit.unit ? String(Number(unit.number) / 100) : folded;
3607
+ };
3608
+ const splitSpaces = (value)=>postcss_value_parser(value).nodes.filter((node)=>'space' !== node.type && 'comment' !== node.type).map((node)=>postcss_value_parser.stringify(node));
3609
+ const lowerValue = (declaration)=>{
3610
+ switch(declaration.prop){
3611
+ case 'opacity':
3612
+ {
3613
+ const unit = postcss_value_parser.unit(declaration.value);
3614
+ if (unit && '%' === unit.unit) declaration.value = String(Number(unit.number) / 100);
3615
+ break;
3616
+ }
3617
+ case 'text-decoration-line':
3618
+ declaration.prop = 'text-decoration';
3619
+ break;
3620
+ case 'transition-property':
3621
+ declaration.value = lowerTransitionProperty(declaration.value);
3622
+ break;
3623
+ case '--tw-gradient-position':
3624
+ declaration.value = lowerGradientPosition(declaration);
3625
+ break;
3626
+ default:
3627
+ if (/\binfinity\b/i.test(declaration.value)) declaration.value = foldCalc(declaration.value);
3628
+ declaration.value = clampHugeNumbers(declaration.value);
3629
+ break;
3630
+ }
3631
+ };
3632
+ const lowerTransitionProperty = (value)=>{
3633
+ const properties = value.split(',').map((property)=>{
3634
+ const name = property.trim().toLowerCase();
3635
+ return [
3636
+ 'translate',
3637
+ 'rotate',
3638
+ 'scale'
3639
+ ].includes(name) ? 'transform' : name;
3640
+ }).filter((name)=>'all' === name || 'none' === name || LYNX_PROPERTIES.has(name));
3641
+ return [
3642
+ ...new Set(properties)
3643
+ ].join(', ') || 'none';
3644
+ };
3645
+ const lowerGradientPosition = (declaration)=>{
3646
+ const position = declaration.value.replace(/\s*\bin\s+[a-z0-9-]+(?:\s+(?:shorter|longer|increasing|decreasing)\s+hue)?/gi, '').trim();
3647
+ if (position) return position;
3648
+ let gradient = 'linear';
3649
+ declaration.parent?.walkDecls('background-image', ({ value })=>{
3650
+ gradient = /^(radial|conic)-gradient\(/.exec(value)?.[1] ?? gradient;
3651
+ });
3652
+ return ({
3653
+ linear: 'to bottom',
3654
+ radial: 'ellipse',
3655
+ conic: 'from 0deg'
3656
+ })[gradient];
3657
+ };
3658
+ const LOGICAL_PAIRS = {
3659
+ 'padding-inline': [
3660
+ 'padding-left',
3661
+ 'padding-right'
3662
+ ],
3663
+ 'padding-block': [
3664
+ 'padding-top',
3665
+ 'padding-bottom'
3666
+ ],
3667
+ 'margin-inline': [
3668
+ 'margin-left',
3669
+ 'margin-right'
3670
+ ],
3671
+ 'margin-block': [
3672
+ 'margin-top',
3673
+ 'margin-bottom'
3674
+ ],
3675
+ 'inset-inline': [
3676
+ 'left',
3677
+ 'right'
3678
+ ],
3679
+ 'inset-block': [
3680
+ 'top',
3681
+ 'bottom'
3682
+ ],
3683
+ 'border-inline-width': [
3684
+ 'border-left-width',
3685
+ 'border-right-width'
3686
+ ],
3687
+ 'border-block-width': [
3688
+ 'border-top-width',
3689
+ 'border-bottom-width'
3690
+ ],
3691
+ 'border-inline-style': [
3692
+ 'border-left-style',
3693
+ 'border-right-style'
3694
+ ],
3695
+ 'border-block-style': [
3696
+ 'border-top-style',
3697
+ 'border-bottom-style'
3698
+ ],
3699
+ 'border-inline-color': [
3700
+ 'border-left-color',
3701
+ 'border-right-color'
3702
+ ],
3703
+ 'border-block-color': [
3704
+ 'border-top-color',
3705
+ 'border-bottom-color'
3706
+ ]
3707
+ };
3708
+ const LOGICAL_BOTH_SIDES = {
3709
+ 'border-inline': [
3710
+ 'border-left',
3711
+ 'border-right'
3712
+ ],
3713
+ 'border-block': [
3714
+ 'border-top',
3715
+ 'border-bottom'
3716
+ ]
3717
+ };
3718
+ const LOGICAL_LONGHANDS = {
3719
+ 'padding-inline-start': 'padding-left',
3720
+ 'padding-inline-end': 'padding-right',
3721
+ 'padding-block-start': 'padding-top',
3722
+ 'padding-block-end': 'padding-bottom',
3723
+ 'margin-inline-start': 'margin-left',
3724
+ 'margin-inline-end': 'margin-right',
3725
+ 'margin-block-start': 'margin-top',
3726
+ 'margin-block-end': 'margin-bottom',
3727
+ 'inset-inline-start': 'left',
3728
+ 'inset-inline-end': 'right',
3729
+ 'inset-block-start': 'top',
3730
+ 'inset-block-end': 'bottom',
3731
+ 'border-inline-start': 'border-left',
3732
+ 'border-inline-end': 'border-right',
3733
+ 'border-block-start': 'border-top',
3734
+ 'border-block-end': 'border-bottom',
3735
+ 'border-inline-start-width': 'border-left-width',
3736
+ 'border-inline-end-width': 'border-right-width',
3737
+ 'border-block-start-width': 'border-top-width',
3738
+ 'border-block-end-width': 'border-bottom-width',
3739
+ 'border-inline-start-style': 'border-left-style',
3740
+ 'border-inline-end-style': 'border-right-style',
3741
+ 'border-block-start-style': 'border-top-style',
3742
+ 'border-block-end-style': 'border-bottom-style',
3743
+ 'border-inline-start-color': 'border-left-color',
3744
+ 'border-inline-end-color': 'border-right-color',
3745
+ 'border-block-start-color': 'border-top-color',
3746
+ 'border-block-end-color': 'border-bottom-color',
3747
+ 'border-start-start-radius': 'border-top-left-radius',
3748
+ 'border-start-end-radius': 'border-top-right-radius',
3749
+ 'border-end-start-radius': 'border-bottom-left-radius',
3750
+ 'border-end-end-radius': 'border-bottom-right-radius'
3751
+ };
3752
+ const expandLogical = (declaration)=>{
3753
+ const { prop, value, important } = declaration;
3754
+ const longhand = LOGICAL_LONGHANDS[prop];
3755
+ if (longhand) {
3756
+ declaration.prop = longhand;
3757
+ return;
3758
+ }
3759
+ let expanded;
3760
+ const pair = LOGICAL_PAIRS[prop];
3761
+ const bothSides = LOGICAL_BOTH_SIDES[prop];
3762
+ if (pair) {
3763
+ const [start, end = start] = splitSpaces(value);
3764
+ expanded = [
3765
+ [
3766
+ pair[0],
3767
+ start
3768
+ ],
3769
+ [
3770
+ pair[1],
3771
+ end
3772
+ ]
3773
+ ];
3774
+ } else if (bothSides) expanded = [
3775
+ [
3776
+ bothSides[0],
3777
+ value
3778
+ ],
3779
+ [
3780
+ bothSides[1],
3781
+ value
3782
+ ]
3783
+ ];
3784
+ else if ('inset' === prop) {
3785
+ const [top, right = top, bottom = top, left = right] = splitSpaces(value);
3786
+ expanded = [
3787
+ [
3788
+ 'top',
3789
+ top
3790
+ ],
3791
+ [
3792
+ 'right',
3793
+ right
3794
+ ],
3795
+ [
3796
+ 'bottom',
3797
+ bottom
3798
+ ],
3799
+ [
3800
+ 'left',
3801
+ left
3802
+ ]
3803
+ ];
3804
+ }
3805
+ if (!expanded) return;
3806
+ for (const [physical, physicalValue] of expanded)declaration.before({
3807
+ prop: physical,
3808
+ value: physicalValue,
3809
+ important
3810
+ });
3811
+ declaration.remove();
3812
+ };
3813
+ const dropUnsupportedProperties = (rule)=>{
3814
+ rule.each((node)=>{
3815
+ if ('decl' !== node.type || node.prop.startsWith('--')) return;
3816
+ const prop = node.prop.toLowerCase();
3817
+ const keywords = LYNX_KEYWORDS.get(prop);
3818
+ const value = node.value.trim().toLowerCase();
3819
+ if (!LYNX_PROPERTIES.has(prop) || void 0 !== keywords && /^[a-z-]+$/.test(value) && !GLOBAL_KEYWORDS.has(value) && !keywords.has(value)) node.remove();
3820
+ });
3821
+ };
3822
+ const GLOBAL_KEYWORDS = new Set([
3823
+ 'inherit',
3824
+ 'initial',
3825
+ 'unset',
3826
+ 'revert'
3827
+ ]);
3828
+ const lowerSelectors = (rule)=>{
3829
+ const selectors = rule.selectors.filter((selector)=>!/(?<!\\):host\b/.test(selector)).flatMap(unwrapWhereAndIs);
3830
+ if (0 === selectors.length) return false;
3831
+ rule.selectors = selectors.every((selector)=>NOT_LAST_CHILD.test(selector)) && mirrorBetweenChildren(rule) ? selectors.map((selector)=>selector.replace(NOT_LAST_CHILD, ' > * + *')) : selectors;
3832
+ return true;
3833
+ };
3834
+ const unwrapWhereAndIs = (selector)=>{
3835
+ const match = /^:(?:where|is)\(/i.exec(selector);
3836
+ if (!match || closingParenthesis(selector, match[0].length) !== selector.length - 1) return [
3837
+ selector
3838
+ ];
3839
+ return splitTopLevel(selector.slice(match[0].length, -1)).flatMap(unwrapWhereAndIs);
3840
+ };
3841
+ const closingParenthesis = (text, start)=>{
3842
+ let depth = 1;
3843
+ for(let index = start; index < text.length; index++){
3844
+ const character = text[index];
3845
+ if ('\\' === character) index++;
3846
+ else if ('(' === character) depth++;
3847
+ else if (')' === character && 0 === --depth) return index;
3848
+ }
3849
+ return -1;
3850
+ };
3851
+ const splitTopLevel = (list)=>{
3852
+ const parts = [];
3853
+ let depth = 0;
3854
+ let current = '';
3855
+ for(let index = 0; index < list.length; index++){
3856
+ const character = list[index];
3857
+ if ('\\' === character) {
3858
+ current += list.slice(index, index + 2);
3859
+ index++;
3860
+ continue;
3861
+ }
3862
+ if ('(' === character) depth++;
3863
+ else if (')' === character) depth--;
3864
+ else if (',' === character && 0 === depth) {
3865
+ parts.push(current.trim());
3866
+ current = '';
3867
+ continue;
3868
+ }
3869
+ current += character;
3870
+ }
3871
+ parts.push(current.trim());
3872
+ return parts;
3873
+ };
3874
+ const NOT_LAST_CHILD = /\s*>\s*:not\(:last-child\)$/;
3875
+ const OPPOSITE_SIDES = {
3876
+ top: 'bottom',
3877
+ bottom: 'top',
3878
+ left: 'right',
3879
+ right: 'left',
3880
+ 'block-start': 'block-end',
3881
+ 'block-end': 'block-start',
3882
+ 'inline-start': 'inline-end',
3883
+ 'inline-end': 'inline-start'
3884
+ };
3885
+ const mirrorBetweenChildren = (rule)=>{
3886
+ const sidesOnly = rule.nodes.every((node)=>'decl' !== node.type || node.prop.startsWith('--') || /^(margin|padding|border)-/.test(node.prop));
3887
+ if (!sidesOnly) return false;
3888
+ rule.walkDecls((declaration)=>{
3889
+ if (declaration.prop.startsWith('--')) return;
3890
+ declaration.prop = declaration.prop.replace(/\b(top|bottom|left|right|block-start|block-end|inline-start|inline-end)\b/, (side)=>OPPOSITE_SIDES[side]);
3891
+ });
3892
+ return true;
3893
+ };
3894
+ const flattenNesting = (root)=>{
3895
+ root.each((node)=>{
3896
+ flattenNode(node);
3897
+ });
3898
+ };
3899
+ const flattenNode = (node)=>{
3900
+ if ('rule' === node.type) flattenRule(node);
3901
+ else if ('atrule' === node.type && node.nodes) node.each((child)=>{
3902
+ flattenNode(child);
3903
+ });
3904
+ };
3905
+ const flattenRule = (rule)=>{
3906
+ let last = rule;
3907
+ for (const child of rule.nodes.slice())if ('rule' === child.type) {
3908
+ child.selectors = resolveNested(child.selectors, rule.selectors);
3909
+ last.after(child);
3910
+ last = flattenRule(child);
3911
+ } else if ('atrule' === child.type) {
3912
+ wrapDeclarations(child, rule);
3913
+ last.after(child);
3914
+ last = child;
3915
+ flattenNode(child);
3916
+ }
3917
+ return last;
3918
+ };
3919
+ const wrapDeclarations = (atRule, rule)=>{
3920
+ if (!atRule.nodes) return;
3921
+ for (const child of atRule.nodes)if ('rule' === child.type) child.selectors = resolveNested(child.selectors, rule.selectors);
3922
+ else if ('atrule' === child.type) wrapDeclarations(child, rule);
3923
+ const declarations = atRule.nodes.filter((node)=>'decl' === node.type);
3924
+ if (declarations.length > 0) {
3925
+ const wrapper = rule.clone();
3926
+ wrapper.removeAll();
3927
+ wrapper.append(declarations);
3928
+ atRule.prepend(wrapper);
3929
+ }
3930
+ };
3931
+ const resolveNested = (selectors, parents)=>parents.flatMap((parent)=>selectors.map((selector)=>/(?<!\\)&/.test(selector) ? selector.replaceAll(/(?<!\\)&/g, parent) : `${parent} ${selector}`));
3932
+ const unwrapLayers = (container)=>{
3933
+ container.each((node)=>{
3934
+ if ('atrule' !== node.type) return;
3935
+ if ('layer' === node.name.toLowerCase()) if (node.nodes) {
3936
+ unwrapLayers(node);
3937
+ node.replaceWith(node.nodes);
3938
+ } else node.remove();
3939
+ else if (node.nodes) unwrapLayers(node);
3940
+ });
3941
+ };
3942
+ const takePropertyRegistrations = (root)=>{
3943
+ const initialValues = new Map();
3944
+ root.walkAtRules(/^property$/i, (atRule)=>{
3945
+ atRule.walkDecls('initial-value', (declaration)=>{
3946
+ initialValues.set(atRule.params.trim(), declaration.value);
3947
+ });
3948
+ atRule.remove();
3949
+ });
3950
+ root.walkAtRules(/^supports$/i, (atRule)=>{
3951
+ const rules = atRule.nodes?.filter((node)=>'rule' === node.type) ?? [];
3952
+ if (rules.length > 0 && rules.every((rule)=>rule.selector.includes('::backdrop'))) atRule.remove();
3953
+ });
3954
+ return initialValues;
3955
+ };
3956
+ const removeEmptyContainers = (container)=>{
3957
+ container.each((node)=>{
3958
+ if ('rule' !== node.type && 'atrule' !== node.type) return;
3959
+ if (!node.nodes) return;
3960
+ removeEmptyContainers(node);
3961
+ if (node.nodes.every((child)=>'comment' === child.type)) node.remove();
3962
+ });
3963
+ };
3964
+ const IMPLIED_KEYFRAME_VALUES = {
3965
+ transform: 'none',
3966
+ opacity: '1'
3967
+ };
3968
+ const completeKeyframes = (root)=>{
3969
+ root.walkAtRules(/^(?:-webkit-)?keyframes$/i, (atRule)=>{
3970
+ const offsets = new Set();
3971
+ const properties = new Set();
3972
+ atRule.walkRules((rule)=>{
3973
+ for (const selector of rule.selectors)offsets.add({
3974
+ from: '0%',
3975
+ to: '100%'
3976
+ }[selector.toLowerCase()] ?? selector);
3977
+ rule.walkDecls(({ prop })=>{
3978
+ if (prop in IMPLIED_KEYFRAME_VALUES) properties.add(prop);
3979
+ });
3980
+ });
3981
+ const first = atRule.first;
3982
+ if (0 === properties.size || first?.type !== 'rule') return;
3983
+ for (const [offset, selector] of [
3984
+ [
3985
+ '0%',
3986
+ 'from'
3987
+ ],
3988
+ [
3989
+ '100%',
3990
+ 'to'
3991
+ ]
3992
+ ]){
3993
+ if (offsets.has(offset)) continue;
3994
+ const keyframe = first.clone({
3995
+ selector
3996
+ });
3997
+ keyframe.removeAll();
3998
+ for (const prop of properties)keyframe.append({
3999
+ prop,
4000
+ value: IMPLIED_KEYFRAME_VALUES[prop]
4001
+ });
4002
+ if ('from' === selector) atRule.prepend(keyframe);
4003
+ else atRule.append(keyframe);
4004
+ }
4005
+ });
4006
+ };
4007
+ const resolveNestedVariables = (root, registrations)=>{
4008
+ const theme = themeVariables(root);
4009
+ root.walkDecls(/^--/, (declaration)=>{
4010
+ if (!declaration.value.includes('var(')) return;
4011
+ const parsed = postcss_value_parser(declaration.value);
4012
+ const lookup = (name)=>sameRuleValue(declaration, name) ?? theme.get(name) ?? registrations.get(name);
4013
+ if (resolveInFunctions(parsed.nodes, false, lookup, new Set())) declaration.value = foldCalc(parsed.toString());
4014
+ });
4015
+ };
4016
+ const themeVariables = (root)=>{
4017
+ const variables = new Map();
4018
+ root.walkRules((rule)=>{
4019
+ if (rule.selectors.includes(':root')) rule.walkDecls(/^--/, ({ prop, value })=>{
4020
+ variables.set(prop, value);
4021
+ });
4022
+ });
4023
+ return variables;
4024
+ };
4025
+ const sameRuleValue = (declaration, name)=>{
4026
+ let value;
4027
+ declaration.parent.each((node)=>{
4028
+ if ('decl' === node.type && node.prop === name && node !== declaration) value = node.value;
4029
+ });
4030
+ return value;
4031
+ };
4032
+ const resolveInFunctions = (nodes, insideFunction, lookup, seen)=>{
4033
+ let changed = false;
4034
+ for (const node of nodes){
4035
+ if ('function' !== node.type) continue;
4036
+ if ('var' !== node.value.toLowerCase()) {
4037
+ changed = resolveInFunctions(node.nodes, true, lookup, seen) || changed;
4038
+ continue;
4039
+ }
4040
+ const resolved = insideFunction ? resolveVariable(node, lookup, seen) : void 0;
4041
+ if (void 0 === resolved) {
4042
+ changed = resolveInFunctions(node.nodes, insideFunction, lookup, seen) || changed;
4043
+ continue;
4044
+ }
4045
+ Object.assign(node, {
4046
+ type: 'word',
4047
+ value: resolved
4048
+ });
4049
+ changed = true;
4050
+ }
4051
+ return changed;
4052
+ };
4053
+ const resolveVariable = (node, lookup, seen)=>{
4054
+ const name = node.nodes[0]?.value ?? '';
4055
+ if (seen.has(name)) return;
4056
+ const commaIndex = node.nodes.findIndex((child)=>'div' === child.type && ',' === child.value);
4057
+ const fallback = -1 === commaIndex ? void 0 : postcss_value_parser.stringify(node.nodes.slice(commaIndex + 1)).trim();
4058
+ const value = lookup(name) ?? fallback;
4059
+ if (void 0 === value) return;
4060
+ const parsed = postcss_value_parser(value);
4061
+ resolveInFunctions(parsed.nodes, true, lookup, new Set([
4062
+ ...seen,
4063
+ name
4064
+ ]));
4065
+ return parsed.toString();
4066
+ };
4067
+ const TAILWIND_POSTCSS = '@tailwindcss/postcss';
4068
+ const tailwindForLynx = ()=>({
4069
+ postcssPlugin: 'angular-lynx-tailwind',
4070
+ OnceExit (root, { result, rule }) {
4071
+ if (!compiledByTailwind(result)) return;
4072
+ lowerForLynx(root, (selector)=>rule({
4073
+ selector
4074
+ }));
4075
+ }
4076
+ });
4077
+ tailwindForLynx.postcss = true;
4078
+ const compiledByTailwind = (result)=>result.messages.some((message)=>message.plugin === TAILWIND_POSTCSS);
4079
+ const lowerForLynx = (root, createRule)=>{
4080
+ flattenNesting(root);
4081
+ unwrapLayers(root);
4082
+ const registrations = takePropertyRegistrations(root);
4083
+ const defaults = new Map(registrations);
4084
+ const channelVariables = colorChannelVariables(root);
4085
+ root.walkRules((rule)=>{
4086
+ const inKeyframes = rule.parent?.type === 'atrule' && /keyframes$/i.test(rule.parent.name);
4087
+ if (!inKeyframes && !lowerSelectors(rule)) return void rule.remove();
4088
+ if (lowerDeclarations(rule, channelVariables).composesTransform) {
4089
+ for (const [name, value] of TRANSFORM_DEFAULTS)if (!defaults.has(name)) defaults.set(name, value);
4090
+ }
4091
+ });
4092
+ unwrapLoweredColorMixSupports(root);
4093
+ resolveNestedVariables(root, registrations);
4094
+ lowerTransformVariables(root);
4095
+ completeKeyframes(root);
4096
+ removeEmptyContainers(root);
4097
+ if (defaults.size > 0) {
4098
+ const defaultsRule = createRule('*');
4099
+ for (const [prop, value] of defaults)defaultsRule.append({
4100
+ prop,
4101
+ value
4102
+ });
4103
+ const imports = root.nodes.filter((node)=>'atrule' === node.type && /^(charset|import)$/i.test(node.name));
4104
+ if (imports.length > 0) imports[imports.length - 1].after(defaultsRule);
4105
+ else root.prepend(defaultsRule);
4106
+ }
4107
+ };
4108
+ const colorChannelVariables = (root)=>{
4109
+ const names = new Set();
4110
+ root.walkDecls(/^--.+-rgb$/, ({ prop })=>{
4111
+ names.add(prop.slice(0, -4));
4112
+ });
4113
+ return names;
4114
+ };
4115
+ const unwrapLoweredColorMixSupports = (root)=>{
4116
+ root.walkAtRules(/^supports$/i, (atRule)=>{
4117
+ if (!atRule.params.includes('color-mix(') || !atRule.nodes) return;
4118
+ let mixes = false;
4119
+ atRule.walkDecls((declaration)=>{
4120
+ mixes ||= declaration.value.includes('color-mix(');
4121
+ });
4122
+ if (!mixes) atRule.replaceWith(atRule.nodes);
4123
+ });
4124
+ };
2290
4125
  const TAILWIND_CONFIG_FILES = [
2291
4126
  'tailwind.config.ts',
2292
4127
  'tailwind.config.js',
@@ -2294,17 +4129,28 @@ const TAILWIND_CONFIG_FILES = [
2294
4129
  'tailwind.config.cjs'
2295
4130
  ];
2296
4131
  const isTailwind = (plugin)=>'function' == typeof plugin ? 'tailwindcss' === plugin.name : plugin?.postcssPlugin === 'tailwindcss';
4132
+ const isTailwind4 = (plugin)=>plugin?.postcssPlugin === '@tailwindcss/postcss';
2297
4133
  const applyTailwind = (api)=>{
2298
4134
  const configFile = findUp(TAILWIND_CONFIG_FILES, process.cwd());
2299
- if (!configFile) return;
4135
+ let warned = false;
2300
4136
  api.modifyRsbuildConfig((config, { mergeRsbuildConfig })=>mergeRsbuildConfig(config, {
2301
4137
  tools: {
2302
4138
  postcss: ({ postcssOptions }, { addPlugins })=>{
2303
- if ('object' == typeof postcssOptions && postcssOptions.plugins?.some(isTailwind)) return;
2304
- const tailwindcss = createRequire(configFile)('tailwindcss');
2305
- addPlugins(tailwindcss({
2306
- config: configFile
2307
- }));
4139
+ const configured = 'object' == typeof postcssOptions ? postcssOptions.plugins ?? [] : [];
4140
+ if (configFile && !configured.some(isTailwind)) {
4141
+ const require = createRequire(configFile);
4142
+ const { version } = require('tailwindcss/package.json');
4143
+ if (Number.parseInt(version, 10) < 4) {
4144
+ const tailwindcss = require('tailwindcss');
4145
+ addPlugins(tailwindcss({
4146
+ config: configFile
4147
+ }));
4148
+ } else if (!configured.some(isTailwind4) && !warned) {
4149
+ warned = true;
4150
+ api.logger.warn(`Found ${configFile}, but Tailwind CSS ${version} is installed, which doesn't run from a Tailwind config file. List @tailwindcss/postcss in a .postcssrc.json, or run \`ng generate @blotch/angular-lynx:add-tailwind\`.`);
4151
+ }
4152
+ }
4153
+ addPlugins(tailwindForLynx());
2308
4154
  }
2309
4155
  }
2310
4156
  }));