@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.
- package/dist/bin.js +901 -789
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-6SQPP47U.js → chunk-ANTWP3UG.js} +532 -31
- package/dist/chunk-ANTWP3UG.js.map +1 -0
- package/dist/{chunk-ONUP6Z4W.js → chunk-B4A4ZEGS.js} +9 -9
- package/dist/{chunk-32LIWN2P.js → chunk-FFCI6OVZ.js} +584 -261
- package/dist/chunk-FFCI6OVZ.js.map +1 -0
- package/dist/{chunk-HQ6A6DTV.js → chunk-HNHE64CR.js} +315 -1089
- package/dist/chunk-HNHE64CR.js.map +1 -0
- package/dist/{chunk-BJE3425I.js → chunk-MN3B2EE6.js} +2 -2
- package/dist/{chunk-QCN35LJU.js → chunk-SAQW37L5.js} +3 -2
- package/dist/chunk-SAQW37L5.js.map +1 -0
- package/dist/{chunk-2WXKALIG.js → chunk-SNZXGHL2.js} +2 -2
- package/dist/{chunk-5JF26E55.js → chunk-VT2J62ND.js} +11 -11
- package/dist/{codebase-scanner-MQHUZC2G.js → codebase-scanner-2T5QIDBA.js} +2 -2
- package/dist/core/index.js +53 -1
- package/dist/{create-EXURTBKK.js → create-D44QD7MV.js} +2 -2
- package/dist/{doctor-BDPMYYE6.js → doctor-7B5N4JYU.js} +2 -2
- package/dist/{generate-PVOLUAAC.js → generate-T47JZRVU.js} +4 -4
- package/dist/govern-scan-X6UEIOSV.js +632 -0
- package/dist/govern-scan-X6UEIOSV.js.map +1 -0
- package/dist/index.js +7 -8
- package/dist/index.js.map +1 -1
- package/dist/{init-SSGUSP7Z.js → init-2RGAY4W6.js} +5 -5
- package/dist/mcp-bin.js +2 -2
- package/dist/scan-A2WJM54L.js +14 -0
- package/dist/{scan-generate-VY27PIOX.js → scan-generate-LUSOHT36.js} +4 -4
- package/dist/{service-QJGWUIVL.js → service-ROCP7TKG.js} +13 -15
- package/dist/{snapshot-WIJMEIFT.js → snapshot-B3SAW74Y.js} +2 -2
- package/dist/{static-viewer-7QIBQZRC.js → static-viewer-7L6UEYTJ.js} +3 -3
- package/dist/{test-64Z5BKBA.js → test-PQDVDURE.js} +3 -3
- package/dist/{token-normalizer-TEPOVBPV.js → token-normalizer-7TFCVDZL.js} +2 -2
- package/dist/{tokens-NZWFQIAB.js → tokens-64FG5FDP.js} +8 -9
- package/dist/{tokens-NZWFQIAB.js.map → tokens-64FG5FDP.js.map} +1 -1
- package/dist/{tokens-generate-5JQSJ27E.js → tokens-generate-CL4LBBQA.js} +2 -2
- package/package.json +9 -8
- package/src/bin.ts +55 -88
- package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +1 -1
- package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +1 -1
- package/src/commands/__tests__/context-cloud.test.ts +291 -0
- package/src/commands/__tests__/govern-scan.test.ts +185 -0
- package/src/commands/__tests__/govern.test.ts +1 -0
- package/src/commands/context-cloud.ts +355 -0
- package/src/commands/govern-scan-report.ts +170 -0
- package/src/commands/govern-scan.ts +282 -135
- package/src/commands/govern.ts +0 -157
- package/src/mcp/__tests__/server.integration.test.ts +9 -20
- package/src/service/enhance/codebase-scanner.ts +3 -2
- package/src/service/enhance/types.ts +3 -0
- package/dist/chunk-32LIWN2P.js.map +0 -1
- package/dist/chunk-6SQPP47U.js.map +0 -1
- package/dist/chunk-HQ6A6DTV.js.map +0 -1
- package/dist/chunk-MHIBEEW4.js +0 -511
- package/dist/chunk-MHIBEEW4.js.map +0 -1
- package/dist/chunk-QCN35LJU.js.map +0 -1
- package/dist/govern-scan-DW4QUAYD.js +0 -414
- package/dist/govern-scan-DW4QUAYD.js.map +0 -1
- package/dist/init-cloud-3DNKPWFB.js +0 -304
- package/dist/init-cloud-3DNKPWFB.js.map +0 -1
- package/dist/node-37AUE74M.js +0 -65
- package/dist/push-contracts-WY32TFP6.js +0 -84
- package/dist/push-contracts-WY32TFP6.js.map +0 -1
- package/dist/scan-PKSYSTRR.js +0 -15
- package/dist/static-viewer-7QIBQZRC.js.map +0 -1
- package/dist/token-parser-32KOIOFN.js +0 -22
- package/dist/token-parser-32KOIOFN.js.map +0 -1
- package/dist/tokens-push-HY3KO36V.js +0 -148
- package/dist/tokens-push-HY3KO36V.js.map +0 -1
- package/src/commands/init-cloud.ts +0 -382
- package/src/commands/push-contracts.ts +0 -112
- package/src/commands/tokens-push.ts +0 -199
- /package/dist/{chunk-ONUP6Z4W.js.map → chunk-B4A4ZEGS.js.map} +0 -0
- /package/dist/{chunk-BJE3425I.js.map → chunk-MN3B2EE6.js.map} +0 -0
- /package/dist/{chunk-2WXKALIG.js.map → chunk-SNZXGHL2.js.map} +0 -0
- /package/dist/{chunk-5JF26E55.js.map → chunk-VT2J62ND.js.map} +0 -0
- /package/dist/{codebase-scanner-MQHUZC2G.js.map → codebase-scanner-2T5QIDBA.js.map} +0 -0
- /package/dist/{create-EXURTBKK.js.map → create-D44QD7MV.js.map} +0 -0
- /package/dist/{doctor-BDPMYYE6.js.map → doctor-7B5N4JYU.js.map} +0 -0
- /package/dist/{generate-PVOLUAAC.js.map → generate-T47JZRVU.js.map} +0 -0
- /package/dist/{init-SSGUSP7Z.js.map → init-2RGAY4W6.js.map} +0 -0
- /package/dist/{node-37AUE74M.js.map → scan-A2WJM54L.js.map} +0 -0
- /package/dist/{scan-generate-VY27PIOX.js.map → scan-generate-LUSOHT36.js.map} +0 -0
- /package/dist/{scan-PKSYSTRR.js.map → service-ROCP7TKG.js.map} +0 -0
- /package/dist/{snapshot-WIJMEIFT.js.map → snapshot-B3SAW74Y.js.map} +0 -0
- /package/dist/{service-QJGWUIVL.js.map → static-viewer-7L6UEYTJ.js.map} +0 -0
- /package/dist/{test-64Z5BKBA.js.map → test-PQDVDURE.js.map} +0 -0
- /package/dist/{token-normalizer-TEPOVBPV.js.map → token-normalizer-7TFCVDZL.js.map} +0 -0
- /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-
|
|
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
|
|
84
|
-
|
|
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
|
|
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((
|
|
193
|
+
return new Promise((resolve4, reject) => {
|
|
199
194
|
const timeout = setTimeout(() => {
|
|
200
|
-
const index = this.waitingQueue.indexOf(
|
|
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
|
-
|
|
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
|
|
291
|
+
let resolve4;
|
|
297
292
|
let reject;
|
|
298
293
|
const promise = new Promise((res, rej) => {
|
|
299
|
-
|
|
294
|
+
resolve4 = res;
|
|
300
295
|
reject = rej;
|
|
301
296
|
});
|
|
302
|
-
return { promise, resolve:
|
|
297
|
+
return { promise, resolve: resolve4, reject };
|
|
303
298
|
}
|
|
304
299
|
function sleep(ms) {
|
|
305
|
-
return new Promise((
|
|
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((
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 ${
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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-
|
|
6091
|
+
//# sourceMappingURL=chunk-ANTWP3UG.js.map
|