@fragments-sdk/cli 0.15.10 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/bin.js +901 -789
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{chunk-6SQPP47U.js → chunk-ANTWP3UG.js} +532 -31
  4. package/dist/chunk-ANTWP3UG.js.map +1 -0
  5. package/dist/{chunk-ONUP6Z4W.js → chunk-B4A4ZEGS.js} +9 -9
  6. package/dist/{chunk-32LIWN2P.js → chunk-FFCI6OVZ.js} +584 -261
  7. package/dist/chunk-FFCI6OVZ.js.map +1 -0
  8. package/dist/{chunk-HQ6A6DTV.js → chunk-HNHE64CR.js} +315 -1089
  9. package/dist/chunk-HNHE64CR.js.map +1 -0
  10. package/dist/{chunk-BJE3425I.js → chunk-MN3B2EE6.js} +2 -2
  11. package/dist/{chunk-QCN35LJU.js → chunk-SAQW37L5.js} +3 -2
  12. package/dist/chunk-SAQW37L5.js.map +1 -0
  13. package/dist/{chunk-2WXKALIG.js → chunk-SNZXGHL2.js} +2 -2
  14. package/dist/{chunk-5JF26E55.js → chunk-VT2J62ND.js} +11 -11
  15. package/dist/{codebase-scanner-MQHUZC2G.js → codebase-scanner-2T5QIDBA.js} +2 -2
  16. package/dist/core/index.js +53 -1
  17. package/dist/{create-EXURTBKK.js → create-D44QD7MV.js} +2 -2
  18. package/dist/{doctor-BDPMYYE6.js → doctor-7B5N4JYU.js} +2 -2
  19. package/dist/{generate-PVOLUAAC.js → generate-T47JZRVU.js} +4 -4
  20. package/dist/govern-scan-X6UEIOSV.js +632 -0
  21. package/dist/govern-scan-X6UEIOSV.js.map +1 -0
  22. package/dist/index.js +7 -8
  23. package/dist/index.js.map +1 -1
  24. package/dist/{init-SSGUSP7Z.js → init-2RGAY4W6.js} +5 -5
  25. package/dist/mcp-bin.js +2 -2
  26. package/dist/scan-A2WJM54L.js +14 -0
  27. package/dist/{scan-generate-VY27PIOX.js → scan-generate-LUSOHT36.js} +4 -4
  28. package/dist/{service-QJGWUIVL.js → service-ROCP7TKG.js} +13 -15
  29. package/dist/{snapshot-WIJMEIFT.js → snapshot-B3SAW74Y.js} +2 -2
  30. package/dist/{static-viewer-7QIBQZRC.js → static-viewer-7L6UEYTJ.js} +3 -3
  31. package/dist/{test-64Z5BKBA.js → test-PQDVDURE.js} +3 -3
  32. package/dist/{token-normalizer-TEPOVBPV.js → token-normalizer-7TFCVDZL.js} +2 -2
  33. package/dist/{tokens-NZWFQIAB.js → tokens-64FG5FDP.js} +8 -9
  34. package/dist/{tokens-NZWFQIAB.js.map → tokens-64FG5FDP.js.map} +1 -1
  35. package/dist/{tokens-generate-5JQSJ27E.js → tokens-generate-CL4LBBQA.js} +2 -2
  36. package/package.json +9 -8
  37. package/src/bin.ts +55 -88
  38. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +1 -1
  39. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +1 -1
  40. package/src/commands/__tests__/context-cloud.test.ts +291 -0
  41. package/src/commands/__tests__/govern-scan.test.ts +185 -0
  42. package/src/commands/__tests__/govern.test.ts +1 -0
  43. package/src/commands/context-cloud.ts +355 -0
  44. package/src/commands/govern-scan-report.ts +170 -0
  45. package/src/commands/govern-scan.ts +282 -135
  46. package/src/commands/govern.ts +0 -157
  47. package/src/mcp/__tests__/server.integration.test.ts +9 -20
  48. package/src/service/enhance/codebase-scanner.ts +3 -2
  49. package/src/service/enhance/types.ts +3 -0
  50. package/dist/chunk-32LIWN2P.js.map +0 -1
  51. package/dist/chunk-6SQPP47U.js.map +0 -1
  52. package/dist/chunk-HQ6A6DTV.js.map +0 -1
  53. package/dist/chunk-MHIBEEW4.js +0 -511
  54. package/dist/chunk-MHIBEEW4.js.map +0 -1
  55. package/dist/chunk-QCN35LJU.js.map +0 -1
  56. package/dist/govern-scan-DW4QUAYD.js +0 -414
  57. package/dist/govern-scan-DW4QUAYD.js.map +0 -1
  58. package/dist/init-cloud-3DNKPWFB.js +0 -304
  59. package/dist/init-cloud-3DNKPWFB.js.map +0 -1
  60. package/dist/node-37AUE74M.js +0 -65
  61. package/dist/push-contracts-WY32TFP6.js +0 -84
  62. package/dist/push-contracts-WY32TFP6.js.map +0 -1
  63. package/dist/scan-PKSYSTRR.js +0 -15
  64. package/dist/static-viewer-7QIBQZRC.js.map +0 -1
  65. package/dist/token-parser-32KOIOFN.js +0 -22
  66. package/dist/token-parser-32KOIOFN.js.map +0 -1
  67. package/dist/tokens-push-HY3KO36V.js +0 -148
  68. package/dist/tokens-push-HY3KO36V.js.map +0 -1
  69. package/src/commands/init-cloud.ts +0 -382
  70. package/src/commands/push-contracts.ts +0 -112
  71. package/src/commands/tokens-push.ts +0 -199
  72. /package/dist/{chunk-ONUP6Z4W.js.map → chunk-B4A4ZEGS.js.map} +0 -0
  73. /package/dist/{chunk-BJE3425I.js.map → chunk-MN3B2EE6.js.map} +0 -0
  74. /package/dist/{chunk-2WXKALIG.js.map → chunk-SNZXGHL2.js.map} +0 -0
  75. /package/dist/{chunk-5JF26E55.js.map → chunk-VT2J62ND.js.map} +0 -0
  76. /package/dist/{codebase-scanner-MQHUZC2G.js.map → codebase-scanner-2T5QIDBA.js.map} +0 -0
  77. /package/dist/{create-EXURTBKK.js.map → create-D44QD7MV.js.map} +0 -0
  78. /package/dist/{doctor-BDPMYYE6.js.map → doctor-7B5N4JYU.js.map} +0 -0
  79. /package/dist/{generate-PVOLUAAC.js.map → generate-T47JZRVU.js.map} +0 -0
  80. /package/dist/{init-SSGUSP7Z.js.map → init-2RGAY4W6.js.map} +0 -0
  81. /package/dist/{node-37AUE74M.js.map → scan-A2WJM54L.js.map} +0 -0
  82. /package/dist/{scan-generate-VY27PIOX.js.map → scan-generate-LUSOHT36.js.map} +0 -0
  83. /package/dist/{scan-PKSYSTRR.js.map → service-ROCP7TKG.js.map} +0 -0
  84. /package/dist/{snapshot-WIJMEIFT.js.map → snapshot-B3SAW74Y.js.map} +0 -0
  85. /package/dist/{service-QJGWUIVL.js.map → static-viewer-7L6UEYTJ.js.map} +0 -0
  86. /package/dist/{test-64Z5BKBA.js.map → test-PQDVDURE.js.map} +0 -0
  87. /package/dist/{token-normalizer-TEPOVBPV.js.map → token-normalizer-7TFCVDZL.js.map} +0 -0
  88. /package/dist/{tokens-generate-5JQSJ27E.js.map → tokens-generate-CL4LBBQA.js.map} +0 -0
@@ -2,12 +2,7 @@ import { createRequire as __banner_createRequire } from 'module'; const require
2
2
  import {
3
3
  BRAND,
4
4
  DEFAULTS
5
- } from "./chunk-32LIWN2P.js";
6
- import {
7
- hexToRgb,
8
- parseRgb,
9
- parseTokenFiles
10
- } from "./chunk-MHIBEEW4.js";
5
+ } from "./chunk-FFCI6OVZ.js";
11
6
  import {
12
7
  BABEL_PARSER_OPTIONS
13
8
  } from "./chunk-7DZC4YEV.js";
@@ -80,8 +75,8 @@ var BrowserPool = class {
80
75
  }
81
76
  await this.clearContext(context);
82
77
  if (this.waitingQueue.length > 0) {
83
- const resolve3 = this.waitingQueue.shift();
84
- resolve3(context);
78
+ const resolve4 = this.waitingQueue.shift();
79
+ resolve4(context);
85
80
  return;
86
81
  }
87
82
  this.available.push(context);
@@ -108,7 +103,7 @@ var BrowserPool = class {
108
103
  clearTimeout(this.idleTimeout);
109
104
  this.idleTimeout = null;
110
105
  }
111
- for (const resolve3 of this.waitingQueue) {
106
+ for (const resolve4 of this.waitingQueue) {
112
107
  }
113
108
  this.waitingQueue = [];
114
109
  for (const context of this.contexts) {
@@ -195,9 +190,9 @@ var BrowserPool = class {
195
190
  * Wait for an available context.
196
191
  */
197
192
  waitForAvailable() {
198
- return new Promise((resolve3, reject) => {
193
+ return new Promise((resolve4, reject) => {
199
194
  const timeout = setTimeout(() => {
200
- const index = this.waitingQueue.indexOf(resolve3);
195
+ const index = this.waitingQueue.indexOf(resolve4);
201
196
  if (index > -1) {
202
197
  this.waitingQueue.splice(index, 1);
203
198
  }
@@ -210,7 +205,7 @@ var BrowserPool = class {
210
205
  }, 3e4);
211
206
  const wrappedResolve = (ctx) => {
212
207
  clearTimeout(timeout);
213
- resolve3(ctx);
208
+ resolve4(ctx);
214
209
  };
215
210
  this.waitingQueue.push(wrappedResolve);
216
211
  });
@@ -293,16 +288,16 @@ var Timer = class {
293
288
  }
294
289
  };
295
290
  function createDeferred() {
296
- let resolve3;
291
+ let resolve4;
297
292
  let reject;
298
293
  const promise = new Promise((res, rej) => {
299
- resolve3 = res;
294
+ resolve4 = res;
300
295
  reject = rej;
301
296
  });
302
- return { promise, resolve: resolve3, reject };
297
+ return { promise, resolve: resolve4, reject };
303
298
  }
304
299
  function sleep(ms) {
305
- return new Promise((resolve3) => setTimeout(resolve3, ms));
300
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
306
301
  }
307
302
  function bufferToBase64Url(buffer, mimeType = "image/png") {
308
303
  return `data:${mimeType};base64,${buffer.toString("base64")}`;
@@ -458,7 +453,7 @@ var CaptureEngine = class {
458
453
  await page.evaluate(async (timeoutMs) => {
459
454
  await Promise.race([
460
455
  document.fonts.ready,
461
- new Promise((resolve3) => setTimeout(resolve3, timeoutMs))
456
+ new Promise((resolve4) => setTimeout(resolve4, timeoutMs))
462
457
  ]);
463
458
  }, timeout);
464
459
  } catch {
@@ -2556,6 +2551,503 @@ function getScripts() {
2556
2551
  `;
2557
2552
  }
2558
2553
 
2554
+ // src/service/token-parser.ts
2555
+ import { readFile as readFile2 } from "fs/promises";
2556
+ import { readFileSync } from "fs";
2557
+ import { relative } from "path";
2558
+ import fastGlob from "fast-glob";
2559
+
2560
+ // src/service/tailwind-v4-parser.ts
2561
+ var CATEGORY_PATTERNS = [
2562
+ { pattern: /color|bg|background|border-color|fill|stroke/i, category: "color" },
2563
+ { pattern: /spacing|margin|padding|gap|space|inset/i, category: "spacing" },
2564
+ { pattern: /font|text|line-height|letter-spacing|typography/i, category: "typography" },
2565
+ { pattern: /radius|rounded|corner/i, category: "radius" },
2566
+ { pattern: /shadow|elevation/i, category: "shadow" },
2567
+ { pattern: /size|width|height|min|max/i, category: "sizing" },
2568
+ { pattern: /border(?!-color)|stroke-width|outline/i, category: "border" },
2569
+ { pattern: /animation|transition|duration|timing|delay/i, category: "animation" },
2570
+ { pattern: /z-index|layer|stack/i, category: "z-index" }
2571
+ ];
2572
+ function inferCategory(name) {
2573
+ const lowerName = name.toLowerCase();
2574
+ for (const { pattern, category } of CATEGORY_PATTERNS) {
2575
+ if (pattern.test(lowerName)) {
2576
+ return category;
2577
+ }
2578
+ }
2579
+ return "other";
2580
+ }
2581
+ function inferLevel(rawValue) {
2582
+ if (/var\(/.test(rawValue)) {
2583
+ return 2;
2584
+ }
2585
+ return 1;
2586
+ }
2587
+ function stripBlockComments(css) {
2588
+ return css.replace(/\/\*[\s\S]*?\*\//g, "");
2589
+ }
2590
+ var CUSTOM_PROPERTY_PATTERN = /^\s*(--[\w-]+)\s*:\s*(.+?)\s*;?\s*$/;
2591
+ function parseTailwindV4Theme(cssContent, filePath) {
2592
+ const startTime = performance.now();
2593
+ const tokens = [];
2594
+ const errors = [];
2595
+ const warnings = [];
2596
+ const source = filePath ?? "unknown";
2597
+ const cleaned = stripBlockComments(cssContent);
2598
+ const lines = cleaned.split("\n");
2599
+ let insideTheme = false;
2600
+ let themeDepth = 0;
2601
+ let pendingTheme = false;
2602
+ for (let i = 0; i < lines.length; i++) {
2603
+ let line = lines[i];
2604
+ const lineNumber = i + 1;
2605
+ const singleCommentIdx = line.indexOf("//");
2606
+ if (singleCommentIdx !== -1) {
2607
+ const beforeComment = line.slice(0, singleCommentIdx);
2608
+ const singleQuotes = (beforeComment.match(/'/g) || []).length;
2609
+ const doubleQuotes = (beforeComment.match(/"/g) || []).length;
2610
+ if (singleQuotes % 2 === 0 && doubleQuotes % 2 === 0) {
2611
+ line = beforeComment;
2612
+ }
2613
+ }
2614
+ const trimmed = line.trim();
2615
+ if (trimmed === "") {
2616
+ continue;
2617
+ }
2618
+ if (!insideTheme && !pendingTheme) {
2619
+ if (/^@theme\b/.test(trimmed)) {
2620
+ pendingTheme = true;
2621
+ const braceIdx = trimmed.indexOf("{");
2622
+ if (braceIdx !== -1) {
2623
+ pendingTheme = false;
2624
+ insideTheme = true;
2625
+ themeDepth = 1;
2626
+ const afterBrace = trimmed.slice(braceIdx + 1);
2627
+ for (const ch of afterBrace) {
2628
+ if (ch === "{") themeDepth++;
2629
+ else if (ch === "}") themeDepth--;
2630
+ }
2631
+ const inlineContent = afterBrace.trim();
2632
+ if (inlineContent && themeDepth > 0) {
2633
+ processThemeLine(inlineContent, lineNumber, source, tokens, warnings);
2634
+ }
2635
+ if (themeDepth <= 0) {
2636
+ insideTheme = false;
2637
+ }
2638
+ }
2639
+ continue;
2640
+ }
2641
+ }
2642
+ if (pendingTheme) {
2643
+ const braceIdx = trimmed.indexOf("{");
2644
+ if (braceIdx !== -1) {
2645
+ pendingTheme = false;
2646
+ insideTheme = true;
2647
+ themeDepth = 1;
2648
+ const afterBrace = trimmed.slice(braceIdx + 1);
2649
+ for (const ch of afterBrace) {
2650
+ if (ch === "{") themeDepth++;
2651
+ else if (ch === "}") themeDepth--;
2652
+ }
2653
+ const inlineContent = afterBrace.trim();
2654
+ if (inlineContent && themeDepth > 0) {
2655
+ processThemeLine(inlineContent, lineNumber, source, tokens, warnings);
2656
+ }
2657
+ if (themeDepth <= 0) {
2658
+ insideTheme = false;
2659
+ }
2660
+ }
2661
+ continue;
2662
+ }
2663
+ if (insideTheme) {
2664
+ for (const ch of trimmed) {
2665
+ if (ch === "{") {
2666
+ themeDepth++;
2667
+ } else if (ch === "}") {
2668
+ themeDepth--;
2669
+ if (themeDepth <= 0) {
2670
+ insideTheme = false;
2671
+ break;
2672
+ }
2673
+ }
2674
+ }
2675
+ if (insideTheme || themeDepth > 0) {
2676
+ const contentLine = trimmed.replace(/\}/g, "").trim();
2677
+ if (contentLine) {
2678
+ processThemeLine(contentLine, lineNumber, source, tokens, warnings);
2679
+ }
2680
+ }
2681
+ }
2682
+ }
2683
+ if (pendingTheme) {
2684
+ warnings.push(
2685
+ `@theme keyword found but no opening brace \u2014 incomplete block in ${source}`
2686
+ );
2687
+ }
2688
+ if (insideTheme) {
2689
+ warnings.push(
2690
+ `Unclosed @theme block \u2014 missing closing brace in ${source}`
2691
+ );
2692
+ }
2693
+ return {
2694
+ tokens,
2695
+ errors,
2696
+ warnings,
2697
+ parseTimeMs: performance.now() - startTime
2698
+ };
2699
+ }
2700
+ function processThemeLine(line, lineNumber, source, tokens, warnings) {
2701
+ const match = line.match(CUSTOM_PROPERTY_PATTERN);
2702
+ if (!match) {
2703
+ const partialMatch = line.match(/^\s*(--[\w-]+)\s*:\s*(.+?)\s*$/);
2704
+ if (partialMatch) {
2705
+ const [, name2, rawValue2] = partialMatch;
2706
+ tokens.push(buildToken(name2, rawValue2, lineNumber, source));
2707
+ return;
2708
+ }
2709
+ if (/^\s*--/.test(line)) {
2710
+ warnings.push(
2711
+ `Line ${lineNumber}: Could not parse custom property declaration: ${line.trim()}`
2712
+ );
2713
+ }
2714
+ return;
2715
+ }
2716
+ const [, name, rawValue] = match;
2717
+ tokens.push(buildToken(name, rawValue, lineNumber, source));
2718
+ }
2719
+ function buildToken(name, rawValue, lineNumber, source) {
2720
+ const value = rawValue.trim();
2721
+ return {
2722
+ name,
2723
+ rawValue: value,
2724
+ resolvedValue: value,
2725
+ category: inferCategory(name),
2726
+ level: inferLevel(value),
2727
+ referenceChain: [],
2728
+ sourceFile: source,
2729
+ lineNumber,
2730
+ theme: "default",
2731
+ selector: "@theme"
2732
+ };
2733
+ }
2734
+
2735
+ // src/service/token-parser.ts
2736
+ var TOKEN_DECLARATION_PATTERN = /--([a-zA-Z0-9_-]+)\s*:\s*([^;]+);/g;
2737
+ var CATEGORY_PATTERNS2 = [
2738
+ { pattern: /color|bg|background|border-color|fill|stroke/i, category: "color" },
2739
+ { pattern: /spacing|margin|padding|gap|space|inset/i, category: "spacing" },
2740
+ { pattern: /font|text|line-height|letter-spacing|typography/i, category: "typography" },
2741
+ { pattern: /radius|rounded|corner/i, category: "radius" },
2742
+ { pattern: /shadow|elevation/i, category: "shadow" },
2743
+ { pattern: /size|width|height|min|max/i, category: "sizing" },
2744
+ { pattern: /border(?!-color)|stroke-width|outline/i, category: "border" },
2745
+ { pattern: /animation|transition|duration|timing|delay/i, category: "animation" },
2746
+ { pattern: /z-index|layer|stack/i, category: "z-index" }
2747
+ ];
2748
+ async function parseTokenFile(filePath, themeSelectors = { ":root": "default" }, projectRoot) {
2749
+ const startTime = performance.now();
2750
+ const tokens = [];
2751
+ const errors = [];
2752
+ const warnings = [];
2753
+ try {
2754
+ const content = await readFile2(filePath, "utf-8");
2755
+ const relativePath = projectRoot ? relative(projectRoot, filePath) : filePath;
2756
+ if (containsTailwindV4Theme(content)) {
2757
+ const v4Result = parseTailwindV4Theme(content, relativePath);
2758
+ tokens.push(...v4Result.tokens);
2759
+ warnings.push(...v4Result.warnings);
2760
+ for (const err of v4Result.errors) {
2761
+ errors.push({ message: err, file: filePath });
2762
+ }
2763
+ }
2764
+ const tokensByName = /* @__PURE__ */ new Map();
2765
+ let lineNumber = 1;
2766
+ const lines = content.split("\n");
2767
+ let currentSelector = ":root";
2768
+ let braceDepth = 0;
2769
+ const selectorStack = [];
2770
+ for (let i = 0; i < lines.length; i++) {
2771
+ const line = lines[i];
2772
+ lineNumber = i + 1;
2773
+ const openBraces = (line.match(/\{/g) || []).length;
2774
+ const closeBraces = (line.match(/\}/g) || []).length;
2775
+ if (openBraces > closeBraces) {
2776
+ const selectorMatch = line.match(/^\s*([^{]+)\s*\{/);
2777
+ if (selectorMatch) {
2778
+ selectorStack.push(selectorMatch[1].trim());
2779
+ currentSelector = selectorStack[selectorStack.length - 1];
2780
+ }
2781
+ braceDepth += openBraces - closeBraces;
2782
+ } else if (closeBraces > openBraces) {
2783
+ braceDepth -= closeBraces - openBraces;
2784
+ if (braceDepth >= 0 && selectorStack.length > 0) {
2785
+ selectorStack.pop();
2786
+ currentSelector = selectorStack.length > 0 ? selectorStack[selectorStack.length - 1] : ":root";
2787
+ }
2788
+ }
2789
+ const tokenMatches = [...line.matchAll(TOKEN_DECLARATION_PATTERN)];
2790
+ for (const match of tokenMatches) {
2791
+ const [, name, rawValue] = match;
2792
+ const fullName = `--${name}`;
2793
+ tokensByName.set(fullName, { rawValue: rawValue.trim(), line: lineNumber });
2794
+ }
2795
+ }
2796
+ for (const [name, { rawValue, line }] of tokensByName) {
2797
+ const selector = findSelectorForLine(content, line || 1);
2798
+ const theme = themeSelectors[selector] || "default";
2799
+ const { resolvedValue, chain, hasCircular, unresolvedRef } = resolveValue(
2800
+ rawValue,
2801
+ tokensByName
2802
+ );
2803
+ if (hasCircular) {
2804
+ warnings.push(
2805
+ `Circular reference detected for ${name} at line ${line}`
2806
+ );
2807
+ }
2808
+ if (unresolvedRef) {
2809
+ warnings.push(
2810
+ `Unresolved reference in ${name}: ${unresolvedRef}`
2811
+ );
2812
+ }
2813
+ const category = inferCategory2(name);
2814
+ const level = inferLevel2(name, rawValue, chain);
2815
+ const description = extractDescription(content, line || 1);
2816
+ tokens.push({
2817
+ name,
2818
+ rawValue,
2819
+ resolvedValue,
2820
+ category,
2821
+ level,
2822
+ referenceChain: chain,
2823
+ sourceFile: relativePath,
2824
+ lineNumber: line,
2825
+ theme,
2826
+ selector,
2827
+ description
2828
+ });
2829
+ }
2830
+ } catch (error) {
2831
+ errors.push({
2832
+ message: error instanceof Error ? error.message : "Unknown error",
2833
+ file: filePath
2834
+ });
2835
+ }
2836
+ return {
2837
+ tokens,
2838
+ errors,
2839
+ warnings,
2840
+ parseTimeMs: performance.now() - startTime
2841
+ };
2842
+ }
2843
+ async function parseTokenFiles(config, projectRoot) {
2844
+ const startTime = performance.now();
2845
+ const allTokens = [];
2846
+ const allErrors = [];
2847
+ const allWarnings = [];
2848
+ const files = await fastGlob(config.include, {
2849
+ cwd: projectRoot,
2850
+ ignore: config.exclude || ["**/node_modules/**"],
2851
+ absolute: true
2852
+ });
2853
+ if (files.length === 0) {
2854
+ allWarnings.push(
2855
+ `No token files found matching: ${config.include.join(", ")}`
2856
+ );
2857
+ }
2858
+ for (const file of files) {
2859
+ const result = await parseTokenFile(
2860
+ file,
2861
+ config.themeSelectors,
2862
+ projectRoot
2863
+ );
2864
+ allTokens.push(...result.tokens);
2865
+ allErrors.push(...result.errors);
2866
+ allWarnings.push(...result.warnings);
2867
+ }
2868
+ return {
2869
+ tokens: allTokens,
2870
+ errors: allErrors,
2871
+ warnings: allWarnings,
2872
+ parseTimeMs: performance.now() - startTime
2873
+ };
2874
+ }
2875
+ function resolveValue(rawValue, tokensByName, visited = /* @__PURE__ */ new Set()) {
2876
+ const chain = [];
2877
+ let current = rawValue;
2878
+ let hasCircular = false;
2879
+ let unresolvedRef;
2880
+ const maxIterations = 20;
2881
+ let iterations = 0;
2882
+ while (iterations < maxIterations) {
2883
+ iterations++;
2884
+ const varMatch = current.match(/var\(\s*--([a-zA-Z0-9_-]+)(?:\s*,\s*([^)]+))?\s*\)/);
2885
+ if (!varMatch) {
2886
+ break;
2887
+ }
2888
+ const [, refName, fallback] = varMatch;
2889
+ const fullRefName = `--${refName}`;
2890
+ if (visited.has(fullRefName)) {
2891
+ hasCircular = true;
2892
+ break;
2893
+ }
2894
+ visited.add(fullRefName);
2895
+ chain.push(fullRefName);
2896
+ const refToken = tokensByName.get(fullRefName);
2897
+ if (refToken) {
2898
+ current = current.replace(
2899
+ varMatch[0],
2900
+ refToken.rawValue
2901
+ );
2902
+ } else if (fallback) {
2903
+ current = current.replace(varMatch[0], fallback.trim());
2904
+ } else {
2905
+ unresolvedRef = fullRefName;
2906
+ break;
2907
+ }
2908
+ }
2909
+ return {
2910
+ resolvedValue: normalizeValue(current.trim()),
2911
+ chain,
2912
+ hasCircular,
2913
+ unresolvedRef
2914
+ };
2915
+ }
2916
+ function normalizeValue(value) {
2917
+ value = value.replace(/#[0-9a-fA-F]+/g, (match) => match.toLowerCase());
2918
+ value = value.replace(/\s+/g, " ").trim();
2919
+ value = value.replace(
2920
+ /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)/g,
2921
+ (_, r, g, b, a) => a !== void 0 ? `rgba(${r}, ${g}, ${b}, ${a})` : `rgb(${r}, ${g}, ${b})`
2922
+ );
2923
+ return value;
2924
+ }
2925
+ function inferCategory2(name) {
2926
+ const lowerName = name.toLowerCase();
2927
+ for (const { pattern, category } of CATEGORY_PATTERNS2) {
2928
+ if (pattern.test(lowerName)) {
2929
+ return category;
2930
+ }
2931
+ }
2932
+ return "other";
2933
+ }
2934
+ function inferLevel2(name, rawValue, referenceChain) {
2935
+ const lowerName = name.toLowerCase();
2936
+ if (/btn|button|input|card|modal|dialog|menu|nav|header|footer|table|form/i.test(
2937
+ lowerName
2938
+ )) {
2939
+ return 3;
2940
+ }
2941
+ if (referenceChain.length > 0) {
2942
+ return 2;
2943
+ }
2944
+ if (rawValue.match(/^#[0-9a-fA-F]+$/) || rawValue.match(/^\d+(\.\d+)?(px|rem|em|%|vh|vw)?$/)) {
2945
+ return 1;
2946
+ }
2947
+ return 2;
2948
+ }
2949
+ function findSelectorForLine(content, targetLine) {
2950
+ const lines = content.split("\n");
2951
+ let currentSelector = ":root";
2952
+ let braceDepth = 0;
2953
+ for (let i = 0; i < Math.min(targetLine, lines.length); i++) {
2954
+ const line = lines[i];
2955
+ const selectorMatch = line.match(/^\s*([^{]+)\s*\{/);
2956
+ if (selectorMatch) {
2957
+ const selector = selectorMatch[1].trim();
2958
+ if ((line.match(/\{/g) || []).length > (line.match(/\}/g) || []).length) {
2959
+ currentSelector = selector;
2960
+ }
2961
+ }
2962
+ braceDepth += (line.match(/\{/g) || []).length;
2963
+ braceDepth -= (line.match(/\}/g) || []).length;
2964
+ if (braceDepth === 0) {
2965
+ currentSelector = ":root";
2966
+ }
2967
+ }
2968
+ return currentSelector;
2969
+ }
2970
+ function extractDescription(content, line) {
2971
+ const lines = content.split("\n");
2972
+ if (line <= 1) return void 0;
2973
+ const prevLine = lines[line - 2]?.trim();
2974
+ const singleLineMatch = prevLine?.match(/\/\/\s*(.+)$/);
2975
+ if (singleLineMatch) {
2976
+ return singleLineMatch[1].trim();
2977
+ }
2978
+ const multiLineMatch = prevLine?.match(/\*\s*(.+)\s*\*\//);
2979
+ if (multiLineMatch) {
2980
+ return multiLineMatch[1].trim();
2981
+ }
2982
+ const inlineMatch = prevLine?.match(/\/\*\s*(.+)\s*\*\//);
2983
+ if (inlineMatch) {
2984
+ return inlineMatch[1].trim();
2985
+ }
2986
+ return void 0;
2987
+ }
2988
+ function hexToRgb(hex) {
2989
+ const match = hex.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);
2990
+ if (!match) return null;
2991
+ return {
2992
+ r: parseInt(match[1], 16),
2993
+ g: parseInt(match[2], 16),
2994
+ b: parseInt(match[3], 16)
2995
+ };
2996
+ }
2997
+ function rgbToHex(r, g, b) {
2998
+ return `#${[r, g, b].map((x) => Math.round(x).toString(16).padStart(2, "0")).join("")}`;
2999
+ }
3000
+ function parseRgb(color) {
3001
+ const match = color.match(
3002
+ /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)/
3003
+ );
3004
+ if (!match) return null;
3005
+ return {
3006
+ r: parseInt(match[1], 10),
3007
+ g: parseInt(match[2], 10),
3008
+ b: parseInt(match[3], 10),
3009
+ a: match[4] ? parseFloat(match[4]) : void 0
3010
+ };
3011
+ }
3012
+ function normalizeColor(color) {
3013
+ if (color.startsWith("#")) {
3014
+ return color.toLowerCase();
3015
+ }
3016
+ const rgb = parseRgb(color);
3017
+ if (rgb) {
3018
+ return rgbToHex(rgb.r, rgb.g, rgb.b);
3019
+ }
3020
+ return color.toLowerCase();
3021
+ }
3022
+ function parseTailwindV4File(filePath) {
3023
+ const startTime = performance.now();
3024
+ try {
3025
+ const content = readFileSync(filePath, "utf-8");
3026
+ const result = parseTailwindV4Theme(content, filePath);
3027
+ return {
3028
+ tokens: result.tokens,
3029
+ errors: result.errors.map((message) => ({ message, file: filePath })),
3030
+ warnings: result.warnings,
3031
+ parseTimeMs: result.parseTimeMs
3032
+ };
3033
+ } catch (error) {
3034
+ return {
3035
+ tokens: [],
3036
+ errors: [
3037
+ {
3038
+ message: error instanceof Error ? error.message : "Unknown error",
3039
+ file: filePath
3040
+ }
3041
+ ],
3042
+ warnings: [],
3043
+ parseTimeMs: performance.now() - startTime
3044
+ };
3045
+ }
3046
+ }
3047
+ function containsTailwindV4Theme(content) {
3048
+ return /^@theme\b/m.test(content);
3049
+ }
3050
+
2559
3051
  // src/service/token-registry.ts
2560
3052
  var TokenRegistryManager = class {
2561
3053
  registry = null;
@@ -3576,7 +4068,7 @@ function applyPatches(sourceCode, patches) {
3576
4068
  }
3577
4069
 
3578
4070
  // src/service/metrics-store.ts
3579
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, readdir as readdir2 } from "fs/promises";
4071
+ import { readFile as readFile3, writeFile as writeFile2, mkdir as mkdir2, readdir as readdir2 } from "fs/promises";
3580
4072
  import { join as join2 } from "path";
3581
4073
  var MetricsStore = class {
3582
4074
  projectRoot;
@@ -3596,7 +4088,7 @@ var MetricsStore = class {
3596
4088
  const filepath = join2(this.metricsDir, filename);
3597
4089
  let snapshots = [];
3598
4090
  try {
3599
- const existing = await readFile2(filepath, "utf-8");
4091
+ const existing = await readFile3(filepath, "utf-8");
3600
4092
  snapshots = JSON.parse(existing);
3601
4093
  } catch {
3602
4094
  }
@@ -3623,7 +4115,7 @@ var MetricsStore = class {
3623
4115
  continue;
3624
4116
  }
3625
4117
  try {
3626
- const content = await readFile2(join2(this.metricsDir, file), "utf-8");
4118
+ const content = await readFile3(join2(this.metricsDir, file), "utf-8");
3627
4119
  const fileSnapshots = JSON.parse(content);
3628
4120
  const matching = component === "all" ? fileSnapshots : fileSnapshots.filter((s) => s.component === component);
3629
4121
  snapshots.push(...matching);
@@ -3754,12 +4246,12 @@ function createMetricsStore(projectRoot) {
3754
4246
  import { parse as parse2 } from "@babel/parser";
3755
4247
  import _traverse from "@babel/traverse";
3756
4248
  import * as t2 from "@babel/types";
3757
- import { readFile as readFile3 } from "fs/promises";
4249
+ import { readFile as readFile4 } from "fs/promises";
3758
4250
  import { existsSync as existsSync2 } from "fs";
3759
4251
  import { basename, dirname as dirname3, join as join3 } from "path";
3760
4252
  var traverse2 = _traverse.default || _traverse;
3761
4253
  async function extractComponentDocs(filePath) {
3762
- const content = await readFile3(filePath, "utf-8");
4254
+ const content = await readFile4(filePath, "utf-8");
3763
4255
  return extractDocsFromSource(content, filePath);
3764
4256
  }
3765
4257
  function extractDocsFromSource(source, filePath) {
@@ -4101,12 +4593,12 @@ async function extractAllComponentDocs(componentFiles) {
4101
4593
  import { parse as parse3 } from "@babel/parser";
4102
4594
  import _traverse2 from "@babel/traverse";
4103
4595
  import * as t3 from "@babel/types";
4104
- import { readFile as readFile4 } from "fs/promises";
4596
+ import { readFile as readFile5 } from "fs/promises";
4105
4597
  import fg from "fast-glob";
4106
- import { basename as basename2, relative } from "path";
4598
+ import { basename as basename2, relative as relative2 } from "path";
4107
4599
  var traverse3 = _traverse2.default || _traverse2;
4108
4600
  async function parseStoryFile(filePath) {
4109
- const content = await readFile4(filePath, "utf-8");
4601
+ const content = await readFile5(filePath, "utf-8");
4110
4602
  return parseStorySource(content, filePath);
4111
4603
  }
4112
4604
  function parseStorySource(source, filePath) {
@@ -4403,7 +4895,7 @@ async function parseAllStories(rootDir) {
4403
4895
  results.set(parsed.meta.componentName, parsed);
4404
4896
  } catch (error) {
4405
4897
  console.warn(
4406
- `Failed to parse story file ${relative(rootDir, filePath)}:`,
4898
+ `Failed to parse story file ${relative2(rootDir, filePath)}:`,
4407
4899
  error.message
4408
4900
  );
4409
4901
  }
@@ -4741,11 +5233,11 @@ If there isn't enough usage data to make confident recommendations, indicate tha
4741
5233
 
4742
5234
  // src/service/enhance/props-extractor.ts
4743
5235
  import * as ts from "typescript";
4744
- import { readFile as readFile5 } from "fs/promises";
5236
+ import { readFile as readFile6 } from "fs/promises";
4745
5237
  import { existsSync as existsSync3 } from "fs";
4746
- import { basename as basename3, dirname as dirname5, join as join5, resolve as resolve2 } from "path";
5238
+ import { basename as basename3, dirname as dirname5, join as join5, resolve as resolve3 } from "path";
4747
5239
  async function extractPropsFromFile(filePath, options = {}) {
4748
- const absPath = resolve2(filePath);
5240
+ const absPath = resolve3(filePath);
4749
5241
  if (!existsSync3(absPath)) {
4750
5242
  return {
4751
5243
  filePath: absPath,
@@ -4755,7 +5247,7 @@ async function extractPropsFromFile(filePath, options = {}) {
4755
5247
  warnings: [`File not found: ${absPath}`]
4756
5248
  };
4757
5249
  }
4758
- const content = await readFile5(absPath, "utf-8");
5250
+ const content = await readFile6(absPath, "utf-8");
4759
5251
  return extractPropsFromSource(content, absPath, options);
4760
5252
  }
4761
5253
  function extractPropsFromSource(source, filePath, options = {}) {
@@ -5545,6 +6037,15 @@ export {
5545
6037
  getGrade,
5546
6038
  getScoreColor,
5547
6039
  generateHtmlReport,
6040
+ parseTailwindV4Theme,
6041
+ parseTokenFile,
6042
+ parseTokenFiles,
6043
+ hexToRgb,
6044
+ rgbToHex,
6045
+ parseRgb,
6046
+ normalizeColor,
6047
+ parseTailwindV4File,
6048
+ containsTailwindV4Theme,
5548
6049
  TokenRegistryManager,
5549
6050
  getSharedTokenRegistry,
5550
6051
  initializeSharedRegistry,
@@ -5587,4 +6088,4 @@ export {
5587
6088
  getStorybookStoryIds,
5588
6089
  renderAllComponentVariants
5589
6090
  };
5590
- //# sourceMappingURL=chunk-6SQPP47U.js.map
6091
+ //# sourceMappingURL=chunk-ANTWP3UG.js.map