@fragments-sdk/cli 0.7.0 → 0.7.1
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 +245 -245
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-XHUDJNN3.js → chunk-32VIEOQY.js} +18 -18
- package/dist/chunk-32VIEOQY.js.map +1 -0
- package/dist/{chunk-CVXKXVOY.js → chunk-5ITIP3ES.js} +27 -27
- package/dist/chunk-5ITIP3ES.js.map +1 -0
- package/dist/{chunk-RVRTRESS.js → chunk-DQHWLAUV.js} +29 -29
- package/dist/chunk-DQHWLAUV.js.map +1 -0
- package/dist/{chunk-TJ34N7C7.js → chunk-GCZMFLDI.js} +30 -32
- package/dist/chunk-GCZMFLDI.js.map +1 -0
- package/dist/{chunk-6JBGU74P.js → chunk-GHYYFAQN.js} +23 -23
- package/dist/chunk-GHYYFAQN.js.map +1 -0
- package/dist/{chunk-NWQ4CJOQ.js → chunk-GKX2HPZ6.js} +40 -40
- package/dist/chunk-GKX2HPZ6.js.map +1 -0
- package/dist/{chunk-7OPWMLOE.js → chunk-U6VTHBNI.js} +110 -110
- package/dist/chunk-U6VTHBNI.js.map +1 -0
- package/dist/{core-W2HYIQW6.js → core-SFHPYR5H.js} +24 -26
- package/dist/{generate-LMTISDIJ.js → generate-54GJAWUY.js} +5 -5
- package/dist/generate-54GJAWUY.js.map +1 -0
- package/dist/index.d.ts +23 -27
- package/dist/index.js +10 -10
- package/dist/{init-7CHRKQ7P.js → init-EIM5WNMP.js} +5 -5
- package/dist/{init-7CHRKQ7P.js.map → init-EIM5WNMP.js.map} +1 -1
- package/dist/mcp-bin.js +73 -73
- package/dist/mcp-bin.js.map +1 -1
- package/dist/scan-KQBKUS64.js +12 -0
- package/dist/{service-T2L7VLTE.js → service-ED2LNCTU.js} +6 -6
- package/dist/{static-viewer-GBR7YNF3.js → static-viewer-Q4F4QP5M.js} +4 -4
- package/dist/{test-OJRXNDO2.js → test-6VN2DA3S.js} +19 -19
- package/dist/test-6VN2DA3S.js.map +1 -0
- package/dist/{tokens-3BWDESVM.js → tokens-P2B7ZAM3.js} +5 -5
- package/dist/{viewer-SUFOISZM.js → viewer-GM7IQPPB.js} +199 -199
- package/dist/viewer-GM7IQPPB.js.map +1 -0
- package/package.json +2 -2
- package/src/ai.ts +5 -5
- package/src/analyze.ts +11 -11
- package/src/bin.ts +1 -1
- package/src/build.ts +33 -33
- package/src/commands/a11y.ts +6 -6
- package/src/commands/add.ts +11 -11
- package/src/commands/audit.ts +4 -4
- package/src/commands/baseline.ts +3 -3
- package/src/commands/build.ts +8 -8
- package/src/commands/compare.ts +20 -20
- package/src/commands/context.ts +16 -16
- package/src/commands/enhance.ts +36 -36
- package/src/commands/generate.ts +1 -1
- package/src/commands/graph.ts +3 -3
- package/src/commands/init.ts +1 -1
- package/src/commands/link/figma.ts +82 -82
- package/src/commands/link/index.ts +3 -3
- package/src/commands/link/storybook.ts +9 -9
- package/src/commands/list.ts +2 -2
- package/src/commands/reset.ts +15 -15
- package/src/commands/scan.ts +27 -27
- package/src/commands/storygen.ts +24 -24
- package/src/commands/validate.ts +2 -2
- package/src/commands/verify.ts +8 -8
- package/src/core/auto-props.ts +4 -4
- package/src/core/composition.test.ts +36 -36
- package/src/core/composition.ts +19 -19
- package/src/core/config.ts +6 -6
- package/src/core/{defineSegment.ts → defineFragment.ts} +16 -22
- package/src/core/discovery.ts +6 -6
- package/src/core/figma.ts +2 -2
- package/src/core/graph-extractor.test.ts +77 -77
- package/src/core/graph-extractor.ts +32 -32
- package/src/core/importAnalyzer.ts +1 -1
- package/src/core/index.ts +22 -23
- package/src/core/loader.ts +22 -22
- package/src/core/node.ts +5 -5
- package/src/core/parser.ts +31 -31
- package/src/core/previewLoader.ts +1 -1
- package/src/core/schema.ts +16 -16
- package/src/core/storyAdapter.test.ts +87 -87
- package/src/core/storyAdapter.ts +16 -16
- package/src/core/types.ts +21 -26
- package/src/diff.ts +22 -22
- package/src/index.ts +2 -2
- package/src/mcp/server.ts +80 -80
- package/src/migrate/__tests__/utils/utils.test.ts +3 -3
- package/src/migrate/bin.ts +4 -4
- package/src/migrate/converter.ts +16 -16
- package/src/migrate/index.ts +3 -3
- package/src/migrate/migrate.ts +3 -3
- package/src/migrate/parser.ts +8 -8
- package/src/migrate/report.ts +2 -2
- package/src/migrate/types.ts +4 -4
- package/src/screenshot.ts +22 -22
- package/src/service/__tests__/props-extractor.test.ts +15 -15
- package/src/service/analytics.ts +39 -39
- package/src/service/enhance/codebase-scanner.ts +1 -1
- package/src/service/enhance/index.ts +1 -1
- package/src/service/enhance/props-extractor.ts +2 -2
- package/src/service/enhance/types.ts +2 -2
- package/src/service/index.ts +2 -2
- package/src/service/metrics-store.ts +1 -1
- package/src/service/patch-generator.ts +1 -1
- package/src/setup.ts +52 -52
- package/src/shared/dev-server-client.ts +7 -7
- package/src/shared/fragment-loader.ts +59 -0
- package/src/shared/index.ts +1 -1
- package/src/shared/types.ts +4 -4
- package/src/static-viewer.ts +35 -35
- package/src/test/discovery.ts +6 -6
- package/src/test/index.ts +5 -5
- package/src/test/reporters/console.ts +1 -1
- package/src/test/reporters/junit.ts +1 -1
- package/src/test/runner.ts +7 -7
- package/src/test/types.ts +3 -3
- package/src/test/watch.ts +9 -9
- package/src/validators.ts +26 -26
- package/src/viewer/__tests__/render-utils.test.ts +28 -28
- package/src/viewer/__tests__/viewer-integration.test.ts +4 -4
- package/src/viewer/cli/health.ts +26 -26
- package/src/viewer/components/App.tsx +79 -79
- package/src/viewer/components/BottomPanel.tsx +17 -17
- package/src/viewer/components/CodePanel.tsx +3 -3
- package/src/viewer/components/CommandPalette.tsx +11 -11
- package/src/viewer/components/ComponentGraph.tsx +28 -28
- package/src/viewer/components/ComponentHeader.tsx +2 -2
- package/src/viewer/components/ContractPanel.tsx +6 -6
- package/src/viewer/components/FigmaEmbed.tsx +9 -9
- package/src/viewer/components/HealthDashboard.tsx +17 -17
- package/src/viewer/components/InteractionsPanel.tsx +2 -2
- package/src/viewer/components/IsolatedPreviewFrame.tsx +6 -6
- package/src/viewer/components/IsolatedRender.tsx +10 -10
- package/src/viewer/components/LeftSidebar.tsx +28 -28
- package/src/viewer/components/MultiViewportPreview.tsx +14 -14
- package/src/viewer/components/PreviewArea.tsx +11 -11
- package/src/viewer/components/PreviewFrameHost.tsx +51 -51
- package/src/viewer/components/RightSidebar.tsx +9 -9
- package/src/viewer/components/Sidebar.tsx +17 -17
- package/src/viewer/components/StoryRenderer.tsx +2 -2
- package/src/viewer/components/TokenStylePanel.tsx +1 -1
- package/src/viewer/components/UsageSection.tsx +2 -2
- package/src/viewer/components/VariantMatrix.tsx +11 -11
- package/src/viewer/components/VariantRenderer.tsx +3 -3
- package/src/viewer/components/VariantTabs.tsx +2 -2
- package/src/viewer/components/_future/CreatePage.tsx +6 -6
- package/src/viewer/composition-renderer.ts +11 -11
- package/src/viewer/entry.tsx +40 -40
- package/src/viewer/hooks/useFigmaIntegration.ts +1 -1
- package/src/viewer/hooks/usePreviewBridge.ts +5 -5
- package/src/viewer/hooks/useUrlState.ts +6 -6
- package/src/viewer/index.ts +2 -2
- package/src/viewer/intelligence/healthReport.ts +17 -17
- package/src/viewer/intelligence/styleDrift.ts +1 -1
- package/src/viewer/intelligence/usageScanner.ts +1 -1
- package/src/viewer/render-template.html +1 -1
- package/src/viewer/render-utils.ts +21 -21
- package/src/viewer/server.ts +18 -18
- package/src/viewer/utils/detectRelationships.ts +22 -22
- package/src/viewer/vite-plugin.ts +213 -213
- package/dist/chunk-6JBGU74P.js.map +0 -1
- package/dist/chunk-7OPWMLOE.js.map +0 -1
- package/dist/chunk-CVXKXVOY.js.map +0 -1
- package/dist/chunk-NWQ4CJOQ.js.map +0 -1
- package/dist/chunk-RVRTRESS.js.map +0 -1
- package/dist/chunk-TJ34N7C7.js.map +0 -1
- package/dist/chunk-XHUDJNN3.js.map +0 -1
- package/dist/generate-LMTISDIJ.js.map +0 -1
- package/dist/scan-WY23TJCP.js +0 -12
- package/dist/test-OJRXNDO2.js.map +0 -1
- package/dist/viewer-SUFOISZM.js.map +0 -1
- package/src/shared/segment-loader.ts +0 -59
- /package/dist/{core-W2HYIQW6.js.map → core-SFHPYR5H.js.map} +0 -0
- /package/dist/{scan-WY23TJCP.js.map → scan-KQBKUS64.js.map} +0 -0
- /package/dist/{service-T2L7VLTE.js.map → service-ED2LNCTU.js.map} +0 -0
- /package/dist/{static-viewer-GBR7YNF3.js.map → static-viewer-Q4F4QP5M.js.map} +0 -0
- /package/dist/{tokens-3BWDESVM.js.map → tokens-P2B7ZAM3.js.map} +0 -0
|
@@ -8,57 +8,57 @@ import {
|
|
|
8
8
|
formatMs,
|
|
9
9
|
generateHtmlReport,
|
|
10
10
|
getGrade
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GKX2HPZ6.js";
|
|
12
12
|
import {
|
|
13
13
|
discoverBlockFiles,
|
|
14
14
|
discoverComponentFiles,
|
|
15
|
-
|
|
15
|
+
discoverFragmentFiles,
|
|
16
16
|
discoverTokenFiles,
|
|
17
17
|
extractComponentName,
|
|
18
18
|
generateContextMd,
|
|
19
19
|
generateRegistry,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from "./chunk-
|
|
20
|
+
loadFragmentFile,
|
|
21
|
+
parseFragmentFile
|
|
22
|
+
} from "./chunk-5ITIP3ES.js";
|
|
23
23
|
import {
|
|
24
24
|
compileBlock,
|
|
25
25
|
parseTokenFile
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-GCZMFLDI.js";
|
|
27
27
|
import {
|
|
28
28
|
BRAND,
|
|
29
29
|
DEFAULTS,
|
|
30
|
-
|
|
31
|
-
} from "./chunk-
|
|
30
|
+
fragmentDefinitionSchema
|
|
31
|
+
} from "./chunk-GHYYFAQN.js";
|
|
32
32
|
|
|
33
33
|
// src/validators.ts
|
|
34
34
|
async function validateSchema(config, configDir) {
|
|
35
|
-
const files = await
|
|
35
|
+
const files = await discoverFragmentFiles(config, configDir);
|
|
36
36
|
const errors = [];
|
|
37
37
|
const warnings = [];
|
|
38
38
|
for (const file of files) {
|
|
39
39
|
try {
|
|
40
|
-
const
|
|
41
|
-
if (!
|
|
40
|
+
const fragment = await loadFragmentFile(file.absolutePath);
|
|
41
|
+
if (!fragment) {
|
|
42
42
|
errors.push({
|
|
43
43
|
file: file.relativePath,
|
|
44
44
|
message: "No default export found",
|
|
45
|
-
details: `
|
|
45
|
+
details: `Fragment files must have a default export from defineFragment()`
|
|
46
46
|
});
|
|
47
47
|
continue;
|
|
48
48
|
}
|
|
49
|
-
const result =
|
|
49
|
+
const result = fragmentDefinitionSchema.safeParse(fragment);
|
|
50
50
|
if (!result.success) {
|
|
51
51
|
const details = result.error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ");
|
|
52
52
|
errors.push({
|
|
53
53
|
file: file.relativePath,
|
|
54
|
-
message: "Invalid
|
|
54
|
+
message: "Invalid fragment schema",
|
|
55
55
|
details
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
} catch (error) {
|
|
59
59
|
errors.push({
|
|
60
60
|
file: file.relativePath,
|
|
61
|
-
message: "Failed to load
|
|
61
|
+
message: "Failed to load fragment file",
|
|
62
62
|
details: error instanceof Error ? error.message : String(error)
|
|
63
63
|
});
|
|
64
64
|
}
|
|
@@ -70,33 +70,33 @@ async function validateSchema(config, configDir) {
|
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
async function validateCoverage(config, configDir) {
|
|
73
|
-
const
|
|
73
|
+
const fragmentFiles = await discoverFragmentFiles(config, configDir);
|
|
74
74
|
const componentFiles = await discoverComponentFiles(config, configDir);
|
|
75
75
|
const errors = [];
|
|
76
76
|
const warnings = [];
|
|
77
77
|
const documentedComponents = /* @__PURE__ */ new Set();
|
|
78
|
-
for (const file of
|
|
78
|
+
for (const file of fragmentFiles) {
|
|
79
79
|
try {
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
82
|
-
documentedComponents.add(
|
|
80
|
+
const fragment = await loadFragmentFile(file.absolutePath);
|
|
81
|
+
if (fragment?.meta?.name) {
|
|
82
|
+
documentedComponents.add(fragment.meta.name);
|
|
83
83
|
}
|
|
84
84
|
} catch {
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
for (const file of componentFiles) {
|
|
88
88
|
const componentName = extractComponentName(file.relativePath);
|
|
89
|
-
const
|
|
89
|
+
const fragmentPath = file.relativePath.replace(
|
|
90
90
|
/\.(tsx?|jsx?)$/,
|
|
91
91
|
BRAND.fileExtension
|
|
92
92
|
);
|
|
93
|
-
const
|
|
94
|
-
(s) => s.relativePath ===
|
|
93
|
+
const hasFragmentFile = fragmentFiles.some(
|
|
94
|
+
(s) => s.relativePath === fragmentPath
|
|
95
95
|
);
|
|
96
|
-
if (!
|
|
96
|
+
if (!hasFragmentFile && !documentedComponents.has(componentName)) {
|
|
97
97
|
warnings.push({
|
|
98
98
|
file: file.relativePath,
|
|
99
|
-
message: `Component "${componentName}" has no
|
|
99
|
+
message: `Component "${componentName}" has no fragment documentation`
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
102
|
}
|
|
@@ -162,11 +162,11 @@ function resolveModulePath(basePath) {
|
|
|
162
162
|
}
|
|
163
163
|
return null;
|
|
164
164
|
}
|
|
165
|
-
function resolveComponentSourcePath(
|
|
165
|
+
function resolveComponentSourcePath(fragmentFileAbsolutePath, componentImportPath) {
|
|
166
166
|
if (!componentImportPath) return null;
|
|
167
167
|
if (!componentImportPath.startsWith(".")) return null;
|
|
168
|
-
const
|
|
169
|
-
const basePath = resolve(
|
|
168
|
+
const fragmentDir = dirname(fragmentFileAbsolutePath);
|
|
169
|
+
const basePath = resolve(fragmentDir, componentImportPath);
|
|
170
170
|
return resolveModulePath(basePath);
|
|
171
171
|
}
|
|
172
172
|
function collectTopLevelDeclarations(sourceFile) {
|
|
@@ -435,8 +435,8 @@ import { readFileSync, existsSync as existsSync2 } from "fs";
|
|
|
435
435
|
import { join as join2 } from "path";
|
|
436
436
|
import { readdirSync } from "fs";
|
|
437
437
|
import { EDGE_TYPE_WEIGHTS, computeHealthFromData } from "@fragments-sdk/context/graph";
|
|
438
|
-
async function buildComponentGraph(
|
|
439
|
-
const knownComponents = new Set(Object.keys(
|
|
438
|
+
async function buildComponentGraph(fragments, blocks, componentDir, options) {
|
|
439
|
+
const knownComponents = new Set(Object.keys(fragments));
|
|
440
440
|
const allEdges = [];
|
|
441
441
|
const autoDetected = /* @__PURE__ */ new Map();
|
|
442
442
|
const warnings = [];
|
|
@@ -452,31 +452,31 @@ async function buildComponentGraph(segments, blocks, componentDir, options) {
|
|
|
452
452
|
});
|
|
453
453
|
}
|
|
454
454
|
}
|
|
455
|
-
const jsxEdges = extractJsxUsageEdges(
|
|
455
|
+
const jsxEdges = extractJsxUsageEdges(fragments, knownComponents);
|
|
456
456
|
allEdges.push(...jsxEdges);
|
|
457
457
|
const blockEdges = extractBlockEdges(blocks);
|
|
458
458
|
allEdges.push(...blockEdges);
|
|
459
|
-
const relationEdges = extractRelationEdges(
|
|
459
|
+
const relationEdges = extractRelationEdges(fragments);
|
|
460
460
|
allEdges.push(...relationEdges);
|
|
461
|
-
const requiredChildrenMap = inferRequiredChildren(
|
|
461
|
+
const requiredChildrenMap = inferRequiredChildren(fragments, autoDetected);
|
|
462
462
|
for (const [name, children] of requiredChildrenMap) {
|
|
463
463
|
const existing = autoDetected.get(name) ?? {};
|
|
464
464
|
autoDetected.set(name, { ...existing, requiredChildren: children });
|
|
465
465
|
}
|
|
466
|
-
const patternsMap = generateCommonPatterns(
|
|
466
|
+
const patternsMap = generateCommonPatterns(fragments, autoDetected);
|
|
467
467
|
for (const [name, patterns] of patternsMap) {
|
|
468
468
|
const existing = autoDetected.get(name) ?? {};
|
|
469
469
|
autoDetected.set(name, { ...existing, commonPatterns: patterns });
|
|
470
470
|
}
|
|
471
471
|
const mergedEdges = mergeAndDeduplicate(allEdges);
|
|
472
|
-
const nodes = Object.entries(
|
|
472
|
+
const nodes = Object.entries(fragments).map(([name, fragment]) => {
|
|
473
473
|
const detected = autoDetected.get(name);
|
|
474
474
|
return {
|
|
475
475
|
name,
|
|
476
|
-
category:
|
|
477
|
-
status:
|
|
478
|
-
compositionPattern:
|
|
479
|
-
subComponents:
|
|
476
|
+
category: fragment.meta.category,
|
|
477
|
+
status: fragment.meta.status ?? "stable",
|
|
478
|
+
compositionPattern: fragment.ai?.compositionPattern ?? detected?.compositionPattern,
|
|
479
|
+
subComponents: fragment.ai?.subComponents ?? detected?.subComponents
|
|
480
480
|
};
|
|
481
481
|
});
|
|
482
482
|
const blockIndex = /* @__PURE__ */ new Map();
|
|
@@ -488,14 +488,14 @@ async function buildComponentGraph(segments, blocks, componentDir, options) {
|
|
|
488
488
|
}
|
|
489
489
|
}
|
|
490
490
|
const health = computeHealthFromData(nodes, mergedEdges, blockIndex);
|
|
491
|
-
for (const [name,
|
|
491
|
+
for (const [name, fragment] of Object.entries(fragments)) {
|
|
492
492
|
const detected = autoDetected.get(name);
|
|
493
493
|
if (!detected) continue;
|
|
494
|
-
if (
|
|
495
|
-
const declared = new Set(
|
|
494
|
+
if (fragment.ai?.subComponents && detected.subComponents) {
|
|
495
|
+
const declared = new Set(fragment.ai.subComponents);
|
|
496
496
|
const found = new Set(detected.subComponents);
|
|
497
497
|
const missing = detected.subComponents.filter((s) => !declared.has(s));
|
|
498
|
-
const extra =
|
|
498
|
+
const extra = fragment.ai.subComponents.filter((s) => !found.has(s));
|
|
499
499
|
if (missing.length > 0) {
|
|
500
500
|
warnings.push(
|
|
501
501
|
`${name}: declares ${declared.size} subComponents but code has ${found.size}. Missing from declaration: ${missing.join(", ")}`
|
|
@@ -631,12 +631,12 @@ function extractSubComponents(componentDir, knownComponents) {
|
|
|
631
631
|
}
|
|
632
632
|
return result;
|
|
633
633
|
}
|
|
634
|
-
function extractJsxUsageEdges(
|
|
634
|
+
function extractJsxUsageEdges(fragments, knownComponents) {
|
|
635
635
|
const edges = [];
|
|
636
636
|
const jsxTagRegex = /<([A-Z][a-zA-Z]*(?:\.[A-Z][a-zA-Z]*)?)/g;
|
|
637
|
-
for (const [name,
|
|
637
|
+
for (const [name, fragment] of Object.entries(fragments)) {
|
|
638
638
|
const usedComponents = /* @__PURE__ */ new Set();
|
|
639
|
-
for (const variant of
|
|
639
|
+
for (const variant of fragment.variants) {
|
|
640
640
|
if (!variant.code) continue;
|
|
641
641
|
let match;
|
|
642
642
|
jsxTagRegex.lastIndex = 0;
|
|
@@ -680,7 +680,7 @@ function extractBlockEdges(blocks) {
|
|
|
680
680
|
}
|
|
681
681
|
return edges;
|
|
682
682
|
}
|
|
683
|
-
function extractRelationEdges(
|
|
683
|
+
function extractRelationEdges(fragments) {
|
|
684
684
|
const edges = [];
|
|
685
685
|
const relationToEdgeType = {
|
|
686
686
|
parent: "parent-of",
|
|
@@ -690,9 +690,9 @@ function extractRelationEdges(segments) {
|
|
|
690
690
|
alternative: "alternative-to",
|
|
691
691
|
sibling: "sibling-of"
|
|
692
692
|
};
|
|
693
|
-
for (const [name,
|
|
694
|
-
if (!
|
|
695
|
-
for (const rel of
|
|
693
|
+
for (const [name, fragment] of Object.entries(fragments)) {
|
|
694
|
+
if (!fragment.relations) continue;
|
|
695
|
+
for (const rel of fragment.relations) {
|
|
696
696
|
const edgeType = relationToEdgeType[rel.relationship];
|
|
697
697
|
if (!edgeType) continue;
|
|
698
698
|
let source;
|
|
@@ -716,13 +716,13 @@ function extractRelationEdges(segments) {
|
|
|
716
716
|
}
|
|
717
717
|
return edges;
|
|
718
718
|
}
|
|
719
|
-
function inferRequiredChildren(
|
|
719
|
+
function inferRequiredChildren(fragments, autoDetected) {
|
|
720
720
|
const result = /* @__PURE__ */ new Map();
|
|
721
|
-
for (const [name,
|
|
721
|
+
for (const [name, fragment] of Object.entries(fragments)) {
|
|
722
722
|
const detected = autoDetected.get(name);
|
|
723
|
-
const subs = detected?.subComponents ??
|
|
723
|
+
const subs = detected?.subComponents ?? fragment.ai?.subComponents;
|
|
724
724
|
if (!subs || subs.length === 0) continue;
|
|
725
|
-
const variantsWithCode =
|
|
725
|
+
const variantsWithCode = fragment.variants.filter((v) => v.code);
|
|
726
726
|
if (variantsWithCode.length === 0) continue;
|
|
727
727
|
const required = [];
|
|
728
728
|
for (const sub of subs) {
|
|
@@ -741,13 +741,13 @@ function inferRequiredChildren(segments, autoDetected) {
|
|
|
741
741
|
}
|
|
742
742
|
return result;
|
|
743
743
|
}
|
|
744
|
-
function generateCommonPatterns(
|
|
744
|
+
function generateCommonPatterns(fragments, autoDetected) {
|
|
745
745
|
const result = /* @__PURE__ */ new Map();
|
|
746
|
-
for (const [name,
|
|
746
|
+
for (const [name, fragment] of Object.entries(fragments)) {
|
|
747
747
|
const detected = autoDetected.get(name);
|
|
748
|
-
const subs = detected?.subComponents ??
|
|
748
|
+
const subs = detected?.subComponents ?? fragment.ai?.subComponents;
|
|
749
749
|
if (!subs || subs.length === 0) continue;
|
|
750
|
-
const firstVariant =
|
|
750
|
+
const firstVariant = fragment.variants.find((v) => v.code);
|
|
751
751
|
if (!firstVariant?.code) continue;
|
|
752
752
|
const usedSubs = [];
|
|
753
753
|
for (const sub of subs) {
|
|
@@ -848,15 +848,15 @@ function mergeDocumentedAndAutoProps(documentedProps, autoProps) {
|
|
|
848
848
|
})
|
|
849
849
|
);
|
|
850
850
|
}
|
|
851
|
-
async function
|
|
852
|
-
const files = await
|
|
851
|
+
async function buildFragments(config, configDir) {
|
|
852
|
+
const files = await discoverFragmentFiles(config, configDir);
|
|
853
853
|
const errors = [];
|
|
854
854
|
const warnings = [];
|
|
855
|
-
const
|
|
855
|
+
const fragments = {};
|
|
856
856
|
for (const file of files) {
|
|
857
857
|
try {
|
|
858
858
|
const content = await readFile(file.absolutePath, "utf-8");
|
|
859
|
-
const parsed =
|
|
859
|
+
const parsed = parseFragmentFile(content, file.relativePath);
|
|
860
860
|
for (const warning of parsed.warnings) {
|
|
861
861
|
warnings.push({ file: file.relativePath, warning });
|
|
862
862
|
}
|
|
@@ -947,7 +947,7 @@ async function buildSegments(config, configDir) {
|
|
|
947
947
|
// Include AI metadata if present
|
|
948
948
|
...parsed.ai && { ai: parsed.ai }
|
|
949
949
|
};
|
|
950
|
-
|
|
950
|
+
fragments[parsed.meta.name] = compiled;
|
|
951
951
|
} catch (error) {
|
|
952
952
|
errors.push({
|
|
953
953
|
file: file.relativePath,
|
|
@@ -960,7 +960,7 @@ async function buildSegments(config, configDir) {
|
|
|
960
960
|
const blockFiles = await discoverBlockFiles(configDir, config.exclude);
|
|
961
961
|
for (const file of blockFiles) {
|
|
962
962
|
try {
|
|
963
|
-
let raw = await
|
|
963
|
+
let raw = await loadFragmentFile(file.absolutePath);
|
|
964
964
|
if (raw && "default" in raw && typeof raw.default === "object") {
|
|
965
965
|
raw = raw.default;
|
|
966
966
|
}
|
|
@@ -1020,22 +1020,22 @@ async function buildSegments(config, configDir) {
|
|
|
1020
1020
|
const componentDir = resolve3(configDir, "src", "components");
|
|
1021
1021
|
let graphData;
|
|
1022
1022
|
try {
|
|
1023
|
-
const graphResult = await buildComponentGraph(
|
|
1024
|
-
for (const [name,
|
|
1023
|
+
const graphResult = await buildComponentGraph(fragments, blocks, componentDir);
|
|
1024
|
+
for (const [name, fragment] of Object.entries(fragments)) {
|
|
1025
1025
|
const detected = graphResult.autoDetected.get(name);
|
|
1026
1026
|
if (!detected) continue;
|
|
1027
|
-
if (!
|
|
1028
|
-
if (!
|
|
1029
|
-
|
|
1027
|
+
if (!fragment.ai) fragment.ai = {};
|
|
1028
|
+
if (!fragment.ai.subComponents && detected.subComponents) {
|
|
1029
|
+
fragment.ai.subComponents = detected.subComponents;
|
|
1030
1030
|
}
|
|
1031
|
-
if (!
|
|
1032
|
-
|
|
1031
|
+
if (!fragment.ai.compositionPattern && detected.compositionPattern) {
|
|
1032
|
+
fragment.ai.compositionPattern = detected.compositionPattern;
|
|
1033
1033
|
}
|
|
1034
|
-
if (!
|
|
1035
|
-
|
|
1034
|
+
if (!fragment.ai.commonPatterns && detected.commonPatterns) {
|
|
1035
|
+
fragment.ai.commonPatterns = detected.commonPatterns;
|
|
1036
1036
|
}
|
|
1037
|
-
if (!
|
|
1038
|
-
|
|
1037
|
+
if (!fragment.ai.requiredChildren && detected.requiredChildren) {
|
|
1038
|
+
fragment.ai.requiredChildren = detected.requiredChildren;
|
|
1039
1039
|
}
|
|
1040
1040
|
}
|
|
1041
1041
|
for (const w of graphResult.warnings) {
|
|
@@ -1052,7 +1052,7 @@ async function buildSegments(config, configDir) {
|
|
|
1052
1052
|
version: "1.0.0",
|
|
1053
1053
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1054
1054
|
...packageName && { packageName },
|
|
1055
|
-
|
|
1055
|
+
fragments,
|
|
1056
1056
|
...Object.keys(blocks).length > 0 && { blocks },
|
|
1057
1057
|
...tokens && { tokens },
|
|
1058
1058
|
...graphData && { graph: graphData }
|
|
@@ -1062,7 +1062,7 @@ async function buildSegments(config, configDir) {
|
|
|
1062
1062
|
return {
|
|
1063
1063
|
success: errors.length === 0,
|
|
1064
1064
|
outputPath,
|
|
1065
|
-
|
|
1065
|
+
fragmentCount: Object.keys(fragments).length,
|
|
1066
1066
|
errors,
|
|
1067
1067
|
warnings
|
|
1068
1068
|
};
|
|
@@ -1118,9 +1118,9 @@ async function runScreenshotCommand(config, configDir, options = {}) {
|
|
|
1118
1118
|
viewport: options.width && options.height ? { width: options.width, height: options.height } : config.screenshots?.viewport
|
|
1119
1119
|
});
|
|
1120
1120
|
await storage.initialize();
|
|
1121
|
-
const
|
|
1122
|
-
if (
|
|
1123
|
-
console.log(pc.yellow("No
|
|
1121
|
+
const fragmentFiles = await discoverFragmentFiles(config, configDir);
|
|
1122
|
+
if (fragmentFiles.length === 0) {
|
|
1123
|
+
console.log(pc.yellow("No fragment files found."));
|
|
1124
1124
|
return {
|
|
1125
1125
|
success: true,
|
|
1126
1126
|
captured: 0,
|
|
@@ -1129,12 +1129,12 @@ async function runScreenshotCommand(config, configDir, options = {}) {
|
|
|
1129
1129
|
totalTimeMs: Date.now() - startTime
|
|
1130
1130
|
};
|
|
1131
1131
|
}
|
|
1132
|
-
const
|
|
1133
|
-
for (const file of
|
|
1132
|
+
const fragments = [];
|
|
1133
|
+
for (const file of fragmentFiles) {
|
|
1134
1134
|
try {
|
|
1135
|
-
const
|
|
1136
|
-
if (
|
|
1137
|
-
|
|
1135
|
+
const fragment = await loadFragmentFile(file.absolutePath);
|
|
1136
|
+
if (fragment) {
|
|
1137
|
+
fragments.push({ path: file.relativePath, fragment });
|
|
1138
1138
|
}
|
|
1139
1139
|
} catch (error) {
|
|
1140
1140
|
errors.push({
|
|
@@ -1144,8 +1144,8 @@ async function runScreenshotCommand(config, configDir, options = {}) {
|
|
|
1144
1144
|
});
|
|
1145
1145
|
}
|
|
1146
1146
|
}
|
|
1147
|
-
const
|
|
1148
|
-
if (options.component &&
|
|
1147
|
+
const filteredFragments = options.component ? fragments.filter((s) => s.fragment.meta.name === options.component) : fragments;
|
|
1148
|
+
if (options.component && filteredFragments.length === 0) {
|
|
1149
1149
|
console.log(pc.yellow(`Component "${options.component}" not found.`));
|
|
1150
1150
|
return {
|
|
1151
1151
|
success: false,
|
|
@@ -1156,11 +1156,11 @@ async function runScreenshotCommand(config, configDir, options = {}) {
|
|
|
1156
1156
|
};
|
|
1157
1157
|
}
|
|
1158
1158
|
const variantsToCapture = [];
|
|
1159
|
-
for (const {
|
|
1160
|
-
const variants = options.variant ?
|
|
1159
|
+
for (const { fragment } of filteredFragments) {
|
|
1160
|
+
const variants = options.variant ? fragment.variants.filter((v) => v.name === options.variant) : fragment.variants;
|
|
1161
1161
|
for (const variant of variants) {
|
|
1162
1162
|
variantsToCapture.push({
|
|
1163
|
-
component:
|
|
1163
|
+
component: fragment.meta.name,
|
|
1164
1164
|
variant: variant.name,
|
|
1165
1165
|
render: variant.render
|
|
1166
1166
|
});
|
|
@@ -1264,9 +1264,9 @@ async function runDiffCommand(config, configDir, options = {}) {
|
|
|
1264
1264
|
await storage.initialize();
|
|
1265
1265
|
const threshold = options.threshold ?? config.screenshots?.threshold ?? DEFAULTS.diffThreshold;
|
|
1266
1266
|
const diffEngine = new DiffEngine(threshold);
|
|
1267
|
-
const
|
|
1268
|
-
if (
|
|
1269
|
-
console.log(pc2.yellow("No
|
|
1267
|
+
const fragmentFiles = await discoverFragmentFiles(config, configDir);
|
|
1268
|
+
if (fragmentFiles.length === 0) {
|
|
1269
|
+
console.log(pc2.yellow("No fragment files found."));
|
|
1270
1270
|
return {
|
|
1271
1271
|
success: true,
|
|
1272
1272
|
total: 0,
|
|
@@ -1277,18 +1277,18 @@ async function runDiffCommand(config, configDir, options = {}) {
|
|
|
1277
1277
|
totalTimeMs: Date.now() - startTime
|
|
1278
1278
|
};
|
|
1279
1279
|
}
|
|
1280
|
-
const
|
|
1281
|
-
for (const file of
|
|
1280
|
+
const fragments = [];
|
|
1281
|
+
for (const file of fragmentFiles) {
|
|
1282
1282
|
try {
|
|
1283
|
-
const
|
|
1284
|
-
if (
|
|
1285
|
-
|
|
1283
|
+
const fragment = await loadFragmentFile(file.absolutePath);
|
|
1284
|
+
if (fragment) {
|
|
1285
|
+
fragments.push({ path: file.relativePath, fragment });
|
|
1286
1286
|
}
|
|
1287
1287
|
} catch {
|
|
1288
1288
|
}
|
|
1289
1289
|
}
|
|
1290
|
-
const
|
|
1291
|
-
if (options.component &&
|
|
1290
|
+
const filteredFragments = options.component ? fragments.filter((s) => s.fragment.meta.name === options.component) : fragments;
|
|
1291
|
+
if (options.component && filteredFragments.length === 0) {
|
|
1292
1292
|
console.log(pc2.yellow(`Component "${options.component}" not found.`));
|
|
1293
1293
|
return {
|
|
1294
1294
|
success: false,
|
|
@@ -1301,11 +1301,11 @@ async function runDiffCommand(config, configDir, options = {}) {
|
|
|
1301
1301
|
};
|
|
1302
1302
|
}
|
|
1303
1303
|
const variantsToDiff = [];
|
|
1304
|
-
for (const {
|
|
1305
|
-
const variants = options.variant ?
|
|
1304
|
+
for (const { fragment } of filteredFragments) {
|
|
1305
|
+
const variants = options.variant ? fragment.variants.filter((v) => v.name === options.variant) : fragment.variants;
|
|
1306
1306
|
for (const variant of variants) {
|
|
1307
1307
|
variantsToDiff.push({
|
|
1308
|
-
component:
|
|
1308
|
+
component: fragment.meta.name,
|
|
1309
1309
|
variant: variant.name
|
|
1310
1310
|
});
|
|
1311
1311
|
}
|
|
@@ -1458,9 +1458,9 @@ async function runAnalyzeCommand(config, configDir, options = {}) {
|
|
|
1458
1458
|
console.log(pc3.cyan(`
|
|
1459
1459
|
${BRAND.name} Analyzer
|
|
1460
1460
|
`));
|
|
1461
|
-
const
|
|
1462
|
-
if (!existsSync4(
|
|
1463
|
-
console.log(pc3.red(`\u2717 No
|
|
1461
|
+
const fragmentsPath = join4(configDir, config.outFile ?? "fragments.json");
|
|
1462
|
+
if (!existsSync4(fragmentsPath)) {
|
|
1463
|
+
console.log(pc3.red(`\u2717 No fragments.json found. Run \`${BRAND.cliCommand} build\` first.
|
|
1464
1464
|
`));
|
|
1465
1465
|
return {
|
|
1466
1466
|
success: false,
|
|
@@ -1468,7 +1468,7 @@ ${BRAND.name} Analyzer
|
|
|
1468
1468
|
};
|
|
1469
1469
|
}
|
|
1470
1470
|
console.log(pc3.dim("Analyzing design system...\n"));
|
|
1471
|
-
const content = await readFile2(
|
|
1471
|
+
const content = await readFile2(fragmentsPath, "utf-8");
|
|
1472
1472
|
const data = JSON.parse(content);
|
|
1473
1473
|
const analytics = analyzeDesignSystem(data);
|
|
1474
1474
|
printConsoleSummary(analytics);
|
|
@@ -1553,7 +1553,7 @@ function colorizeScore(score) {
|
|
|
1553
1553
|
return pc3.red(`${score}%`);
|
|
1554
1554
|
}
|
|
1555
1555
|
function getDefaultOutputPath(format, configDir) {
|
|
1556
|
-
const filename = format === "html" ? "
|
|
1556
|
+
const filename = format === "html" ? "fragments-report.html" : "fragments-report.json";
|
|
1557
1557
|
return join4(configDir, filename);
|
|
1558
1558
|
}
|
|
1559
1559
|
async function openInBrowser(path) {
|
|
@@ -1616,10 +1616,10 @@ export {
|
|
|
1616
1616
|
validateSchema,
|
|
1617
1617
|
validateCoverage,
|
|
1618
1618
|
validateAll,
|
|
1619
|
-
|
|
1619
|
+
buildFragments,
|
|
1620
1620
|
buildFragmentsDir,
|
|
1621
1621
|
runScreenshotCommand,
|
|
1622
1622
|
runDiffCommand,
|
|
1623
1623
|
runAnalyzeCommand
|
|
1624
1624
|
};
|
|
1625
|
-
//# sourceMappingURL=chunk-
|
|
1625
|
+
//# sourceMappingURL=chunk-U6VTHBNI.js.map
|