@fragments-sdk/cli 0.2.2
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/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +4783 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk-4FDQSGKX.js +786 -0
- package/dist/chunk-4FDQSGKX.js.map +1 -0
- package/dist/chunk-7H2MMGYG.js +369 -0
- package/dist/chunk-7H2MMGYG.js.map +1 -0
- package/dist/chunk-BSCG3IP7.js +619 -0
- package/dist/chunk-BSCG3IP7.js.map +1 -0
- package/dist/chunk-LY2CFFPY.js +898 -0
- package/dist/chunk-LY2CFFPY.js.map +1 -0
- package/dist/chunk-MUZ6CM66.js +6636 -0
- package/dist/chunk-MUZ6CM66.js.map +1 -0
- package/dist/chunk-OAENNG3G.js +1489 -0
- package/dist/chunk-OAENNG3G.js.map +1 -0
- package/dist/chunk-XHNKNI6J.js +235 -0
- package/dist/chunk-XHNKNI6J.js.map +1 -0
- package/dist/core-DWKLGY4N.js +68 -0
- package/dist/core-DWKLGY4N.js.map +1 -0
- package/dist/generate-4LQNJ7SX.js +249 -0
- package/dist/generate-4LQNJ7SX.js.map +1 -0
- package/dist/index.d.ts +775 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/init-EMVI47QG.js +416 -0
- package/dist/init-EMVI47QG.js.map +1 -0
- package/dist/mcp-bin.d.ts +1 -0
- package/dist/mcp-bin.js +1117 -0
- package/dist/mcp-bin.js.map +1 -0
- package/dist/scan-4YPRF7FV.js +12 -0
- package/dist/scan-4YPRF7FV.js.map +1 -0
- package/dist/service-QSZMZJBJ.js +208 -0
- package/dist/service-QSZMZJBJ.js.map +1 -0
- package/dist/static-viewer-MIPGZ4Z7.js +12 -0
- package/dist/static-viewer-MIPGZ4Z7.js.map +1 -0
- package/dist/test-SQ5ZHXWU.js +1067 -0
- package/dist/test-SQ5ZHXWU.js.map +1 -0
- package/dist/tokens-HSGMYK64.js +173 -0
- package/dist/tokens-HSGMYK64.js.map +1 -0
- package/dist/viewer-YRF4SQE4.js +11101 -0
- package/dist/viewer-YRF4SQE4.js.map +1 -0
- package/package.json +107 -0
- package/src/ai.ts +266 -0
- package/src/analyze.ts +265 -0
- package/src/bin.ts +916 -0
- package/src/build.ts +248 -0
- package/src/commands/a11y.ts +302 -0
- package/src/commands/add.ts +313 -0
- package/src/commands/audit.ts +195 -0
- package/src/commands/baseline.ts +221 -0
- package/src/commands/build.ts +144 -0
- package/src/commands/compare.ts +337 -0
- package/src/commands/context.ts +107 -0
- package/src/commands/dev.ts +107 -0
- package/src/commands/enhance.ts +858 -0
- package/src/commands/generate.ts +391 -0
- package/src/commands/init.ts +531 -0
- package/src/commands/link/figma.ts +645 -0
- package/src/commands/link/index.ts +10 -0
- package/src/commands/link/storybook.ts +267 -0
- package/src/commands/list.ts +49 -0
- package/src/commands/metrics.ts +114 -0
- package/src/commands/reset.ts +242 -0
- package/src/commands/scan.ts +537 -0
- package/src/commands/storygen.ts +207 -0
- package/src/commands/tokens.ts +251 -0
- package/src/commands/validate.ts +93 -0
- package/src/commands/verify.ts +215 -0
- package/src/core/composition.test.ts +262 -0
- package/src/core/composition.ts +255 -0
- package/src/core/config.ts +84 -0
- package/src/core/constants.ts +111 -0
- package/src/core/context.ts +380 -0
- package/src/core/defineSegment.ts +137 -0
- package/src/core/discovery.ts +337 -0
- package/src/core/figma.ts +263 -0
- package/src/core/fragment-types.ts +214 -0
- package/src/core/generators/context.ts +389 -0
- package/src/core/generators/index.ts +23 -0
- package/src/core/generators/registry.ts +364 -0
- package/src/core/generators/typescript-extractor.ts +374 -0
- package/src/core/importAnalyzer.ts +217 -0
- package/src/core/index.ts +149 -0
- package/src/core/loader.ts +155 -0
- package/src/core/node.ts +63 -0
- package/src/core/parser.ts +551 -0
- package/src/core/previewLoader.ts +172 -0
- package/src/core/schema/fragment.schema.json +189 -0
- package/src/core/schema/registry.schema.json +137 -0
- package/src/core/schema.ts +182 -0
- package/src/core/storyAdapter.test.ts +571 -0
- package/src/core/storyAdapter.ts +761 -0
- package/src/core/token-types.ts +287 -0
- package/src/core/types.ts +754 -0
- package/src/diff.ts +323 -0
- package/src/index.ts +43 -0
- package/src/mcp/__tests__/projectFields.test.ts +130 -0
- package/src/mcp/bin.ts +36 -0
- package/src/mcp/index.ts +8 -0
- package/src/mcp/server.ts +1310 -0
- package/src/mcp/utils.ts +54 -0
- package/src/mcp-bin.ts +36 -0
- package/src/migrate/__tests__/argTypes/argTypes.test.ts +189 -0
- package/src/migrate/__tests__/args/args.test.ts +452 -0
- package/src/migrate/__tests__/meta/meta.test.ts +198 -0
- package/src/migrate/__tests__/stories/stories.test.ts +278 -0
- package/src/migrate/__tests__/utils/utils.test.ts +371 -0
- package/src/migrate/__tests__/values/values.test.ts +303 -0
- package/src/migrate/bin.ts +108 -0
- package/src/migrate/converter.ts +658 -0
- package/src/migrate/detect.ts +196 -0
- package/src/migrate/index.ts +45 -0
- package/src/migrate/migrate.ts +163 -0
- package/src/migrate/parser.ts +1136 -0
- package/src/migrate/report.ts +624 -0
- package/src/migrate/types.ts +169 -0
- package/src/screenshot.ts +249 -0
- package/src/service/__tests__/ast-utils.test.ts +426 -0
- package/src/service/__tests__/enhance-scanner.test.ts +200 -0
- package/src/service/__tests__/figma/figma.test.ts +652 -0
- package/src/service/__tests__/metrics-store.test.ts +409 -0
- package/src/service/__tests__/patch-generator.test.ts +186 -0
- package/src/service/__tests__/props-extractor.test.ts +365 -0
- package/src/service/__tests__/token-registry.test.ts +267 -0
- package/src/service/analytics.ts +659 -0
- package/src/service/ast-utils.ts +444 -0
- package/src/service/browser-pool.ts +339 -0
- package/src/service/capture.ts +267 -0
- package/src/service/diff.ts +279 -0
- package/src/service/enhance/aggregator.ts +489 -0
- package/src/service/enhance/cache.ts +275 -0
- package/src/service/enhance/codebase-scanner.ts +357 -0
- package/src/service/enhance/context-generator.ts +529 -0
- package/src/service/enhance/doc-extractor.ts +523 -0
- package/src/service/enhance/index.ts +131 -0
- package/src/service/enhance/props-extractor.ts +665 -0
- package/src/service/enhance/scanner.ts +445 -0
- package/src/service/enhance/storybook-parser.ts +552 -0
- package/src/service/enhance/types.ts +346 -0
- package/src/service/enhance/variant-renderer.ts +479 -0
- package/src/service/figma.ts +1008 -0
- package/src/service/index.ts +249 -0
- package/src/service/metrics-store.ts +333 -0
- package/src/service/patch-generator.ts +349 -0
- package/src/service/report.ts +854 -0
- package/src/service/storage.ts +401 -0
- package/src/service/token-fixes.ts +281 -0
- package/src/service/token-parser.ts +504 -0
- package/src/service/token-registry.ts +721 -0
- package/src/service/utils.ts +172 -0
- package/src/setup.ts +241 -0
- package/src/shared/command-wrapper.ts +81 -0
- package/src/shared/dev-server-client.ts +199 -0
- package/src/shared/index.ts +8 -0
- package/src/shared/segment-loader.ts +59 -0
- package/src/shared/types.ts +147 -0
- package/src/static-viewer.ts +715 -0
- package/src/test/discovery.ts +172 -0
- package/src/test/index.ts +281 -0
- package/src/test/reporters/console.ts +194 -0
- package/src/test/reporters/json.ts +190 -0
- package/src/test/reporters/junit.ts +186 -0
- package/src/test/runner.ts +598 -0
- package/src/test/types.ts +245 -0
- package/src/test/watch.ts +200 -0
- package/src/validators.ts +152 -0
- package/src/viewer/__tests__/jsx-parser.test.ts +502 -0
- package/src/viewer/__tests__/render-utils.test.ts +232 -0
- package/src/viewer/__tests__/style-utils.test.ts +404 -0
- package/src/viewer/bin.ts +86 -0
- package/src/viewer/cli/health.ts +256 -0
- package/src/viewer/cli/index.ts +33 -0
- package/src/viewer/cli/scan.ts +124 -0
- package/src/viewer/cli/utils.ts +174 -0
- package/src/viewer/components/AccessibilityPanel.tsx +1404 -0
- package/src/viewer/components/ActionCapture.tsx +172 -0
- package/src/viewer/components/ActionsPanel.tsx +371 -0
- package/src/viewer/components/App.tsx +638 -0
- package/src/viewer/components/BottomPanel.tsx +224 -0
- package/src/viewer/components/CodePanel.tsx +589 -0
- package/src/viewer/components/CommandPalette.tsx +336 -0
- package/src/viewer/components/ComponentGraph.tsx +394 -0
- package/src/viewer/components/ComponentHeader.tsx +85 -0
- package/src/viewer/components/ContractPanel.tsx +234 -0
- package/src/viewer/components/ErrorBoundary.tsx +85 -0
- package/src/viewer/components/FigmaEmbed.tsx +231 -0
- package/src/viewer/components/FragmentEditor.tsx +485 -0
- package/src/viewer/components/HealthDashboard.tsx +452 -0
- package/src/viewer/components/HmrStatusIndicator.tsx +71 -0
- package/src/viewer/components/Icons.tsx +417 -0
- package/src/viewer/components/InteractionsPanel.tsx +720 -0
- package/src/viewer/components/IsolatedPreviewFrame.tsx +321 -0
- package/src/viewer/components/IsolatedRender.tsx +111 -0
- package/src/viewer/components/KeyboardShortcutsHelp.tsx +89 -0
- package/src/viewer/components/LandingPage.tsx +441 -0
- package/src/viewer/components/Layout.tsx +22 -0
- package/src/viewer/components/LeftSidebar.tsx +391 -0
- package/src/viewer/components/MultiViewportPreview.tsx +429 -0
- package/src/viewer/components/PreviewArea.tsx +404 -0
- package/src/viewer/components/PreviewFrameHost.tsx +310 -0
- package/src/viewer/components/PreviewPane.tsx +150 -0
- package/src/viewer/components/PreviewToolbar.tsx +176 -0
- package/src/viewer/components/PropsEditor.tsx +512 -0
- package/src/viewer/components/PropsTable.tsx +98 -0
- package/src/viewer/components/RelationsSection.tsx +57 -0
- package/src/viewer/components/ResizablePanel.tsx +328 -0
- package/src/viewer/components/RightSidebar.tsx +118 -0
- package/src/viewer/components/ScreenshotButton.tsx +90 -0
- package/src/viewer/components/Sidebar.tsx +169 -0
- package/src/viewer/components/SkeletonLoader.tsx +156 -0
- package/src/viewer/components/StoryRenderer.tsx +128 -0
- package/src/viewer/components/ThemeProvider.tsx +96 -0
- package/src/viewer/components/Toast.tsx +67 -0
- package/src/viewer/components/TokenStylePanel.tsx +708 -0
- package/src/viewer/components/UsageSection.tsx +95 -0
- package/src/viewer/components/VariantMatrix.tsx +350 -0
- package/src/viewer/components/VariantRenderer.tsx +131 -0
- package/src/viewer/components/VariantTabs.tsx +84 -0
- package/src/viewer/components/ViewportSelector.tsx +165 -0
- package/src/viewer/components/_future/CreatePage.tsx +836 -0
- package/src/viewer/composition-renderer.ts +381 -0
- package/src/viewer/constants/index.ts +1 -0
- package/src/viewer/constants/ui.ts +185 -0
- package/src/viewer/entry.tsx +299 -0
- package/src/viewer/hooks/index.ts +2 -0
- package/src/viewer/hooks/useA11yCache.ts +383 -0
- package/src/viewer/hooks/useA11yService.ts +498 -0
- package/src/viewer/hooks/useActions.ts +138 -0
- package/src/viewer/hooks/useAppState.ts +124 -0
- package/src/viewer/hooks/useFigmaIntegration.ts +132 -0
- package/src/viewer/hooks/useHmrStatus.ts +109 -0
- package/src/viewer/hooks/useKeyboardShortcuts.ts +222 -0
- package/src/viewer/hooks/usePreviewBridge.ts +347 -0
- package/src/viewer/hooks/useScrollSpy.ts +78 -0
- package/src/viewer/hooks/useUrlState.ts +330 -0
- package/src/viewer/hooks/useViewSettings.ts +125 -0
- package/src/viewer/index.html +28 -0
- package/src/viewer/index.ts +14 -0
- package/src/viewer/intelligence/healthReport.ts +505 -0
- package/src/viewer/intelligence/styleDrift.ts +340 -0
- package/src/viewer/intelligence/usageScanner.ts +309 -0
- package/src/viewer/jsx-parser.ts +485 -0
- package/src/viewer/postcss.config.js +6 -0
- package/src/viewer/preview-frame-entry.tsx +25 -0
- package/src/viewer/preview-frame.html +109 -0
- package/src/viewer/render-template.html +68 -0
- package/src/viewer/render-utils.ts +170 -0
- package/src/viewer/server.ts +276 -0
- package/src/viewer/style-utils.ts +414 -0
- package/src/viewer/styles/globals.css +355 -0
- package/src/viewer/tailwind.config.js +37 -0
- package/src/viewer/types/a11y.ts +197 -0
- package/src/viewer/utils/a11y-fixes.ts +471 -0
- package/src/viewer/utils/actionExport.ts +372 -0
- package/src/viewer/utils/colorSchemes.ts +201 -0
- package/src/viewer/utils/detectRelationships.ts +256 -0
- package/src/viewer/vite-plugin.ts +2143 -0
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Context Generator
|
|
3
|
+
*
|
|
4
|
+
* Packages codebase analysis, documentation, and Storybook examples
|
|
5
|
+
* into structured context for AI-powered documentation generation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
ComponentAnalysis,
|
|
10
|
+
UsageAnalysis,
|
|
11
|
+
ExtractedDocs,
|
|
12
|
+
ComponentEnhancement,
|
|
13
|
+
} from "./types.js";
|
|
14
|
+
import type { ParsedStoryFile, StoryExample } from "./storybook-parser.js";
|
|
15
|
+
import type { PropsExtractionResult, ExtractedProp } from "./props-extractor.js";
|
|
16
|
+
import { summarizePatternsForPrompt, type ComponentRelation } from "./aggregator.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Boilerplate patterns that should be filtered from AI suggestions
|
|
20
|
+
*/
|
|
21
|
+
const BOILERPLATE_PATTERNS = [
|
|
22
|
+
/component is needed/i,
|
|
23
|
+
/alternative.*appropriate/i,
|
|
24
|
+
/use (?:this|the) component when/i,
|
|
25
|
+
/don'?t use (?:this|the) component/i,
|
|
26
|
+
/when you need (?:this|a|the) component/i,
|
|
27
|
+
/TODO:/i,
|
|
28
|
+
/FIXME:/i,
|
|
29
|
+
/TBD/i,
|
|
30
|
+
/placeholder/i,
|
|
31
|
+
/\[.*\]/, // Placeholder brackets like [describe when]
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check if text matches any boilerplate pattern
|
|
36
|
+
*/
|
|
37
|
+
export function isBoilerplate(text: string): boolean {
|
|
38
|
+
return BOILERPLATE_PATTERNS.some((pattern) => pattern.test(text));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Filter out boilerplate suggestions
|
|
43
|
+
*/
|
|
44
|
+
export function filterBoilerplate(suggestions: string[]): string[] {
|
|
45
|
+
return suggestions.filter((s) => !isBoilerplate(s));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Enhanced prop data from TypeScript extraction
|
|
50
|
+
*/
|
|
51
|
+
export interface EnhancedProp {
|
|
52
|
+
name: string;
|
|
53
|
+
type: string;
|
|
54
|
+
description: string;
|
|
55
|
+
required: boolean;
|
|
56
|
+
defaultValue?: unknown;
|
|
57
|
+
enumValues?: string[];
|
|
58
|
+
deprecated?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Full context for AI enhancement of a single component
|
|
63
|
+
*/
|
|
64
|
+
export interface ComponentContext {
|
|
65
|
+
componentName: string;
|
|
66
|
+
sourceFile: string;
|
|
67
|
+
|
|
68
|
+
// Existing documentation
|
|
69
|
+
existingDocs: {
|
|
70
|
+
description?: string;
|
|
71
|
+
props: Array<{
|
|
72
|
+
name: string;
|
|
73
|
+
type: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
required: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
examples: string[];
|
|
78
|
+
tags: Record<string, string>;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Enhanced props from TypeScript extraction
|
|
82
|
+
extractedProps?: EnhancedProp[];
|
|
83
|
+
|
|
84
|
+
// Component relationships inferred from usage patterns
|
|
85
|
+
relations?: Array<{
|
|
86
|
+
component: string;
|
|
87
|
+
relationship: "parent" | "sibling" | "child";
|
|
88
|
+
frequency: number;
|
|
89
|
+
}>;
|
|
90
|
+
|
|
91
|
+
// Usage analysis
|
|
92
|
+
usageAnalysis: {
|
|
93
|
+
totalUsages: number;
|
|
94
|
+
uniqueFiles: number;
|
|
95
|
+
topPatterns: Array<{
|
|
96
|
+
props: Record<string, unknown>;
|
|
97
|
+
count: number;
|
|
98
|
+
sampleContext?: string;
|
|
99
|
+
}>;
|
|
100
|
+
contexts: Array<{
|
|
101
|
+
type: string;
|
|
102
|
+
count: number;
|
|
103
|
+
}>;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Storybook examples
|
|
107
|
+
storybook?: {
|
|
108
|
+
title?: string;
|
|
109
|
+
description?: string;
|
|
110
|
+
stories: Array<{
|
|
111
|
+
name: string;
|
|
112
|
+
displayName: string;
|
|
113
|
+
description?: string;
|
|
114
|
+
args: Record<string, unknown>;
|
|
115
|
+
code: string;
|
|
116
|
+
}>;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Full context package for AI enhancement session
|
|
122
|
+
*/
|
|
123
|
+
export interface AIContextPackage {
|
|
124
|
+
projectName: string;
|
|
125
|
+
totalComponents: number;
|
|
126
|
+
components: ComponentContext[];
|
|
127
|
+
globalPatterns: {
|
|
128
|
+
mostUsedComponents: Array<{ name: string; usages: number }>;
|
|
129
|
+
commonPropCombinations: Array<{ props: string[]; count: number }>;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Generate full context for a single component
|
|
135
|
+
*/
|
|
136
|
+
export function generateComponentContext(
|
|
137
|
+
componentName: string,
|
|
138
|
+
analysis: ComponentAnalysis | undefined,
|
|
139
|
+
docs: ExtractedDocs | undefined,
|
|
140
|
+
storyFile: ParsedStoryFile | undefined,
|
|
141
|
+
propsExtraction?: PropsExtractionResult,
|
|
142
|
+
relations?: ComponentRelation[]
|
|
143
|
+
): ComponentContext {
|
|
144
|
+
const context: ComponentContext = {
|
|
145
|
+
componentName,
|
|
146
|
+
sourceFile: analysis?.sourceFile || propsExtraction?.filePath || docs?.filePath || "unknown",
|
|
147
|
+
existingDocs: {
|
|
148
|
+
description: docs?.description,
|
|
149
|
+
props: docs?.props || [],
|
|
150
|
+
examples: docs?.examples || [],
|
|
151
|
+
tags: docs?.tags || {},
|
|
152
|
+
},
|
|
153
|
+
usageAnalysis: {
|
|
154
|
+
totalUsages: analysis?.totalUsages || 0,
|
|
155
|
+
uniqueFiles: analysis?.uniqueFiles || 0,
|
|
156
|
+
topPatterns: [],
|
|
157
|
+
contexts: [],
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// Add enhanced props from TypeScript extraction (preferred source)
|
|
162
|
+
if (propsExtraction?.success && propsExtraction.props.length > 0) {
|
|
163
|
+
context.extractedProps = propsExtraction.props.map((p) => ({
|
|
164
|
+
name: p.name,
|
|
165
|
+
type: p.type,
|
|
166
|
+
description: p.description,
|
|
167
|
+
required: p.required,
|
|
168
|
+
defaultValue: p.defaultValue,
|
|
169
|
+
enumValues: p.enumValues,
|
|
170
|
+
deprecated: p.deprecated,
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Add inferred relations
|
|
175
|
+
if (relations && relations.length > 0) {
|
|
176
|
+
context.relations = relations.slice(0, 10).map((r) => ({
|
|
177
|
+
component: r.component,
|
|
178
|
+
relationship: r.relationship,
|
|
179
|
+
frequency: r.frequency,
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Add usage patterns
|
|
184
|
+
if (analysis?.patterns) {
|
|
185
|
+
context.usageAnalysis.topPatterns = analysis.patterns.slice(0, 10).map((p) => ({
|
|
186
|
+
props: p.props,
|
|
187
|
+
count: p.count,
|
|
188
|
+
sampleContext: p.sampleContexts[0],
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Add context types
|
|
193
|
+
if (analysis?.contexts) {
|
|
194
|
+
context.usageAnalysis.contexts = analysis.contexts.map((c) => ({
|
|
195
|
+
type: c.type,
|
|
196
|
+
count: c.count,
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Add Storybook data
|
|
201
|
+
if (storyFile) {
|
|
202
|
+
context.storybook = {
|
|
203
|
+
title: storyFile.meta.title,
|
|
204
|
+
description: storyFile.meta.description,
|
|
205
|
+
stories: storyFile.stories.map((s) => ({
|
|
206
|
+
name: s.name,
|
|
207
|
+
displayName: s.displayName,
|
|
208
|
+
description: s.description,
|
|
209
|
+
args: s.args,
|
|
210
|
+
code: s.code,
|
|
211
|
+
})),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return context;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Generate full AI context package for all components
|
|
220
|
+
*/
|
|
221
|
+
export function generateAIContextPackage(
|
|
222
|
+
projectName: string,
|
|
223
|
+
usageAnalysis: UsageAnalysis,
|
|
224
|
+
allDocs: Map<string, ExtractedDocs>,
|
|
225
|
+
allStories: Map<string, ParsedStoryFile>
|
|
226
|
+
): AIContextPackage {
|
|
227
|
+
const components: ComponentContext[] = [];
|
|
228
|
+
|
|
229
|
+
// Get all unique component names
|
|
230
|
+
const allComponentNames = new Set<string>();
|
|
231
|
+
for (const name of Object.keys(usageAnalysis.components)) {
|
|
232
|
+
allComponentNames.add(name);
|
|
233
|
+
}
|
|
234
|
+
for (const name of allDocs.keys()) {
|
|
235
|
+
allComponentNames.add(name);
|
|
236
|
+
}
|
|
237
|
+
for (const name of allStories.keys()) {
|
|
238
|
+
allComponentNames.add(name);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Generate context for each component
|
|
242
|
+
for (const componentName of allComponentNames) {
|
|
243
|
+
const analysis = usageAnalysis.components[componentName];
|
|
244
|
+
const docs = allDocs.get(componentName);
|
|
245
|
+
const storyFile = allStories.get(componentName);
|
|
246
|
+
|
|
247
|
+
const context = generateComponentContext(
|
|
248
|
+
componentName,
|
|
249
|
+
analysis,
|
|
250
|
+
docs,
|
|
251
|
+
storyFile
|
|
252
|
+
);
|
|
253
|
+
components.push(context);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Sort by usage count
|
|
257
|
+
components.sort(
|
|
258
|
+
(a, b) => b.usageAnalysis.totalUsages - a.usageAnalysis.totalUsages
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
// Calculate global patterns
|
|
262
|
+
const mostUsedComponents = Object.values(usageAnalysis.components)
|
|
263
|
+
.map((c) => ({ name: c.name, usages: c.totalUsages }))
|
|
264
|
+
.sort((a, b) => b.usages - a.usages)
|
|
265
|
+
.slice(0, 20);
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
projectName,
|
|
269
|
+
totalComponents: components.length,
|
|
270
|
+
components,
|
|
271
|
+
globalPatterns: {
|
|
272
|
+
mostUsedComponents,
|
|
273
|
+
commonPropCombinations: [], // Would need aggregation across all components
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Generate a focused prompt context for a single component
|
|
280
|
+
*/
|
|
281
|
+
export function generatePromptContext(context: ComponentContext): string {
|
|
282
|
+
const lines: string[] = [];
|
|
283
|
+
|
|
284
|
+
lines.push(`# Component: ${context.componentName}`);
|
|
285
|
+
lines.push(`Source: ${context.sourceFile}`);
|
|
286
|
+
lines.push("");
|
|
287
|
+
|
|
288
|
+
// Existing documentation
|
|
289
|
+
if (context.existingDocs.description) {
|
|
290
|
+
lines.push("## Current Description");
|
|
291
|
+
lines.push(context.existingDocs.description);
|
|
292
|
+
lines.push("");
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Enhanced props from TypeScript extraction (preferred)
|
|
296
|
+
if (context.extractedProps && context.extractedProps.length > 0) {
|
|
297
|
+
lines.push("## Props (from TypeScript)");
|
|
298
|
+
for (const prop of context.extractedProps) {
|
|
299
|
+
const required = prop.required ? "(required)" : "(optional)";
|
|
300
|
+
const deprecated = prop.deprecated ? " [DEPRECATED]" : "";
|
|
301
|
+
const defaultVal = prop.defaultValue !== undefined
|
|
302
|
+
? ` (default: ${JSON.stringify(prop.defaultValue)})`
|
|
303
|
+
: "";
|
|
304
|
+
const desc = prop.description || "";
|
|
305
|
+
|
|
306
|
+
lines.push(`- **${prop.name}**: \`${prop.type}\` ${required}${deprecated}${defaultVal}`);
|
|
307
|
+
if (desc) {
|
|
308
|
+
lines.push(` ${desc}`);
|
|
309
|
+
}
|
|
310
|
+
if (prop.enumValues && prop.enumValues.length > 0) {
|
|
311
|
+
lines.push(` Values: ${prop.enumValues.map(v => `"${v}"`).join(" | ")}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
lines.push("");
|
|
315
|
+
} else if (context.existingDocs.props.length > 0) {
|
|
316
|
+
// Fallback to existing docs props
|
|
317
|
+
lines.push("## Props");
|
|
318
|
+
for (const prop of context.existingDocs.props) {
|
|
319
|
+
const required = prop.required ? "(required)" : "(optional)";
|
|
320
|
+
const desc = prop.description || "No description";
|
|
321
|
+
lines.push(`- **${prop.name}**: \`${prop.type}\` ${required} - ${desc}`);
|
|
322
|
+
}
|
|
323
|
+
lines.push("");
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Component relationships
|
|
327
|
+
if (context.relations && context.relations.length > 0) {
|
|
328
|
+
lines.push("## Related Components");
|
|
329
|
+
const parents = context.relations.filter((r) => r.relationship === "parent");
|
|
330
|
+
const siblings = context.relations.filter((r) => r.relationship === "sibling");
|
|
331
|
+
|
|
332
|
+
if (parents.length > 0) {
|
|
333
|
+
lines.push("### Commonly Used Inside");
|
|
334
|
+
for (const rel of parents.slice(0, 5)) {
|
|
335
|
+
lines.push(`- **${rel.component}**: ${rel.frequency} times`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (siblings.length > 0) {
|
|
340
|
+
lines.push("### Often Used With");
|
|
341
|
+
for (const rel of siblings.slice(0, 5)) {
|
|
342
|
+
lines.push(`- **${rel.component}**: appears together in ${rel.frequency} files`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
lines.push("");
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Usage patterns
|
|
349
|
+
if (context.usageAnalysis.totalUsages > 0) {
|
|
350
|
+
lines.push("## Usage Analysis");
|
|
351
|
+
lines.push(
|
|
352
|
+
`Found ${context.usageAnalysis.totalUsages} usages across ${context.usageAnalysis.uniqueFiles} files.`
|
|
353
|
+
);
|
|
354
|
+
lines.push("");
|
|
355
|
+
|
|
356
|
+
if (context.usageAnalysis.topPatterns.length > 0) {
|
|
357
|
+
lines.push("### Most Common Patterns");
|
|
358
|
+
for (const pattern of context.usageAnalysis.topPatterns.slice(0, 5)) {
|
|
359
|
+
const propsStr =
|
|
360
|
+
Object.keys(pattern.props).length > 0
|
|
361
|
+
? Object.entries(pattern.props)
|
|
362
|
+
.map(([k, v]) => `${k}=${JSON.stringify(v)}`)
|
|
363
|
+
.join(", ")
|
|
364
|
+
: "(no props)";
|
|
365
|
+
lines.push(`- ${propsStr}: ${pattern.count} times`);
|
|
366
|
+
}
|
|
367
|
+
lines.push("");
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (context.usageAnalysis.contexts.length > 0) {
|
|
371
|
+
lines.push("### Where It's Used");
|
|
372
|
+
for (const ctx of context.usageAnalysis.contexts) {
|
|
373
|
+
lines.push(`- ${ctx.type}: ${ctx.count} times`);
|
|
374
|
+
}
|
|
375
|
+
lines.push("");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Sample code context
|
|
379
|
+
const samplePattern = context.usageAnalysis.topPatterns.find(
|
|
380
|
+
(p) => p.sampleContext
|
|
381
|
+
);
|
|
382
|
+
if (samplePattern?.sampleContext) {
|
|
383
|
+
lines.push("### Sample Usage Context");
|
|
384
|
+
lines.push("```tsx");
|
|
385
|
+
lines.push(samplePattern.sampleContext.trim());
|
|
386
|
+
lines.push("```");
|
|
387
|
+
lines.push("");
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Storybook examples
|
|
392
|
+
if (context.storybook && context.storybook.stories.length > 0) {
|
|
393
|
+
lines.push("## Storybook Examples");
|
|
394
|
+
for (const story of context.storybook.stories.slice(0, 5)) {
|
|
395
|
+
lines.push(`### ${story.displayName}`);
|
|
396
|
+
if (story.description) {
|
|
397
|
+
lines.push(story.description);
|
|
398
|
+
}
|
|
399
|
+
lines.push("```tsx");
|
|
400
|
+
lines.push(story.code);
|
|
401
|
+
lines.push("```");
|
|
402
|
+
lines.push("");
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return lines.join("\n");
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Generate enhancement suggestions based on context
|
|
411
|
+
*/
|
|
412
|
+
export function generateEnhancementSuggestions(
|
|
413
|
+
context: ComponentContext
|
|
414
|
+
): ComponentEnhancement {
|
|
415
|
+
const suggestions: ComponentEnhancement = {
|
|
416
|
+
componentName: context.componentName,
|
|
417
|
+
suggestions: {
|
|
418
|
+
when: [],
|
|
419
|
+
whenNot: [],
|
|
420
|
+
examples: [],
|
|
421
|
+
},
|
|
422
|
+
confidence: 0,
|
|
423
|
+
reasoning: [],
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
// Analyze context types to suggest "when" scenarios
|
|
427
|
+
if (context.usageAnalysis.contexts.length > 0) {
|
|
428
|
+
for (const ctx of context.usageAnalysis.contexts) {
|
|
429
|
+
if (ctx.count >= 2) {
|
|
430
|
+
suggestions.suggestions.when.push(
|
|
431
|
+
`Use in ${ctx.type} components (found in ${ctx.count} places)`
|
|
432
|
+
);
|
|
433
|
+
suggestions.reasoning.push(
|
|
434
|
+
`Component is commonly used in ${ctx.type} contexts`
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Analyze usage patterns
|
|
441
|
+
const highUsagePatterns = context.usageAnalysis.topPatterns.filter(
|
|
442
|
+
(p) => p.count >= 3
|
|
443
|
+
);
|
|
444
|
+
if (highUsagePatterns.length > 0) {
|
|
445
|
+
for (const pattern of highUsagePatterns.slice(0, 3)) {
|
|
446
|
+
const props = Object.entries(pattern.props);
|
|
447
|
+
if (props.length > 0) {
|
|
448
|
+
const propDesc = props.map(([k, v]) => `${k}="${v}"`).join(", ");
|
|
449
|
+
suggestions.suggestions.when.push(
|
|
450
|
+
`Use with ${propDesc} (common pattern, ${pattern.count} occurrences)`
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Generate examples from Storybook
|
|
457
|
+
if (context.storybook?.stories) {
|
|
458
|
+
for (const story of context.storybook.stories.slice(0, 3)) {
|
|
459
|
+
if (story.code) {
|
|
460
|
+
suggestions.suggestions.examples.push(story.code);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Calculate confidence based on available data
|
|
466
|
+
let confidence = 0;
|
|
467
|
+
if (context.usageAnalysis.totalUsages > 10) confidence += 30;
|
|
468
|
+
else if (context.usageAnalysis.totalUsages > 5) confidence += 20;
|
|
469
|
+
else if (context.usageAnalysis.totalUsages > 0) confidence += 10;
|
|
470
|
+
|
|
471
|
+
if (context.storybook?.stories && context.storybook.stories.length > 0) {
|
|
472
|
+
confidence += 25;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Enhanced props from TypeScript extraction are more valuable
|
|
476
|
+
if (context.extractedProps && context.extractedProps.length > 0) {
|
|
477
|
+
confidence += 25;
|
|
478
|
+
} else if (context.existingDocs.props.length > 0) {
|
|
479
|
+
confidence += 15;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (context.usageAnalysis.contexts.length > 0) {
|
|
483
|
+
confidence += 20;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
suggestions.confidence = Math.min(confidence, 100);
|
|
487
|
+
|
|
488
|
+
return suggestions;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Generate the system prompt for AI enhancement
|
|
493
|
+
*/
|
|
494
|
+
export function generateSystemPrompt(): string {
|
|
495
|
+
return `You are a technical writer specializing in React component documentation. Your task is to generate clear, actionable "when to use" and "when not to use" documentation based on actual usage patterns found in a codebase.
|
|
496
|
+
|
|
497
|
+
Guidelines:
|
|
498
|
+
1. Be specific and actionable - avoid vague statements
|
|
499
|
+
2. Base recommendations on observed usage patterns
|
|
500
|
+
3. Consider the contexts where components are used (forms, modals, tables, etc.)
|
|
501
|
+
4. Include concrete examples when available
|
|
502
|
+
5. Mention prop combinations that are commonly used together
|
|
503
|
+
6. Note any patterns that suggest best practices or anti-patterns
|
|
504
|
+
|
|
505
|
+
Format your response as JSON with this structure:
|
|
506
|
+
{
|
|
507
|
+
"when": ["scenario 1", "scenario 2", ...],
|
|
508
|
+
"whenNot": ["anti-pattern 1", "anti-pattern 2", ...],
|
|
509
|
+
"examples": ["<Component prop=\\"value\\" />", ...]
|
|
510
|
+
}`;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Generate the user prompt for a specific component
|
|
515
|
+
*/
|
|
516
|
+
export function generateUserPrompt(context: ComponentContext): string {
|
|
517
|
+
const promptContext = generatePromptContext(context);
|
|
518
|
+
|
|
519
|
+
return `Based on the following usage analysis, generate "when" and "whenNot" documentation for this component.
|
|
520
|
+
|
|
521
|
+
${promptContext}
|
|
522
|
+
|
|
523
|
+
Requirements:
|
|
524
|
+
1. Generate 2-4 "when" scenarios based on the actual usage patterns
|
|
525
|
+
2. Generate 1-3 "whenNot" scenarios (anti-patterns or inappropriate use cases)
|
|
526
|
+
3. Include 1-3 example code snippets showing common usage patterns
|
|
527
|
+
|
|
528
|
+
If there isn't enough usage data to make confident recommendations, indicate that in your response.`;
|
|
529
|
+
}
|