@fragments-sdk/cli 0.5.2 → 0.6.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 +712 -39
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-ICAIQ57V.js → chunk-6JBGU74P.js} +5 -3
- package/dist/chunk-6JBGU74P.js.map +1 -0
- package/dist/{chunk-U4GQ2JTD.js → chunk-D35RGPAG.js} +412 -35
- package/dist/chunk-D35RGPAG.js.map +1 -0
- package/dist/{chunk-XNWDI6UT.js → chunk-F7ITZPDJ.js} +5 -5
- package/dist/{chunk-IOJE35DZ.js → chunk-NWQ4CJOQ.js} +3 -3
- package/dist/{chunk-V7YLRR4C.js → chunk-Q7GOHVOK.js} +3 -3
- package/dist/{chunk-2DJH4F4P.js → chunk-RVRTRESS.js} +3 -3
- package/dist/{chunk-2H2JAA3U.js → chunk-SSLQXHNX.js} +3 -3
- package/dist/{core-DKHB7FYV.js → core-SKRPJQZG.js} +4 -4
- package/dist/{generate-KL24VZVD.js → generate-7AF7WRVK.js} +5 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/{init-NION5S3M.js → init-WKGDPYI4.js} +5 -5
- package/dist/mcp-bin.js +8 -220
- package/dist/mcp-bin.js.map +1 -1
- package/dist/scan-K6JNMCGM.js +12 -0
- package/dist/{service-RWUMZ3EW.js → service-F3E4JJM7.js} +5 -5
- package/dist/static-viewer-4LQZ5AGA.js +12 -0
- package/dist/{test-ECPEXFDN.js → test-CJDNJTPZ.js} +4 -4
- package/dist/{tokens-ITADYVPF.js → tokens-JAJABYXP.js} +6 -6
- package/dist/viewer-R3Q6WAMJ.js +1822 -0
- package/dist/viewer-R3Q6WAMJ.js.map +1 -0
- package/package.json +5 -4
- package/src/bin.ts +8 -0
- package/src/build.ts +104 -13
- package/src/cli-commands.ts +18 -0
- package/src/commands/__tests__/a11y-scoring.test.ts +278 -0
- package/src/commands/a11y-report.ts +625 -0
- package/src/commands/a11y.ts +168 -14
- package/src/commands/build.ts +16 -0
- package/src/core/auto-props.ts +464 -0
- package/src/core/schema.ts +2 -0
- package/src/core/types.ts +3 -1
- package/src/index.ts +4 -0
- package/src/mcp/server.ts +13 -220
- package/src/theme/__tests__/component-contrast.test.ts +338 -0
- package/src/theme/__tests__/contrast-validation.test.ts +326 -0
- package/src/theme/contrast.test.ts +331 -0
- package/src/theme/contrast.ts +246 -0
- package/src/theme/generator.ts +213 -1
- package/src/theme/index.ts +16 -0
- package/src/theme/types.ts +51 -0
- package/src/viewer/__tests__/a11y-fixes.test.ts +358 -0
- package/src/viewer/__tests__/viewer-integration.test.ts +2 -7
- package/src/viewer/components/AccessibilityPanel.tsx +493 -433
- package/src/viewer/components/ActionCapture.tsx +1 -1
- package/src/viewer/components/ActionsPanel.tsx +142 -183
- package/src/viewer/components/App.tsx +159 -164
- package/src/viewer/components/BottomPanel.tsx +40 -80
- package/src/viewer/components/CodePanel.tsx +9 -87
- package/src/viewer/components/CommandPalette.tsx +117 -74
- package/src/viewer/components/ComponentGraph.tsx +143 -126
- package/src/viewer/components/ComponentHeader.tsx +46 -43
- package/src/viewer/components/ContractPanel.tsx +124 -117
- package/src/viewer/components/ErrorBoundary.tsx +47 -35
- package/src/viewer/components/FigmaEmbed.tsx +18 -13
- package/src/viewer/components/FragmentEditor.tsx +126 -63
- package/src/viewer/components/HealthDashboard.tsx +146 -171
- package/src/viewer/components/HmrStatusIndicator.tsx +31 -41
- package/src/viewer/components/Icons.tsx +99 -98
- package/src/viewer/components/InteractionsPanel.tsx +317 -264
- package/src/viewer/components/IsolatedPreviewFrame.tsx +52 -27
- package/src/viewer/components/IsolatedRender.tsx +12 -6
- package/src/viewer/components/KeyboardShortcutsHelp.tsx +34 -70
- package/src/viewer/components/LandingPage.tsx +285 -305
- package/src/viewer/components/Layout.tsx +7 -9
- package/src/viewer/components/LeftSidebar.tsx +78 -108
- package/src/viewer/components/MultiViewportPreview.tsx +254 -63
- package/src/viewer/components/PreviewArea.tsx +113 -44
- package/src/viewer/components/PreviewFrameHost.tsx +6 -5
- package/src/viewer/components/PreviewPane.tsx +2 -3
- package/src/viewer/components/PreviewToolbar.tsx +61 -104
- package/src/viewer/components/PropsEditor.tsx +154 -74
- package/src/viewer/components/PropsTable.tsx +95 -82
- package/src/viewer/components/RelationsSection.tsx +71 -40
- package/src/viewer/components/ResizablePanel.tsx +158 -55
- package/src/viewer/components/RightSidebar.tsx +46 -56
- package/src/viewer/components/ScreenshotButton.tsx +12 -12
- package/src/viewer/components/SkeletonLoader.tsx +99 -83
- package/src/viewer/components/StoryRenderer.tsx +4 -11
- package/src/viewer/components/Toast.tsx +3 -67
- package/src/viewer/components/TokenStylePanel.tsx +136 -118
- package/src/viewer/components/UsageSection.tsx +26 -26
- package/src/viewer/components/VariantMatrix.tsx +140 -47
- package/src/viewer/components/VariantTabs.tsx +24 -68
- package/src/viewer/components/ViewportSelector.tsx +106 -110
- package/src/viewer/constants/ui.ts +19 -18
- package/src/viewer/entry.tsx +8 -3
- package/src/viewer/index.ts +3 -6
- package/src/viewer/preview-frame.html +21 -5
- package/src/viewer/server.ts +7 -16
- package/src/viewer/styles/globals.css +4 -4
- package/src/viewer/utils/a11y-fixes.ts +53 -30
- package/dist/chunk-ICAIQ57V.js.map +0 -1
- package/dist/chunk-U4GQ2JTD.js.map +0 -1
- package/dist/scan-ESEXV7LF.js +0 -12
- package/dist/static-viewer-O37MJ5B6.js +0 -12
- package/dist/viewer-YDGFDTK5.js +0 -11104
- package/dist/viewer-YDGFDTK5.js.map +0 -1
- package/src/viewer/postcss.config.js +0 -6
- package/src/viewer/tailwind.config.js +0 -37
- /package/dist/{chunk-XNWDI6UT.js.map → chunk-F7ITZPDJ.js.map} +0 -0
- /package/dist/{chunk-IOJE35DZ.js.map → chunk-NWQ4CJOQ.js.map} +0 -0
- /package/dist/{chunk-V7YLRR4C.js.map → chunk-Q7GOHVOK.js.map} +0 -0
- /package/dist/{chunk-2DJH4F4P.js.map → chunk-RVRTRESS.js.map} +0 -0
- /package/dist/{chunk-2H2JAA3U.js.map → chunk-SSLQXHNX.js.map} +0 -0
- /package/dist/{core-DKHB7FYV.js.map → core-SKRPJQZG.js.map} +0 -0
- /package/dist/{generate-KL24VZVD.js.map → generate-7AF7WRVK.js.map} +0 -0
- /package/dist/{init-NION5S3M.js.map → init-WKGDPYI4.js.map} +0 -0
- /package/dist/{scan-ESEXV7LF.js.map → scan-K6JNMCGM.js.map} +0 -0
- /package/dist/{service-RWUMZ3EW.js.map → service-F3E4JJM7.js.map} +0 -0
- /package/dist/{static-viewer-O37MJ5B6.js.map → static-viewer-4LQZ5AGA.js.map} +0 -0
- /package/dist/{test-ECPEXFDN.js.map → test-CJDNJTPZ.js.map} +0 -0
- /package/dist/{tokens-ITADYVPF.js.map → tokens-JAJABYXP.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRequire } from 'module'; const require =
|
|
1
|
+
import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
|
|
2
2
|
|
|
3
3
|
// src/core/constants.ts
|
|
4
4
|
var BRAND = {
|
|
@@ -152,7 +152,9 @@ var relationshipTypeSchema = z.enum([
|
|
|
152
152
|
"sibling",
|
|
153
153
|
"parent",
|
|
154
154
|
"child",
|
|
155
|
-
"composition"
|
|
155
|
+
"composition",
|
|
156
|
+
"complementary",
|
|
157
|
+
"used-by"
|
|
156
158
|
]);
|
|
157
159
|
var componentRelationSchema = z.object({
|
|
158
160
|
component: z.string().min(1),
|
|
@@ -244,4 +246,4 @@ export {
|
|
|
244
246
|
segmentsConfigSchema,
|
|
245
247
|
recipeDefinitionSchema
|
|
246
248
|
};
|
|
247
|
-
//# sourceMappingURL=chunk-
|
|
249
|
+
//# sourceMappingURL=chunk-6JBGU74P.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/constants.ts","../src/core/schema.ts"],"sourcesContent":["/**\n * Brand constants for easy rebranding if domain availability requires it.\n * All naming throughout the codebase should reference these constants.\n */\nexport const BRAND = {\n /** Display name (e.g., \"Fragments\") */\n name: \"Fragments\",\n\n /** Lowercase name for file paths and CLI (e.g., \"fragments\") */\n nameLower: \"fragments\",\n\n /** File extension for fragment definition files (e.g., \".fragment.tsx\") */\n fileExtension: \".fragment.tsx\",\n\n /** Legacy file extension for segments (still supported for migration) */\n legacyFileExtension: \".segment.tsx\",\n\n /** JSON file extension for compiled output */\n jsonExtension: \".fragment.json\",\n\n /** Default output file name (e.g., \"fragments.json\") */\n outFile: \"fragments.json\",\n\n /** Config file name (e.g., \"fragments.config.ts\") */\n configFile: \"fragments.config.ts\",\n\n /** Legacy config file name (still supported for migration) */\n legacyConfigFile: \"segments.config.ts\",\n\n /** CLI command name (e.g., \"fragments\") */\n cliCommand: \"fragments\",\n\n /** Package scope (e.g., \"@fragments\") */\n packageScope: \"@fragments\",\n\n /** Directory for storing fragments, registry, and cache */\n dataDir: \".fragments\",\n\n /** Components subdirectory within .fragments/ */\n componentsDir: \"components\",\n\n /** Registry file name */\n registryFile: \"registry.json\",\n\n /** Context file name (AI-ready markdown) */\n contextFile: \"context.md\",\n\n /** Screenshots subdirectory */\n screenshotsDir: \"screenshots\",\n\n /** Cache subdirectory (gitignored) */\n cacheDir: \"cache\",\n\n /** Diff output subdirectory (gitignored) */\n diffDir: \"diff\",\n\n /** Manifest filename */\n manifestFile: \"manifest.json\",\n\n /** Prefix for localStorage keys (e.g., \"fragments-\") */\n storagePrefix: \"fragments-\",\n\n /** Static viewer HTML file name */\n viewerHtmlFile: \"fragments-viewer.html\",\n\n /** MCP tool name prefix (e.g., \"fragments_\") */\n mcpToolPrefix: \"fragments_\",\n\n /** File extension for block definition files */\n blockFileExtension: \".block.ts\",\n\n /** @deprecated Use blockFileExtension instead */\n recipeFileExtension: \".recipe.ts\",\n\n /** Vite plugin namespace */\n vitePluginNamespace: \"fragments-core-shim\",\n} as const;\n\nexport type Brand = typeof BRAND;\n\n/**\n * Default configuration values for the service.\n * These can be overridden in fragments.config.ts\n */\nexport const DEFAULTS = {\n /** Default viewport dimensions */\n viewport: {\n width: 1280,\n height: 800,\n },\n\n /** Default diff threshold (percentage) */\n diffThreshold: 5,\n\n /** Browser pool size */\n poolSize: 3,\n\n /** Idle timeout before browser shutdown (ms) - 5 minutes */\n idleTimeoutMs: 5 * 60 * 1000,\n\n /** Delay after render before capture (ms) */\n captureDelayMs: 100,\n\n /** Font loading timeout (ms) */\n fontTimeoutMs: 3000,\n\n /** Default theme */\n theme: \"light\" as const,\n\n /** Dev server port */\n port: 6006,\n} as const;\n\nexport type Defaults = typeof DEFAULTS;\n","import { z } from 'zod';\n\n/**\n * Zod schemas for runtime validation of segment definitions\n */\n\n// Figma property mapping schemas\nconst figmaStringMappingSchema = z.object({\n __type: z.literal('figma-string'),\n figmaProperty: z.string().min(1),\n});\n\nconst figmaBooleanMappingSchema = z.object({\n __type: z.literal('figma-boolean'),\n figmaProperty: z.string().min(1),\n valueMapping: z.object({ true: z.unknown(), false: z.unknown() }).optional(),\n});\n\nconst figmaEnumMappingSchema = z.object({\n __type: z.literal('figma-enum'),\n figmaProperty: z.string().min(1),\n valueMapping: z.record(z.unknown()),\n});\n\nconst figmaInstanceMappingSchema = z.object({\n __type: z.literal('figma-instance'),\n figmaProperty: z.string().min(1),\n});\n\nconst figmaChildrenMappingSchema = z.object({\n __type: z.literal('figma-children'),\n layers: z.array(z.string().min(1)),\n});\n\nconst figmaTextContentMappingSchema = z.object({\n __type: z.literal('figma-text-content'),\n layer: z.string().min(1),\n});\n\nexport const figmaPropMappingSchema = z.discriminatedUnion('__type', [\n figmaStringMappingSchema,\n figmaBooleanMappingSchema,\n figmaEnumMappingSchema,\n figmaInstanceMappingSchema,\n figmaChildrenMappingSchema,\n figmaTextContentMappingSchema,\n]);\n\nexport const segmentMetaSchema = z.object({\n name: z.string().min(1),\n description: z.string().min(1),\n category: z.string().min(1),\n tags: z.array(z.string()).optional(),\n status: z.enum(['stable', 'beta', 'deprecated', 'experimental']).optional(),\n since: z.string().optional(),\n figma: z.string().url().optional(),\n figmaProps: z.record(figmaPropMappingSchema).optional(),\n});\n\nexport const segmentUsageSchema = z.object({\n when: z.array(z.string()).min(1),\n whenNot: z.array(z.string()).min(1),\n guidelines: z.array(z.string()).optional(),\n accessibility: z.array(z.string()).optional(),\n});\n\nexport const propTypeSchema: z.ZodType<string> = z.enum([\n 'string',\n 'number',\n 'boolean',\n 'enum',\n 'function',\n 'node',\n 'element',\n 'object',\n 'array',\n 'union',\n 'custom',\n]);\n\nexport const propDefinitionSchema = z.object({\n type: propTypeSchema,\n values: z.array(z.string()).readonly().optional(),\n default: z.unknown().optional(),\n description: z.string().optional(),\n required: z.boolean().optional(),\n constraints: z.array(z.string()).optional(),\n typeDetails: z.record(z.unknown()).optional(),\n});\n\nexport const relationshipTypeSchema = z.enum([\n 'alternative',\n 'sibling',\n 'parent',\n 'child',\n 'composition',\n 'complementary',\n 'used-by',\n]);\n\nexport const componentRelationSchema = z.object({\n component: z.string().min(1),\n relationship: relationshipTypeSchema,\n note: z.string().min(1),\n});\n\nexport const segmentVariantSchema = z.object({\n name: z.string().min(1),\n description: z.string().min(1),\n render: z.function().returns(z.unknown()),\n code: z.string().optional(),\n figma: z.string().url().optional(),\n});\n\n/**\n * Schema for banned patterns in codebase\n */\nexport const segmentBanSchema = z.object({\n pattern: z.string().min(1),\n message: z.string().min(1),\n});\n\n/**\n * Schema for agent-optimized contract metadata\n */\nexport const segmentContractSchema = z.object({\n propsSummary: z.array(z.string()).optional(),\n a11yRules: z.array(z.string()).optional(),\n bans: z.array(segmentBanSchema).optional(),\n scenarioTags: z.array(z.string()).optional(),\n});\n\n/**\n * Schema for provenance tracking of generated segments\n */\nexport const segmentGeneratedSchema = z.object({\n source: z.enum(['storybook', 'manual', 'ai']),\n sourceFile: z.string().optional(),\n confidence: z.number().min(0).max(1).optional(),\n timestamp: z.string().datetime().optional(),\n});\n\n/**\n * Schema for AI-specific metadata for playground context generation\n */\nexport const aiMetadataSchema = z.object({\n compositionPattern: z.enum(['compound', 'simple', 'controlled']).optional(),\n subComponents: z.array(z.string()).optional(),\n requiredChildren: z.array(z.string()).optional(),\n commonPatterns: z.array(z.string()).optional(),\n});\n\n/**\n * Schema for block definitions\n */\nexport const blockDefinitionSchema = z.object({\n name: z.string().min(1),\n description: z.string().min(1),\n category: z.string().min(1),\n components: z.array(z.string().min(1)).min(1),\n code: z.string().min(1),\n tags: z.array(z.string()).optional(),\n});\n\nexport const segmentDefinitionSchema = z.object({\n component: z.any(), // Allow any component type (function, class, forwardRef, etc.)\n meta: segmentMetaSchema,\n usage: segmentUsageSchema,\n props: z.record(propDefinitionSchema),\n relations: z.array(componentRelationSchema).optional(),\n variants: z.array(segmentVariantSchema), // Allow empty variants array\n contract: segmentContractSchema.optional(),\n ai: aiMetadataSchema.optional(),\n _generated: segmentGeneratedSchema.optional(),\n});\n\n/**\n * Config schema - validates required fields, passes through optional config objects.\n * Type definitions are in types.ts - schema just ensures basic structure.\n */\nexport const segmentsConfigSchema = z.object({\n include: z.array(z.string()).min(1),\n exclude: z.array(z.string()).optional(),\n components: z.array(z.string()).optional(),\n outFile: z.string().optional(),\n framework: z.enum(['react', 'vue', 'svelte']).optional(),\n figmaFile: z.string().url().optional(),\n figmaToken: z.string().optional(),\n screenshots: z.object({}).passthrough().optional(),\n service: z.object({}).passthrough().optional(),\n registry: z.object({}).passthrough().optional(),\n tokens: z.object({\n include: z.array(z.string()).min(1),\n }).passthrough().optional(),\n});\n\n/**\n * @deprecated Use blockDefinitionSchema instead\n */\nexport const recipeDefinitionSchema = blockDefinitionSchema;\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRequire } from 'module'; const require =
|
|
1
|
+
import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
BrowserPool,
|
|
4
4
|
CaptureEngine,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
formatMs,
|
|
9
9
|
generateHtmlReport,
|
|
10
10
|
getGrade
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-NWQ4CJOQ.js";
|
|
12
12
|
import {
|
|
13
13
|
discoverBlockFiles,
|
|
14
14
|
discoverComponentFiles,
|
|
@@ -19,16 +19,16 @@ import {
|
|
|
19
19
|
generateRegistry,
|
|
20
20
|
loadSegmentFile,
|
|
21
21
|
parseSegmentFile
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-SSLQXHNX.js";
|
|
23
23
|
import {
|
|
24
24
|
compileBlock,
|
|
25
25
|
parseTokenFile
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-Q7GOHVOK.js";
|
|
27
27
|
import {
|
|
28
28
|
BRAND,
|
|
29
29
|
DEFAULTS,
|
|
30
30
|
segmentDefinitionSchema
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-6JBGU74P.js";
|
|
32
32
|
|
|
33
33
|
// src/validators.ts
|
|
34
34
|
async function validateSchema(config, configDir) {
|
|
@@ -120,8 +120,350 @@ async function validateAll(config, configDir) {
|
|
|
120
120
|
|
|
121
121
|
// src/build.ts
|
|
122
122
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
123
|
-
import { resolve, join } from "path";
|
|
124
|
-
import { existsSync } from "fs";
|
|
123
|
+
import { resolve as resolve2, join as join2 } from "path";
|
|
124
|
+
import { existsSync as existsSync2 } from "fs";
|
|
125
|
+
|
|
126
|
+
// src/core/auto-props.ts
|
|
127
|
+
import { existsSync, statSync } from "fs";
|
|
128
|
+
import { dirname, extname, join, resolve } from "path";
|
|
129
|
+
import ts from "typescript";
|
|
130
|
+
function toPosixPath(filePath) {
|
|
131
|
+
return filePath.replace(/\\/g, "/");
|
|
132
|
+
}
|
|
133
|
+
function isFile(filePath) {
|
|
134
|
+
if (!existsSync(filePath)) return false;
|
|
135
|
+
try {
|
|
136
|
+
return statSync(filePath).isFile();
|
|
137
|
+
} catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function resolveModulePath(basePath) {
|
|
142
|
+
const candidates = [];
|
|
143
|
+
const extension = extname(basePath);
|
|
144
|
+
if (extension) {
|
|
145
|
+
candidates.push(basePath);
|
|
146
|
+
} else {
|
|
147
|
+
candidates.push(
|
|
148
|
+
`${basePath}.tsx`,
|
|
149
|
+
`${basePath}.ts`,
|
|
150
|
+
`${basePath}.jsx`,
|
|
151
|
+
`${basePath}.js`,
|
|
152
|
+
join(basePath, "index.tsx"),
|
|
153
|
+
join(basePath, "index.ts"),
|
|
154
|
+
join(basePath, "index.jsx"),
|
|
155
|
+
join(basePath, "index.js")
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
for (const candidate of candidates) {
|
|
159
|
+
if (isFile(candidate)) {
|
|
160
|
+
return resolve(candidate);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
function resolveComponentSourcePath(segmentFileAbsolutePath, componentImportPath) {
|
|
166
|
+
if (!componentImportPath) return null;
|
|
167
|
+
if (!componentImportPath.startsWith(".")) return null;
|
|
168
|
+
const segmentDir = dirname(segmentFileAbsolutePath);
|
|
169
|
+
const basePath = resolve(segmentDir, componentImportPath);
|
|
170
|
+
return resolveModulePath(basePath);
|
|
171
|
+
}
|
|
172
|
+
function collectTopLevelDeclarations(sourceFile) {
|
|
173
|
+
const typeDeclarations = /* @__PURE__ */ new Map();
|
|
174
|
+
const functionDeclarations = /* @__PURE__ */ new Map();
|
|
175
|
+
const variableDeclarations = /* @__PURE__ */ new Map();
|
|
176
|
+
for (const node of sourceFile.statements) {
|
|
177
|
+
if (ts.isInterfaceDeclaration(node)) {
|
|
178
|
+
typeDeclarations.set(node.name.text, node);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (ts.isTypeAliasDeclaration(node)) {
|
|
182
|
+
typeDeclarations.set(node.name.text, node);
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
186
|
+
functionDeclarations.set(node.name.text, node);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (ts.isVariableStatement(node)) {
|
|
190
|
+
for (const declaration of node.declarationList.declarations) {
|
|
191
|
+
if (ts.isIdentifier(declaration.name)) {
|
|
192
|
+
variableDeclarations.set(declaration.name.text, declaration);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return { typeDeclarations, functionDeclarations, variableDeclarations };
|
|
198
|
+
}
|
|
199
|
+
function readDefaultValue(expression) {
|
|
200
|
+
if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) {
|
|
201
|
+
return expression.text;
|
|
202
|
+
}
|
|
203
|
+
if (ts.isNumericLiteral(expression)) {
|
|
204
|
+
return Number(expression.text);
|
|
205
|
+
}
|
|
206
|
+
if (expression.kind === ts.SyntaxKind.TrueKeyword) return true;
|
|
207
|
+
if (expression.kind === ts.SyntaxKind.FalseKeyword) return false;
|
|
208
|
+
if (expression.kind === ts.SyntaxKind.NullKeyword) return null;
|
|
209
|
+
if (ts.isPrefixUnaryExpression(expression) && expression.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(expression.operand)) {
|
|
210
|
+
return -Number(expression.operand.text);
|
|
211
|
+
}
|
|
212
|
+
return void 0;
|
|
213
|
+
}
|
|
214
|
+
function extractDefaultValues(componentNode) {
|
|
215
|
+
const defaults = {};
|
|
216
|
+
if (!componentNode?.parameters?.length) return defaults;
|
|
217
|
+
const firstParam = componentNode.parameters[0];
|
|
218
|
+
if (!ts.isObjectBindingPattern(firstParam.name)) return defaults;
|
|
219
|
+
for (const element of firstParam.name.elements) {
|
|
220
|
+
let propName = null;
|
|
221
|
+
if (element.propertyName) {
|
|
222
|
+
if (ts.isIdentifier(element.propertyName) || ts.isStringLiteral(element.propertyName)) {
|
|
223
|
+
propName = element.propertyName.text;
|
|
224
|
+
}
|
|
225
|
+
} else if (ts.isIdentifier(element.name)) {
|
|
226
|
+
propName = element.name.text;
|
|
227
|
+
}
|
|
228
|
+
if (!propName || !element.initializer) continue;
|
|
229
|
+
const value = readDefaultValue(element.initializer);
|
|
230
|
+
if (value !== void 0) {
|
|
231
|
+
defaults[propName] = value;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return defaults;
|
|
235
|
+
}
|
|
236
|
+
function isNullishType(type) {
|
|
237
|
+
return (type.flags & ts.TypeFlags.Null) !== 0 || (type.flags & ts.TypeFlags.Undefined) !== 0 || (type.flags & ts.TypeFlags.Void) !== 0;
|
|
238
|
+
}
|
|
239
|
+
function isBooleanLikeType(type) {
|
|
240
|
+
return (type.flags & ts.TypeFlags.BooleanLike) !== 0 || type.flags === ts.TypeFlags.BooleanLiteral;
|
|
241
|
+
}
|
|
242
|
+
function inferPropType(type, checker) {
|
|
243
|
+
const typeText = checker.typeToString(type, void 0, ts.TypeFormatFlags.NoTruncation);
|
|
244
|
+
if (typeText.includes("ReactNode")) {
|
|
245
|
+
return { type: "node" };
|
|
246
|
+
}
|
|
247
|
+
if (typeText.includes("ReactElement") || typeText.includes("JSX.Element")) {
|
|
248
|
+
return { type: "element" };
|
|
249
|
+
}
|
|
250
|
+
if (type.getCallSignatures().length > 0) {
|
|
251
|
+
return { type: "function" };
|
|
252
|
+
}
|
|
253
|
+
if (checker.isArrayType(type) || checker.isTupleType(type)) {
|
|
254
|
+
return { type: "array" };
|
|
255
|
+
}
|
|
256
|
+
if (type.isUnion()) {
|
|
257
|
+
const nonNullableTypes = type.types.filter((unionType) => !isNullishType(unionType));
|
|
258
|
+
if (nonNullableTypes.length === 1) {
|
|
259
|
+
return inferPropType(nonNullableTypes[0], checker);
|
|
260
|
+
}
|
|
261
|
+
const stringLiteralValues = nonNullableTypes.filter((unionType) => (unionType.flags & ts.TypeFlags.StringLiteral) !== 0).map((unionType) => unionType.value);
|
|
262
|
+
if (stringLiteralValues.length > 0 && stringLiteralValues.length === nonNullableTypes.length) {
|
|
263
|
+
return { type: "enum", values: stringLiteralValues };
|
|
264
|
+
}
|
|
265
|
+
if (nonNullableTypes.every((unionType) => isBooleanLikeType(unionType))) {
|
|
266
|
+
return { type: "boolean" };
|
|
267
|
+
}
|
|
268
|
+
return { type: "union" };
|
|
269
|
+
}
|
|
270
|
+
if ((type.flags & ts.TypeFlags.StringLike) !== 0) {
|
|
271
|
+
return { type: "string" };
|
|
272
|
+
}
|
|
273
|
+
if ((type.flags & ts.TypeFlags.NumberLike) !== 0) {
|
|
274
|
+
return { type: "number" };
|
|
275
|
+
}
|
|
276
|
+
if ((type.flags & ts.TypeFlags.BooleanLike) !== 0) {
|
|
277
|
+
return { type: "boolean" };
|
|
278
|
+
}
|
|
279
|
+
if ((type.flags & ts.TypeFlags.Object) !== 0) {
|
|
280
|
+
return { type: "object" };
|
|
281
|
+
}
|
|
282
|
+
return { type: "custom" };
|
|
283
|
+
}
|
|
284
|
+
function resolveComponentSignature(exportName, declarations, sourceFile) {
|
|
285
|
+
const visitedNames = /* @__PURE__ */ new Set();
|
|
286
|
+
const typeNodeFromFunction = (node) => ({
|
|
287
|
+
propsTypeNode: node.parameters[0]?.type ?? null,
|
|
288
|
+
componentNode: node
|
|
289
|
+
});
|
|
290
|
+
const resolveFromExpression = (expression) => {
|
|
291
|
+
if (ts.isParenthesizedExpression(expression)) {
|
|
292
|
+
return resolveFromExpression(expression.expression);
|
|
293
|
+
}
|
|
294
|
+
if (ts.isAsExpression(expression) || ts.isTypeAssertionExpression(expression)) {
|
|
295
|
+
return resolveFromExpression(expression.expression);
|
|
296
|
+
}
|
|
297
|
+
if (ts.isArrowFunction(expression) || ts.isFunctionExpression(expression)) {
|
|
298
|
+
return typeNodeFromFunction(expression);
|
|
299
|
+
}
|
|
300
|
+
if (ts.isIdentifier(expression)) {
|
|
301
|
+
return resolveFromIdentifier(expression.text);
|
|
302
|
+
}
|
|
303
|
+
if (ts.isCallExpression(expression)) {
|
|
304
|
+
if (ts.isPropertyAccessExpression(expression.expression) && expression.expression.name.text === "forwardRef") {
|
|
305
|
+
const forwardRefPropsType = expression.typeArguments?.[1] ?? null;
|
|
306
|
+
const innerArg = expression.arguments[0];
|
|
307
|
+
const inner = innerArg && (ts.isArrowFunction(innerArg) || ts.isFunctionExpression(innerArg)) ? typeNodeFromFunction(innerArg) : innerArg && ts.isIdentifier(innerArg) ? resolveFromIdentifier(innerArg.text) : { propsTypeNode: null, componentNode: null };
|
|
308
|
+
return {
|
|
309
|
+
propsTypeNode: forwardRefPropsType ?? inner.propsTypeNode,
|
|
310
|
+
componentNode: inner.componentNode
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
if (ts.isPropertyAccessExpression(expression.expression) && expression.expression.name.text === "memo" && expression.arguments[0]) {
|
|
314
|
+
return resolveFromExpression(expression.arguments[0]);
|
|
315
|
+
}
|
|
316
|
+
if (ts.isPropertyAccessExpression(expression.expression) && expression.expression.expression.getText(sourceFile) === "Object" && expression.expression.name.text === "assign" && expression.arguments[0]) {
|
|
317
|
+
return resolveFromExpression(expression.arguments[0]);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return { propsTypeNode: null, componentNode: null };
|
|
321
|
+
};
|
|
322
|
+
const resolveFromVariable = (declaration) => {
|
|
323
|
+
if (declaration.type && ts.isTypeReferenceNode(declaration.type) && declaration.type.typeArguments?.length) {
|
|
324
|
+
const typeName = declaration.type.typeName.getText(sourceFile);
|
|
325
|
+
if (typeName.includes("FC") || typeName.includes("FunctionComponent")) {
|
|
326
|
+
const componentNode = declaration.initializer && (ts.isArrowFunction(declaration.initializer) || ts.isFunctionExpression(declaration.initializer)) ? declaration.initializer : null;
|
|
327
|
+
return {
|
|
328
|
+
propsTypeNode: declaration.type.typeArguments[0] ?? null,
|
|
329
|
+
componentNode
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (declaration.initializer) {
|
|
334
|
+
return resolveFromExpression(declaration.initializer);
|
|
335
|
+
}
|
|
336
|
+
return { propsTypeNode: null, componentNode: null };
|
|
337
|
+
};
|
|
338
|
+
const resolveFromIdentifier = (name) => {
|
|
339
|
+
if (!name || visitedNames.has(name)) {
|
|
340
|
+
return { propsTypeNode: null, componentNode: null };
|
|
341
|
+
}
|
|
342
|
+
visitedNames.add(name);
|
|
343
|
+
const functionDeclaration = declarations.functionDeclarations.get(name);
|
|
344
|
+
if (functionDeclaration) {
|
|
345
|
+
return typeNodeFromFunction(functionDeclaration);
|
|
346
|
+
}
|
|
347
|
+
const variableDeclaration = declarations.variableDeclarations.get(name);
|
|
348
|
+
if (variableDeclaration) {
|
|
349
|
+
return resolveFromVariable(variableDeclaration);
|
|
350
|
+
}
|
|
351
|
+
return { propsTypeNode: null, componentNode: null };
|
|
352
|
+
};
|
|
353
|
+
return resolveFromIdentifier(exportName);
|
|
354
|
+
}
|
|
355
|
+
function extractCustomPropsFromComponentFile(componentFilePath, exportName) {
|
|
356
|
+
const warnings = [];
|
|
357
|
+
const resolvedPath = resolve(componentFilePath);
|
|
358
|
+
if (!existsSync(resolvedPath)) {
|
|
359
|
+
return {
|
|
360
|
+
props: {},
|
|
361
|
+
warnings: [`Component file not found: ${resolvedPath}`],
|
|
362
|
+
resolved: false
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
const compilerOptions = {
|
|
366
|
+
target: ts.ScriptTarget.ESNext,
|
|
367
|
+
module: ts.ModuleKind.ESNext,
|
|
368
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
369
|
+
jsx: ts.JsxEmit.ReactJSX,
|
|
370
|
+
allowSyntheticDefaultImports: true,
|
|
371
|
+
esModuleInterop: true,
|
|
372
|
+
skipLibCheck: true,
|
|
373
|
+
strict: false,
|
|
374
|
+
noEmit: true
|
|
375
|
+
};
|
|
376
|
+
const program = ts.createProgram([resolvedPath], compilerOptions);
|
|
377
|
+
const sourceFile = program.getSourceFile(resolvedPath);
|
|
378
|
+
if (!sourceFile) {
|
|
379
|
+
return {
|
|
380
|
+
props: {},
|
|
381
|
+
warnings: [`Unable to parse component source: ${resolvedPath}`],
|
|
382
|
+
resolved: false
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
const checker = program.getTypeChecker();
|
|
386
|
+
const declarations = collectTopLevelDeclarations(sourceFile);
|
|
387
|
+
const signature = resolveComponentSignature(exportName, declarations, sourceFile);
|
|
388
|
+
if (!signature.propsTypeNode) {
|
|
389
|
+
return {
|
|
390
|
+
props: {},
|
|
391
|
+
warnings: [`Unable to resolve props type for export: ${exportName}`],
|
|
392
|
+
resolved: false
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
const propsType = checker.getTypeFromTypeNode(signature.propsTypeNode);
|
|
396
|
+
const defaultValues = extractDefaultValues(signature.componentNode);
|
|
397
|
+
const sourceFilePath = toPosixPath(sourceFile.fileName);
|
|
398
|
+
const extractedProps = {};
|
|
399
|
+
for (const symbol of checker.getPropertiesOfType(propsType)) {
|
|
400
|
+
const propName = symbol.getName();
|
|
401
|
+
if (propName.startsWith("_") || propName.startsWith("$")) {
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
const declarationsForSymbol = symbol.getDeclarations() ?? [];
|
|
405
|
+
const localDeclarations = declarationsForSymbol.filter(
|
|
406
|
+
(declaration) => toPosixPath(declaration.getSourceFile().fileName) === sourceFilePath
|
|
407
|
+
);
|
|
408
|
+
if (localDeclarations.length === 0) {
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
const referenceNode = localDeclarations[0];
|
|
412
|
+
const inferredType = inferPropType(checker.getTypeOfSymbolAtLocation(symbol, referenceNode), checker);
|
|
413
|
+
const description = ts.displayPartsToString(symbol.getDocumentationComment(checker)).trim();
|
|
414
|
+
extractedProps[propName] = {
|
|
415
|
+
type: inferredType.type,
|
|
416
|
+
description,
|
|
417
|
+
required: (symbol.getFlags() & ts.SymbolFlags.Optional) === 0,
|
|
418
|
+
...inferredType.values && { values: inferredType.values },
|
|
419
|
+
...defaultValues[propName] !== void 0 && { default: defaultValues[propName] }
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
if (Object.keys(extractedProps).length === 0) {
|
|
423
|
+
warnings.push(`Resolved props type for ${exportName}, but no local custom props were found`);
|
|
424
|
+
}
|
|
425
|
+
return {
|
|
426
|
+
props: extractedProps,
|
|
427
|
+
warnings,
|
|
428
|
+
resolved: true
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// src/build.ts
|
|
433
|
+
function normalizeParsedProps(parsedProps) {
|
|
434
|
+
return Object.fromEntries(
|
|
435
|
+
Object.entries(parsedProps).map(([name, prop]) => [
|
|
436
|
+
name,
|
|
437
|
+
{
|
|
438
|
+
type: prop.type ?? "custom",
|
|
439
|
+
description: prop.description ?? "",
|
|
440
|
+
default: prop.default,
|
|
441
|
+
required: prop.required,
|
|
442
|
+
values: prop.values,
|
|
443
|
+
constraints: prop.constraints
|
|
444
|
+
}
|
|
445
|
+
])
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
function mergeDocumentedAndAutoProps(documentedProps, autoProps) {
|
|
449
|
+
return Object.fromEntries(
|
|
450
|
+
Object.keys(autoProps).map((name) => {
|
|
451
|
+
const documented = documentedProps[name];
|
|
452
|
+
const auto = autoProps[name];
|
|
453
|
+
return [
|
|
454
|
+
name,
|
|
455
|
+
{
|
|
456
|
+
type: auto.type,
|
|
457
|
+
description: documented?.description ?? auto.description ?? "",
|
|
458
|
+
default: auto.default !== void 0 ? auto.default : documented?.default,
|
|
459
|
+
required: auto.required,
|
|
460
|
+
values: auto.values ?? documented?.values,
|
|
461
|
+
constraints: documented?.constraints
|
|
462
|
+
}
|
|
463
|
+
];
|
|
464
|
+
})
|
|
465
|
+
);
|
|
466
|
+
}
|
|
125
467
|
async function buildSegments(config, configDir) {
|
|
126
468
|
const files = await discoverSegmentFiles(config, configDir);
|
|
127
469
|
const errors = [];
|
|
@@ -141,6 +483,53 @@ async function buildSegments(config, configDir) {
|
|
|
141
483
|
});
|
|
142
484
|
continue;
|
|
143
485
|
}
|
|
486
|
+
const documentedProps = normalizeParsedProps(parsed.props);
|
|
487
|
+
let mergedProps = documentedProps;
|
|
488
|
+
const componentExportName = parsed.componentName ?? parsed.meta.name;
|
|
489
|
+
const componentSourcePath = resolveComponentSourcePath(
|
|
490
|
+
file.absolutePath,
|
|
491
|
+
parsed.componentImport
|
|
492
|
+
);
|
|
493
|
+
if (componentExportName && componentSourcePath) {
|
|
494
|
+
const autoPropsResult = extractCustomPropsFromComponentFile(
|
|
495
|
+
componentSourcePath,
|
|
496
|
+
componentExportName
|
|
497
|
+
);
|
|
498
|
+
for (const warning of autoPropsResult.warnings) {
|
|
499
|
+
warnings.push({ file: file.relativePath, warning });
|
|
500
|
+
}
|
|
501
|
+
const hasAutoProps = Object.keys(autoPropsResult.props).length > 0;
|
|
502
|
+
if (autoPropsResult.resolved && hasAutoProps) {
|
|
503
|
+
const removedDocumentedProps = Object.keys(documentedProps).filter(
|
|
504
|
+
(propName) => !(propName in autoPropsResult.props)
|
|
505
|
+
);
|
|
506
|
+
if (removedDocumentedProps.length > 0) {
|
|
507
|
+
warnings.push({
|
|
508
|
+
file: file.relativePath,
|
|
509
|
+
warning: `Removed ${removedDocumentedProps.length} documented props not present in source API: ${removedDocumentedProps.join(", ")}`
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
mergedProps = mergeDocumentedAndAutoProps(
|
|
513
|
+
documentedProps,
|
|
514
|
+
autoPropsResult.props
|
|
515
|
+
);
|
|
516
|
+
} else if (autoPropsResult.resolved && !hasAutoProps && Object.keys(documentedProps).length > 0) {
|
|
517
|
+
warnings.push({
|
|
518
|
+
file: file.relativePath,
|
|
519
|
+
warning: "Auto-props extraction returned no custom props; falling back to documented props"
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
} else if (!componentExportName) {
|
|
523
|
+
warnings.push({
|
|
524
|
+
file: file.relativePath,
|
|
525
|
+
warning: "Unable to resolve component export name for auto-props extraction"
|
|
526
|
+
});
|
|
527
|
+
} else if (!componentSourcePath) {
|
|
528
|
+
warnings.push({
|
|
529
|
+
file: file.relativePath,
|
|
530
|
+
warning: `Unable to resolve component source path from import: ${parsed.componentImport ?? "unknown"}`
|
|
531
|
+
});
|
|
532
|
+
}
|
|
144
533
|
const compiled = {
|
|
145
534
|
filePath: file.relativePath,
|
|
146
535
|
meta: {
|
|
@@ -158,19 +547,7 @@ async function buildSegments(config, configDir) {
|
|
|
158
547
|
guidelines: parsed.usage.guidelines,
|
|
159
548
|
accessibility: parsed.usage.accessibility
|
|
160
549
|
},
|
|
161
|
-
props:
|
|
162
|
-
Object.entries(parsed.props).map(([name, prop]) => [
|
|
163
|
-
name,
|
|
164
|
-
{
|
|
165
|
-
type: prop.type ?? "custom",
|
|
166
|
-
description: prop.description ?? "",
|
|
167
|
-
default: prop.default,
|
|
168
|
-
required: prop.required,
|
|
169
|
-
values: prop.values,
|
|
170
|
-
constraints: prop.constraints
|
|
171
|
-
}
|
|
172
|
-
])
|
|
173
|
-
),
|
|
550
|
+
props: mergedProps,
|
|
174
551
|
relations: parsed.relations.map((rel) => ({
|
|
175
552
|
component: rel.component,
|
|
176
553
|
relationship: rel.relationship,
|
|
@@ -248,8 +625,8 @@ async function buildSegments(config, configDir) {
|
|
|
248
625
|
} catch {
|
|
249
626
|
}
|
|
250
627
|
let packageName;
|
|
251
|
-
const pkgJsonPath =
|
|
252
|
-
if (
|
|
628
|
+
const pkgJsonPath = resolve2(configDir, "package.json");
|
|
629
|
+
if (existsSync2(pkgJsonPath)) {
|
|
253
630
|
try {
|
|
254
631
|
const pkg = JSON.parse(await readFile(pkgJsonPath, "utf-8"));
|
|
255
632
|
if (pkg.name) packageName = pkg.name;
|
|
@@ -264,7 +641,7 @@ async function buildSegments(config, configDir) {
|
|
|
264
641
|
...Object.keys(blocks).length > 0 && { blocks },
|
|
265
642
|
...tokens && { tokens }
|
|
266
643
|
};
|
|
267
|
-
const outputPath =
|
|
644
|
+
const outputPath = resolve2(configDir, config.outFile ?? BRAND.outFile);
|
|
268
645
|
await writeFile(outputPath, JSON.stringify(output));
|
|
269
646
|
return {
|
|
270
647
|
success: errors.length === 0,
|
|
@@ -275,8 +652,8 @@ async function buildSegments(config, configDir) {
|
|
|
275
652
|
};
|
|
276
653
|
}
|
|
277
654
|
async function buildFragmentsDir(config, configDir) {
|
|
278
|
-
const fragmentsDir =
|
|
279
|
-
const componentsDir =
|
|
655
|
+
const fragmentsDir = join2(configDir, BRAND.dataDir);
|
|
656
|
+
const componentsDir = join2(fragmentsDir, BRAND.componentsDir);
|
|
280
657
|
await mkdir(fragmentsDir, { recursive: true });
|
|
281
658
|
await mkdir(componentsDir, { recursive: true });
|
|
282
659
|
const registryResult = await generateRegistry({
|
|
@@ -288,9 +665,9 @@ async function buildFragmentsDir(config, configDir) {
|
|
|
288
665
|
});
|
|
289
666
|
const errors = [...registryResult.errors];
|
|
290
667
|
const warnings = [...registryResult.warnings];
|
|
291
|
-
const indexPath =
|
|
668
|
+
const indexPath = join2(fragmentsDir, "index.json");
|
|
292
669
|
await writeFile(indexPath, JSON.stringify(registryResult.index, null, 2));
|
|
293
|
-
const registryPath =
|
|
670
|
+
const registryPath = join2(fragmentsDir, BRAND.registryFile);
|
|
294
671
|
await writeFile(registryPath, JSON.stringify(registryResult.registry, null, 2));
|
|
295
672
|
const contextResult = generateContextMd(registryResult.registry, {
|
|
296
673
|
format: "markdown",
|
|
@@ -302,7 +679,7 @@ async function buildFragmentsDir(config, configDir) {
|
|
|
302
679
|
code: false
|
|
303
680
|
}
|
|
304
681
|
});
|
|
305
|
-
const contextPath =
|
|
682
|
+
const contextPath = join2(fragmentsDir, BRAND.contextFile);
|
|
306
683
|
await writeFile(contextPath, contextResult.content);
|
|
307
684
|
return {
|
|
308
685
|
success: errors.length === 0,
|
|
@@ -655,9 +1032,9 @@ ${BRAND.name} Diff
|
|
|
655
1032
|
}
|
|
656
1033
|
|
|
657
1034
|
// src/analyze.ts
|
|
658
|
-
import { existsSync as
|
|
1035
|
+
import { existsSync as existsSync3 } from "fs";
|
|
659
1036
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
660
|
-
import { join as
|
|
1037
|
+
import { join as join3, dirname as dirname2 } from "path";
|
|
661
1038
|
import pc3 from "picocolors";
|
|
662
1039
|
async function runAnalyzeCommand(config, configDir, options = {}) {
|
|
663
1040
|
const format = options.format ?? "html";
|
|
@@ -665,8 +1042,8 @@ async function runAnalyzeCommand(config, configDir, options = {}) {
|
|
|
665
1042
|
console.log(pc3.cyan(`
|
|
666
1043
|
${BRAND.name} Analyzer
|
|
667
1044
|
`));
|
|
668
|
-
const segmentsPath =
|
|
669
|
-
if (!
|
|
1045
|
+
const segmentsPath = join3(configDir, config.outFile ?? "segments.json");
|
|
1046
|
+
if (!existsSync3(segmentsPath)) {
|
|
670
1047
|
console.log(pc3.red(`\u2717 No segments.json found. Run \`${BRAND.cliCommand} build\` first.
|
|
671
1048
|
`));
|
|
672
1049
|
return {
|
|
@@ -682,7 +1059,7 @@ ${BRAND.name} Analyzer
|
|
|
682
1059
|
let outputPath;
|
|
683
1060
|
if (format === "html" || format === "json") {
|
|
684
1061
|
outputPath = options.output ?? getDefaultOutputPath(format, configDir);
|
|
685
|
-
await mkdir2(
|
|
1062
|
+
await mkdir2(dirname2(outputPath), { recursive: true });
|
|
686
1063
|
if (format === "html") {
|
|
687
1064
|
const html = generateHtmlReport(analytics);
|
|
688
1065
|
await writeFile2(outputPath, html);
|
|
@@ -761,7 +1138,7 @@ function colorizeScore(score) {
|
|
|
761
1138
|
}
|
|
762
1139
|
function getDefaultOutputPath(format, configDir) {
|
|
763
1140
|
const filename = format === "html" ? "segments-report.html" : "segments-report.json";
|
|
764
|
-
return
|
|
1141
|
+
return join3(configDir, filename);
|
|
765
1142
|
}
|
|
766
1143
|
async function openInBrowser(path) {
|
|
767
1144
|
const { platform } = await import("os");
|
|
@@ -829,4 +1206,4 @@ export {
|
|
|
829
1206
|
runDiffCommand,
|
|
830
1207
|
runAnalyzeCommand
|
|
831
1208
|
};
|
|
832
|
-
//# sourceMappingURL=chunk-
|
|
1209
|
+
//# sourceMappingURL=chunk-D35RGPAG.js.map
|