@tpitre/story-ui 2.6.1 ā 2.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/README.md +36 -37
- package/dist/cli/deploy.d.ts +4 -3
- package/dist/cli/deploy.d.ts.map +1 -1
- package/dist/cli/deploy.js +542 -46
- package/dist/cli/index.js +17 -14
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +4 -110
- package/dist/cli/setup.js.map +1 -0
- package/dist/cloudflare-edge/src/mcp-session.js +462 -0
- package/dist/cloudflare-edge/src/types.js +4 -0
- package/dist/cloudflare-edge/src/worker.js +106 -0
- package/dist/cloudflare-pages/vite.config.js +14 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/mcp-server/mcp-stdio-server.js.map +1 -0
- package/dist/mcp-server/routes/claude.js.map +1 -0
- package/dist/mcp-server/routes/components.js.map +1 -0
- package/dist/mcp-server/routes/generateStory.js.map +1 -0
- package/dist/mcp-server/routes/hybridStories.js.map +1 -0
- package/dist/mcp-server/routes/memoryStories.js.map +1 -0
- package/dist/mcp-server/routes/storySync.js.map +1 -0
- package/dist/mcp-server/routes/updateStory.js +246 -0
- package/dist/mcp-server/sessionManager.js.map +1 -0
- package/dist/playground/components/AIAssistant/AIAssistant.d.ts +6 -0
- package/dist/playground/components/AIAssistant/AIAssistant.d.ts.map +1 -0
- package/dist/playground/components/AIAssistant/AIAssistant.js +109 -0
- package/dist/playground/components/AIAssistant/AIAssistant.js.map +1 -0
- package/dist/playground/components/AIAssistant/AIAssistant.module.css +166 -0
- package/dist/playground/components/Canvas/Canvas.d.ts +9 -0
- package/dist/playground/components/Canvas/Canvas.d.ts.map +1 -0
- package/dist/playground/components/Canvas/Canvas.js +58 -0
- package/dist/playground/components/Canvas/Canvas.js.map +1 -0
- package/dist/playground/components/Canvas/Canvas.module.css +189 -0
- package/dist/playground/components/Canvas/CanvasWithDnd.d.ts +9 -0
- package/dist/playground/components/Canvas/CanvasWithDnd.d.ts.map +1 -0
- package/dist/playground/components/Canvas/CanvasWithDnd.js +158 -0
- package/dist/playground/components/Canvas/CanvasWithDnd.js.map +1 -0
- package/dist/playground/components/Canvas/ComponentRenderer.d.ts +15 -0
- package/dist/playground/components/Canvas/ComponentRenderer.d.ts.map +1 -0
- package/dist/playground/components/Canvas/ComponentRenderer.js +177 -0
- package/dist/playground/components/Canvas/ComponentRenderer.js.map +1 -0
- package/dist/playground/components/Canvas/DraggableComponent.d.ts +15 -0
- package/dist/playground/components/Canvas/DraggableComponent.d.ts.map +1 -0
- package/dist/playground/components/Canvas/DraggableComponent.js +49 -0
- package/dist/playground/components/Canvas/DraggableComponent.js.map +1 -0
- package/dist/playground/components/Canvas/index.d.ts +9 -0
- package/dist/playground/components/Canvas/index.d.ts.map +1 -0
- package/dist/playground/components/Canvas/index.js +5 -0
- package/dist/playground/components/Canvas/index.js.map +1 -0
- package/dist/playground/components/CodeView/CodeView.d.ts +12 -0
- package/dist/playground/components/CodeView/CodeView.d.ts.map +1 -0
- package/dist/playground/components/CodeView/CodeView.js +77 -0
- package/dist/playground/components/CodeView/CodeView.js.map +1 -0
- package/dist/playground/components/CodeView/CodeView.module.css +178 -0
- package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts +17 -0
- package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts.map +1 -0
- package/dist/playground/components/ComponentPalette/ComponentPalette.js +138 -0
- package/dist/playground/components/ComponentPalette/ComponentPalette.js.map +1 -0
- package/dist/playground/components/ComponentPalette/ComponentPalette.module.css +217 -0
- package/dist/playground/components/ComponentPalette/index.d.ts +3 -0
- package/dist/playground/components/ComponentPalette/index.d.ts.map +1 -0
- package/dist/playground/components/ComponentPalette/index.js +2 -0
- package/dist/playground/components/ComponentPalette/index.js.map +1 -0
- package/dist/playground/components/DropZone/DropZone.d.ts +17 -0
- package/dist/playground/components/DropZone/DropZone.d.ts.map +1 -0
- package/dist/playground/components/DropZone/DropZone.js +73 -0
- package/dist/playground/components/DropZone/DropZone.js.map +1 -0
- package/dist/playground/components/DropZone/DropZone.module.css +86 -0
- package/dist/playground/components/ExportDialog/ExportDialog.d.ts +10 -0
- package/dist/playground/components/ExportDialog/ExportDialog.d.ts.map +1 -0
- package/dist/playground/components/ExportDialog/ExportDialog.js +57 -0
- package/dist/playground/components/ExportDialog/ExportDialog.js.map +1 -0
- package/dist/playground/components/ExportDialog/ExportDialog.module.css +328 -0
- package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts +134 -0
- package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts.map +1 -0
- package/dist/playground/components/LayoutHelpers/LayoutHelpers.js +254 -0
- package/dist/playground/components/LayoutHelpers/LayoutHelpers.js.map +1 -0
- package/dist/playground/components/LayoutHelpers/index.d.ts +3 -0
- package/dist/playground/components/LayoutHelpers/index.d.ts.map +1 -0
- package/dist/playground/components/LayoutHelpers/index.js +2 -0
- package/dist/playground/components/LayoutHelpers/index.js.map +1 -0
- package/dist/playground/components/Playground/Playground.d.ts +10 -0
- package/dist/playground/components/Playground/Playground.d.ts.map +1 -0
- package/dist/playground/components/Playground/Playground.js +128 -0
- package/dist/playground/components/Playground/Playground.js.map +1 -0
- package/dist/playground/components/Playground/Playground.module.css +308 -0
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts +10 -0
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts.map +1 -0
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.js +150 -0
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.js.map +1 -0
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.module.css +155 -0
- package/dist/playground/components/PropertiesPanel/index.d.ts +3 -0
- package/dist/playground/components/PropertiesPanel/index.d.ts.map +1 -0
- package/dist/playground/components/PropertiesPanel/index.js +2 -0
- package/dist/playground/components/PropertiesPanel/index.js.map +1 -0
- package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts +12 -0
- package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts.map +1 -0
- package/dist/playground/components/PropertyEditors/BooleanEditor.js +14 -0
- package/dist/playground/components/PropertyEditors/BooleanEditor.js.map +1 -0
- package/dist/playground/components/PropertyEditors/ColorEditor.d.ts +12 -0
- package/dist/playground/components/PropertyEditors/ColorEditor.d.ts.map +1 -0
- package/dist/playground/components/PropertyEditors/ColorEditor.js +62 -0
- package/dist/playground/components/PropertyEditors/ColorEditor.js.map +1 -0
- package/dist/playground/components/PropertyEditors/IconEditor.d.ts +12 -0
- package/dist/playground/components/PropertyEditors/IconEditor.d.ts.map +1 -0
- package/dist/playground/components/PropertyEditors/IconEditor.js +123 -0
- package/dist/playground/components/PropertyEditors/IconEditor.js.map +1 -0
- package/dist/playground/components/PropertyEditors/NumberEditor.d.ts +15 -0
- package/dist/playground/components/PropertyEditors/NumberEditor.d.ts.map +1 -0
- package/dist/playground/components/PropertyEditors/NumberEditor.js +46 -0
- package/dist/playground/components/PropertyEditors/NumberEditor.js.map +1 -0
- package/dist/playground/components/PropertyEditors/PropertyEditors.module.css +432 -0
- package/dist/playground/components/PropertyEditors/SelectEditor.d.ts +19 -0
- package/dist/playground/components/PropertyEditors/SelectEditor.d.ts.map +1 -0
- package/dist/playground/components/PropertyEditors/SelectEditor.js +17 -0
- package/dist/playground/components/PropertyEditors/SelectEditor.js.map +1 -0
- package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts +19 -0
- package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts.map +1 -0
- package/dist/playground/components/PropertyEditors/SpacingEditor.js +162 -0
- package/dist/playground/components/PropertyEditors/SpacingEditor.js.map +1 -0
- package/dist/playground/components/PropertyEditors/SpacingEditor.module.css +214 -0
- package/dist/playground/components/PropertyEditors/TextEditor.d.ts +14 -0
- package/dist/playground/components/PropertyEditors/TextEditor.d.ts.map +1 -0
- package/dist/playground/components/PropertyEditors/TextEditor.js +38 -0
- package/dist/playground/components/PropertyEditors/TextEditor.js.map +1 -0
- package/dist/playground/components/PropertyEditors/TokenEditor.d.ts +23 -0
- package/dist/playground/components/PropertyEditors/TokenEditor.d.ts.map +1 -0
- package/dist/playground/components/PropertyEditors/TokenEditor.js +50 -0
- package/dist/playground/components/PropertyEditors/TokenEditor.js.map +1 -0
- package/dist/playground/components/PropertyEditors/index.d.ts +20 -0
- package/dist/playground/components/PropertyEditors/index.d.ts.map +1 -0
- package/dist/playground/components/PropertyEditors/index.js +12 -0
- package/dist/playground/components/PropertyEditors/index.js.map +1 -0
- package/dist/playground/components/TreeView/TreeView.d.ts +10 -0
- package/dist/playground/components/TreeView/TreeView.d.ts.map +1 -0
- package/dist/playground/components/TreeView/TreeView.js +146 -0
- package/dist/playground/components/TreeView/TreeView.js.map +1 -0
- package/dist/playground/components/TreeView/TreeView.module.css +214 -0
- package/dist/playground/components/TreeView/index.d.ts +3 -0
- package/dist/playground/components/TreeView/index.d.ts.map +1 -0
- package/dist/playground/components/TreeView/index.js +2 -0
- package/dist/playground/components/TreeView/index.js.map +1 -0
- package/dist/playground/config/propertyDefinitions.d.ts +73 -0
- package/dist/playground/config/propertyDefinitions.d.ts.map +1 -0
- package/dist/playground/config/propertyDefinitions.js +809 -0
- package/dist/playground/config/propertyDefinitions.js.map +1 -0
- package/dist/playground/hooks/useKeyboardShortcuts.d.ts +38 -0
- package/dist/playground/hooks/useKeyboardShortcuts.d.ts.map +1 -0
- package/dist/playground/hooks/useKeyboardShortcuts.js +191 -0
- package/dist/playground/hooks/useKeyboardShortcuts.js.map +1 -0
- package/dist/playground/index.d.ts +21 -0
- package/dist/playground/index.d.ts.map +1 -0
- package/dist/playground/index.js +23 -0
- package/dist/playground/index.js.map +1 -0
- package/dist/playground/services/CodeGenerator.d.ts +73 -0
- package/dist/playground/services/CodeGenerator.d.ts.map +1 -0
- package/dist/playground/services/CodeGenerator.js +359 -0
- package/dist/playground/services/CodeGenerator.js.map +1 -0
- package/dist/playground/services/DragDropManager.d.ts +95 -0
- package/dist/playground/services/DragDropManager.d.ts.map +1 -0
- package/dist/playground/services/DragDropManager.js +408 -0
- package/dist/playground/services/DragDropManager.js.map +1 -0
- package/dist/playground/services/StoryParser.d.ts +73 -0
- package/dist/playground/services/StoryParser.d.ts.map +1 -0
- package/dist/playground/services/StoryParser.js +419 -0
- package/dist/playground/services/StoryParser.js.map +1 -0
- package/dist/playground/store/playgroundStore.d.ts +86 -0
- package/dist/playground/store/playgroundStore.d.ts.map +1 -0
- package/dist/playground/store/playgroundStore.js +337 -0
- package/dist/playground/store/playgroundStore.js.map +1 -0
- package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts +13 -0
- package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts.map +1 -0
- package/dist/playground/stories/PlaygroundDragDrop.stories.js +227 -0
- package/dist/playground/stories/PlaygroundDragDrop.stories.js.map +1 -0
- package/dist/playground/stories/PlaygroundPhase4.stories.d.ts +13 -0
- package/dist/playground/stories/PlaygroundPhase4.stories.d.ts.map +1 -0
- package/dist/playground/stories/PlaygroundPhase4.stories.js +334 -0
- package/dist/playground/stories/PlaygroundPhase4.stories.js.map +1 -0
- package/dist/playground/stories/PlaygroundPhase5.stories.d.ts +14 -0
- package/dist/playground/stories/PlaygroundPhase5.stories.d.ts.map +1 -0
- package/dist/playground/stories/PlaygroundPhase5.stories.js +512 -0
- package/dist/playground/stories/PlaygroundPhase5.stories.js.map +1 -0
- package/dist/playground/stories/PlaygroundProperties.stories.d.ts +13 -0
- package/dist/playground/stories/PlaygroundProperties.stories.d.ts.map +1 -0
- package/dist/playground/stories/PlaygroundProperties.stories.js +342 -0
- package/dist/playground/stories/PlaygroundProperties.stories.js.map +1 -0
- package/dist/playground/types/index.d.ts +251 -0
- package/dist/playground/types/index.d.ts.map +1 -0
- package/dist/playground/types/index.js +5 -0
- package/dist/playground/types/index.js.map +1 -0
- package/dist/scripts/verify-framework-adapters.js +105 -0
- package/dist/story-generator/componentBlacklist.js.map +1 -0
- package/dist/story-generator/componentDiscovery.js.map +1 -0
- package/dist/story-generator/configLoader.js.map +1 -0
- package/dist/story-generator/considerationsLoader.js.map +1 -0
- package/dist/story-generator/documentation-sources.js.map +1 -0
- package/dist/story-generator/documentationLoader.js.map +1 -0
- package/dist/story-generator/dynamicPackageDiscovery.js.map +1 -0
- package/dist/story-generator/enhancedComponentDiscovery.d.ts.map +1 -1
- package/dist/story-generator/enhancedComponentDiscovery.js +4 -6
- package/dist/story-generator/enhancedComponentDiscovery.js.map +1 -0
- package/dist/story-generator/generateStory.js.map +1 -0
- package/dist/story-generator/gitignoreManager.js.map +1 -0
- package/dist/story-generator/inMemoryStoryService.js.map +1 -0
- package/dist/story-generator/llm-providers/settings-manager.js +4 -4
- package/dist/story-generator/logger.js.map +1 -0
- package/dist/story-generator/postProcessStory.js.map +1 -0
- package/dist/story-generator/productionGitignoreManager.d.ts.map +1 -1
- package/dist/story-generator/productionGitignoreManager.js +6 -0
- package/dist/story-generator/productionGitignoreManager.js.map +1 -0
- package/dist/story-generator/promptGenerator.js.map +1 -0
- package/dist/story-generator/providerPresets.d.ts +54 -0
- package/dist/story-generator/providerPresets.d.ts.map +1 -0
- package/dist/story-generator/providerPresets.js +214 -0
- package/dist/story-generator/storyHistory.js.map +1 -0
- package/dist/story-generator/storySync.js.map +1 -0
- package/dist/story-generator/storyTracker.js.map +1 -0
- package/dist/story-generator/storyValidator.js.map +1 -0
- package/dist/story-generator/test_validation.d.ts +2 -0
- package/dist/story-generator/test_validation.d.ts.map +1 -0
- package/dist/story-generator/test_validation.js +51 -0
- package/dist/story-generator/universalDesignSystemAdapter.js.map +1 -0
- package/dist/story-generator/urlRedirectService.js.map +1 -0
- package/dist/story-generator/validateStory.js.map +1 -0
- package/dist/story-ui.config.js.map +1 -0
- package/dist/story-ui.config.loader.d.ts +36 -0
- package/dist/story-ui.config.loader.d.ts.map +1 -0
- package/dist/story-ui.config.loader.js +205 -0
- package/dist/story-ui.config.loader.js.map +1 -0
- package/dist/temp/package/templates/StoryUI/StoryUIPanel.js +807 -0
- package/dist/temp/package/templates/StoryUI/StoryUIPanel.stories.js +37 -0
- package/dist/temp/package/templates/StoryUI/index.js +2 -0
- package/dist/templates/StoryUI/StoryUIPanel.js.map +1 -0
- package/dist/templates/StoryUI/StoryUIPanel.stories.js.map +1 -0
- package/dist/templates/StoryUI/index.js.map +1 -0
- package/dist/templates/StoryUI/manager.d.ts +14 -0
- package/dist/templates/StoryUI/manager.d.ts.map +1 -0
- package/dist/templates/production-app/src/App.d.ts +10 -0
- package/dist/templates/production-app/src/App.d.ts.map +1 -0
- package/dist/templates/production-app/src/App.js +653 -0
- package/dist/templates/production-app/src/LivePreviewRenderer.d.ts +24 -0
- package/dist/templates/production-app/src/LivePreviewRenderer.d.ts.map +1 -0
- package/dist/templates/production-app/src/LivePreviewRenderer.js +199 -0
- package/dist/templates/production-app/src/componentRegistry.d.ts +20 -0
- package/dist/templates/production-app/src/componentRegistry.d.ts.map +1 -0
- package/dist/templates/production-app/src/componentRegistry.js +316 -0
- package/dist/templates/production-app/src/main.d.ts +9 -0
- package/dist/templates/production-app/src/main.d.ts.map +1 -0
- package/dist/templates/production-app/src/main.js +18 -0
- package/dist/templates/production-app/vite.config.d.ts +3 -0
- package/dist/templates/production-app/vite.config.d.ts.map +1 -0
- package/dist/templates/production-app/vite.config.js +71 -0
- package/dist/test-storybooks/angular-material-storybook/src/main.js +66 -0
- package/dist/test-storybooks/chakra-storybook/vite.config.js +6 -0
- package/dist/test-storybooks/mantine-storybook/vite.config.js +93 -0
- package/dist/test-storybooks/web-components-shoelace/vite.config.js +9 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/visual-builder/components/Canvas/Canvas.js +70 -0
- package/dist/visual-builder/components/Canvas/ComponentRenderer.js +545 -0
- package/dist/visual-builder/components/CodeExporter/CodeExporter.js +25 -0
- package/dist/visual-builder/components/CodeExporter/codeGenerator.js +99 -0
- package/dist/visual-builder/components/ComponentPalette/ComponentPalette.js +8 -0
- package/dist/visual-builder/components/ComponentPalette/ComponentPaletteItem.js +51 -0
- package/dist/visual-builder/components/EmbeddedVisualBuilder.js +107 -0
- package/dist/visual-builder/components/PropertyEditor/PropertyEditor.js +16 -0
- package/dist/visual-builder/components/PropertyEditor/PropertyForm.js +88 -0
- package/dist/visual-builder/components/PropertyEditor/SpacingControl.js +145 -0
- package/dist/visual-builder/components/PropertyEditor/SpacingEditor.js +32 -0
- package/dist/visual-builder/components/StoryManager/SaveOnlyManager.js +94 -0
- package/dist/visual-builder/components/StoryManager/StoryManager.js +68 -0
- package/dist/visual-builder/components/StoryManager/index.js +1 -0
- package/dist/visual-builder/components/VisualBuilder.js +256 -0
- package/dist/visual-builder/config/componentRegistry.js +1758 -0
- package/dist/visual-builder/decorators/VisualBuilderDecorator.js +184 -0
- package/dist/visual-builder/example-integration.js +59 -0
- package/dist/visual-builder/example.js +23 -0
- package/dist/visual-builder/hooks/useDragAndDrop.js +137 -0
- package/dist/visual-builder/hooks/useSelection.js +27 -0
- package/dist/visual-builder/index.js +7 -0
- package/dist/visual-builder/store/visualBuilderStore.js +305 -0
- package/dist/visual-builder/types/index.js +1 -0
- package/dist/visual-builder/utils/__tests__/storyFileUpdater.test.js +145 -0
- package/dist/visual-builder/utils/aiParser.js +336 -0
- package/dist/visual-builder/utils/componentTreeUtils.js +111 -0
- package/dist/visual-builder/utils/parserValidation.js +122 -0
- package/dist/visual-builder/utils/storyFileManager.js +73 -0
- package/dist/visual-builder/utils/storyFileUpdater.js +326 -0
- package/dist/visual-builder/utils/storyNameExtraction.test.js +211 -0
- package/dist/visual-builder/utils/storyPersistence.js +180 -0
- package/dist/visual-builder/utils/storyToBuilder.js +813 -0
- package/package.json +1 -1
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { getComponentConfig } from '../config/componentRegistry';
|
|
2
|
+
/**
|
|
3
|
+
* Parse AI-generated JSX code into Visual Builder component definitions
|
|
4
|
+
*/
|
|
5
|
+
export const parseAIGeneratedCode = (code) => {
|
|
6
|
+
const result = {
|
|
7
|
+
components: [],
|
|
8
|
+
errors: [],
|
|
9
|
+
warnings: []
|
|
10
|
+
};
|
|
11
|
+
try {
|
|
12
|
+
// Clean and extract the component JSX
|
|
13
|
+
const jsxContent = extractJSXContent(code);
|
|
14
|
+
if (!jsxContent) {
|
|
15
|
+
result.errors.push('No JSX content found in the provided code');
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
// Parse the JSX into component definitions
|
|
19
|
+
const parsedComponents = parseJSXToComponents(jsxContent);
|
|
20
|
+
result.components = parsedComponents;
|
|
21
|
+
// Validate components against registry
|
|
22
|
+
validateComponents(result.components, result);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
result.errors.push(`Failed to parse code: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Extract JSX content from the AI-generated code
|
|
31
|
+
*/
|
|
32
|
+
const extractJSXContent = (code) => {
|
|
33
|
+
// Remove imports and exports to focus on JSX
|
|
34
|
+
const lines = code.split('\n');
|
|
35
|
+
const jsxLines = [];
|
|
36
|
+
let inJSX = false;
|
|
37
|
+
let bracketCount = 0;
|
|
38
|
+
let parenthesesCount = 0;
|
|
39
|
+
for (const line of lines) {
|
|
40
|
+
const trimmed = line.trim();
|
|
41
|
+
// Skip import statements
|
|
42
|
+
if (trimmed.startsWith('import ') || trimmed.startsWith('export ')) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// Skip function declaration lines
|
|
46
|
+
if (trimmed.includes('= () => {') || trimmed.includes('function ') || trimmed === '{' || trimmed === '}') {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
// Skip return statement
|
|
50
|
+
if (trimmed.startsWith('return (') || trimmed.startsWith('return')) {
|
|
51
|
+
inJSX = true;
|
|
52
|
+
if (trimmed.includes('(')) {
|
|
53
|
+
parenthesesCount += (trimmed.match(/\(/g) || []).length;
|
|
54
|
+
parenthesesCount -= (trimmed.match(/\)/g) || []).length;
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (inJSX) {
|
|
59
|
+
// Track brackets and parentheses
|
|
60
|
+
bracketCount += (line.match(/</g) || []).length;
|
|
61
|
+
bracketCount -= (line.match(/>/g) || []).length;
|
|
62
|
+
parenthesesCount += (line.match(/\(/g) || []).length;
|
|
63
|
+
parenthesesCount -= (line.match(/\)/g) || []).length;
|
|
64
|
+
// Add line if it contains actual JSX content
|
|
65
|
+
if (trimmed && !trimmed.startsWith('//') && trimmed !== ';') {
|
|
66
|
+
jsxLines.push(line);
|
|
67
|
+
}
|
|
68
|
+
// Stop when we've closed all parentheses (end of return statement)
|
|
69
|
+
if (parenthesesCount <= 0 && bracketCount <= 0) {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return jsxLines.length > 0 ? jsxLines.join('\n') : null;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Parse JSX string into component definitions
|
|
78
|
+
*/
|
|
79
|
+
const parseJSXToComponents = (jsx) => {
|
|
80
|
+
const components = [];
|
|
81
|
+
// Simple regex-based parsing for common patterns
|
|
82
|
+
// This is a basic implementation - in production, you'd want a proper JSX parser
|
|
83
|
+
// Remove extra whitespace and normalize
|
|
84
|
+
const cleanJSX = jsx.replace(/\s+/g, ' ').trim();
|
|
85
|
+
// Parse top-level components
|
|
86
|
+
const topLevelComponents = extractTopLevelComponents(cleanJSX);
|
|
87
|
+
topLevelComponents.forEach((componentString, index) => {
|
|
88
|
+
const parsed = parseComponentString(componentString, index);
|
|
89
|
+
if (parsed) {
|
|
90
|
+
components.push(parsed);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
return components;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Extract top-level components from JSX string
|
|
97
|
+
*/
|
|
98
|
+
const extractTopLevelComponents = (jsx) => {
|
|
99
|
+
const components = [];
|
|
100
|
+
let currentComponent = '';
|
|
101
|
+
let depth = 0;
|
|
102
|
+
let i = 0;
|
|
103
|
+
while (i < jsx.length) {
|
|
104
|
+
const char = jsx[i];
|
|
105
|
+
if (char === '<') {
|
|
106
|
+
const nextChar = jsx[i + 1];
|
|
107
|
+
if (nextChar === '/') {
|
|
108
|
+
// Closing tag
|
|
109
|
+
depth--;
|
|
110
|
+
currentComponent += char;
|
|
111
|
+
}
|
|
112
|
+
else if (nextChar === '!') {
|
|
113
|
+
// Comment or doctype, skip
|
|
114
|
+
const endComment = jsx.indexOf('>', i);
|
|
115
|
+
i = endComment;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Opening tag
|
|
120
|
+
depth++;
|
|
121
|
+
currentComponent += char;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
currentComponent += char;
|
|
126
|
+
}
|
|
127
|
+
// If we've closed all tags and have content, we have a complete component
|
|
128
|
+
if (depth === 0 && currentComponent.trim()) {
|
|
129
|
+
const trimmed = currentComponent.trim();
|
|
130
|
+
if (trimmed.startsWith('<') && (trimmed.endsWith('>') || trimmed.endsWith('/>'))) {
|
|
131
|
+
components.push(trimmed);
|
|
132
|
+
currentComponent = '';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
i++;
|
|
136
|
+
}
|
|
137
|
+
// Add any remaining component
|
|
138
|
+
if (currentComponent.trim()) {
|
|
139
|
+
components.push(currentComponent.trim());
|
|
140
|
+
}
|
|
141
|
+
return components;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Parse individual component string into ComponentDefinition
|
|
145
|
+
*/
|
|
146
|
+
const parseComponentString = (componentString, index) => {
|
|
147
|
+
// Extract component type
|
|
148
|
+
const typeMatch = componentString.match(/<(\w+)/);
|
|
149
|
+
if (!typeMatch)
|
|
150
|
+
return null;
|
|
151
|
+
const type = typeMatch[1];
|
|
152
|
+
const config = getComponentConfig(type);
|
|
153
|
+
if (!config) {
|
|
154
|
+
// Return a basic definition even for unknown components
|
|
155
|
+
return {
|
|
156
|
+
id: `${type.toLowerCase()}-${Date.now()}-${index}`,
|
|
157
|
+
type,
|
|
158
|
+
displayName: type,
|
|
159
|
+
category: 'Unknown',
|
|
160
|
+
props: {},
|
|
161
|
+
children: []
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
// Extract props
|
|
165
|
+
const props = extractProps(componentString, config.defaultProps);
|
|
166
|
+
// Extract children
|
|
167
|
+
const children = extractChildren(componentString, index);
|
|
168
|
+
return {
|
|
169
|
+
id: `${type.toLowerCase()}-${Date.now()}-${index}`,
|
|
170
|
+
type,
|
|
171
|
+
displayName: config.displayName,
|
|
172
|
+
category: config.category,
|
|
173
|
+
props,
|
|
174
|
+
children
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Extract props from component string
|
|
179
|
+
*/
|
|
180
|
+
const extractProps = (componentString, defaultProps) => {
|
|
181
|
+
const props = { ...defaultProps };
|
|
182
|
+
// Extract attributes using regex
|
|
183
|
+
const attrRegex = /(\w+)=(?:"([^"]*)"|{([^}]*)}|(\w+))/g;
|
|
184
|
+
let match;
|
|
185
|
+
while ((match = attrRegex.exec(componentString)) !== null) {
|
|
186
|
+
const [, propName, stringValue, jsValue, boolValue] = match;
|
|
187
|
+
if (stringValue !== undefined) {
|
|
188
|
+
props[propName] = stringValue;
|
|
189
|
+
}
|
|
190
|
+
else if (jsValue !== undefined) {
|
|
191
|
+
// Try to parse JavaScript value
|
|
192
|
+
try {
|
|
193
|
+
props[propName] = JSON.parse(jsValue);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// If parsing fails, treat as string
|
|
197
|
+
props[propName] = jsValue;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else if (boolValue !== undefined) {
|
|
201
|
+
props[propName] = true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Extract text content for components that support it
|
|
205
|
+
const textContentMatch = componentString.match(/>([^<]+)</);
|
|
206
|
+
if (textContentMatch && textContentMatch[1].trim()) {
|
|
207
|
+
const textContent = textContentMatch[1].trim();
|
|
208
|
+
if (!textContent.startsWith('<')) {
|
|
209
|
+
props.children = textContent;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return props;
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* Extract children components
|
|
216
|
+
*/
|
|
217
|
+
const extractChildren = (componentString, parentIndex) => {
|
|
218
|
+
// Check if component is self-closing
|
|
219
|
+
if (componentString.endsWith('/>')) {
|
|
220
|
+
return [];
|
|
221
|
+
}
|
|
222
|
+
// Extract content between opening and closing tags
|
|
223
|
+
const contentMatch = componentString.match(/>(.+)</s);
|
|
224
|
+
if (!contentMatch)
|
|
225
|
+
return [];
|
|
226
|
+
const content = contentMatch[1];
|
|
227
|
+
// If content doesn't contain tags, it's just text
|
|
228
|
+
if (!content.includes('<')) {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
// Recursively parse child components
|
|
232
|
+
const childComponents = extractTopLevelComponents(content);
|
|
233
|
+
const children = [];
|
|
234
|
+
childComponents.forEach((childString, index) => {
|
|
235
|
+
const parsed = parseComponentString(childString, parentIndex * 100 + index);
|
|
236
|
+
if (parsed) {
|
|
237
|
+
children.push(parsed);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
return children;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Validate components against the registry and collect warnings
|
|
244
|
+
*/
|
|
245
|
+
const validateComponents = (components, result) => {
|
|
246
|
+
const validateComponent = (component) => {
|
|
247
|
+
const config = getComponentConfig(component.type);
|
|
248
|
+
if (!config) {
|
|
249
|
+
result.warnings.push(`Component "${component.type}" is not in the Mantine component registry`);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
// Validate props
|
|
253
|
+
Object.keys(component.props).forEach(propName => {
|
|
254
|
+
const propConfig = config.properties.find(p => p.name === propName);
|
|
255
|
+
if (!propConfig) {
|
|
256
|
+
result.warnings.push(`Property "${propName}" is not defined for ${component.type}`);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
// Recursively validate children
|
|
260
|
+
if (component.children) {
|
|
261
|
+
component.children.forEach(validateComponent);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
components.forEach(validateComponent);
|
|
265
|
+
};
|
|
266
|
+
/**
|
|
267
|
+
* Create a simplified component structure for basic layouts
|
|
268
|
+
*/
|
|
269
|
+
export const createBasicLayout = (description) => {
|
|
270
|
+
// This can be enhanced to create basic layouts based on keywords
|
|
271
|
+
const lowerDesc = description.toLowerCase();
|
|
272
|
+
if (lowerDesc.includes('button')) {
|
|
273
|
+
return [{
|
|
274
|
+
id: `button-${Date.now()}`,
|
|
275
|
+
type: 'Button',
|
|
276
|
+
displayName: 'Button',
|
|
277
|
+
category: 'Inputs',
|
|
278
|
+
props: {
|
|
279
|
+
children: 'Click me',
|
|
280
|
+
variant: 'filled',
|
|
281
|
+
size: 'sm'
|
|
282
|
+
}
|
|
283
|
+
}];
|
|
284
|
+
}
|
|
285
|
+
if (lowerDesc.includes('form')) {
|
|
286
|
+
return [
|
|
287
|
+
{
|
|
288
|
+
id: `stack-${Date.now()}`,
|
|
289
|
+
type: 'Stack',
|
|
290
|
+
displayName: 'Stack',
|
|
291
|
+
category: 'Layout',
|
|
292
|
+
props: { gap: 'md' },
|
|
293
|
+
children: [
|
|
294
|
+
{
|
|
295
|
+
id: `textinput-${Date.now()}`,
|
|
296
|
+
type: 'TextInput',
|
|
297
|
+
displayName: 'Text Input',
|
|
298
|
+
category: 'Inputs',
|
|
299
|
+
props: {
|
|
300
|
+
placeholder: 'Enter text...',
|
|
301
|
+
label: 'Input Label'
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: `button-${Date.now()}`,
|
|
306
|
+
type: 'Button',
|
|
307
|
+
displayName: 'Button',
|
|
308
|
+
category: 'Inputs',
|
|
309
|
+
props: {
|
|
310
|
+
children: 'Submit',
|
|
311
|
+
variant: 'filled'
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
]
|
|
315
|
+
}
|
|
316
|
+
];
|
|
317
|
+
}
|
|
318
|
+
// Default: simple container with text
|
|
319
|
+
return [{
|
|
320
|
+
id: `container-${Date.now()}`,
|
|
321
|
+
type: 'Container',
|
|
322
|
+
displayName: 'Container',
|
|
323
|
+
category: 'Layout',
|
|
324
|
+
props: { size: 'md' },
|
|
325
|
+
children: [{
|
|
326
|
+
id: `text-${Date.now()}`,
|
|
327
|
+
type: 'Text',
|
|
328
|
+
displayName: 'Text',
|
|
329
|
+
category: 'Typography',
|
|
330
|
+
props: {
|
|
331
|
+
children: 'Generated component',
|
|
332
|
+
size: 'md'
|
|
333
|
+
}
|
|
334
|
+
}]
|
|
335
|
+
}];
|
|
336
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find a component and its parent in the component tree
|
|
3
|
+
*/
|
|
4
|
+
export const findComponentWithParent = (components, targetId, parent = null) => {
|
|
5
|
+
for (let i = 0; i < components.length; i++) {
|
|
6
|
+
const component = components[i];
|
|
7
|
+
if (component.id === targetId) {
|
|
8
|
+
return {
|
|
9
|
+
component,
|
|
10
|
+
parent,
|
|
11
|
+
index: i
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
if (component.children && component.children.length > 0) {
|
|
15
|
+
const result = findComponentWithParent(component.children, targetId, component);
|
|
16
|
+
if (result) {
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Remove a component from the tree and return the updated tree and removed component
|
|
25
|
+
*/
|
|
26
|
+
export const removeComponentFromTree = (components, targetId) => {
|
|
27
|
+
for (let i = 0; i < components.length; i++) {
|
|
28
|
+
if (components[i].id === targetId) {
|
|
29
|
+
const removed = components[i];
|
|
30
|
+
return {
|
|
31
|
+
components: [...components.slice(0, i), ...components.slice(i + 1)],
|
|
32
|
+
removed
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (components[i].children && components[i].children.length > 0) {
|
|
36
|
+
const result = removeComponentFromTree(components[i].children, targetId);
|
|
37
|
+
if (result.removed) {
|
|
38
|
+
return {
|
|
39
|
+
components: components.map(comp => comp.id === components[i].id
|
|
40
|
+
? { ...comp, children: result.components }
|
|
41
|
+
: comp),
|
|
42
|
+
removed: result.removed
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { components, removed: null };
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Insert a component at a specific location in the tree
|
|
51
|
+
*/
|
|
52
|
+
export const insertComponentInTree = (components, component, parentId, index) => {
|
|
53
|
+
if (!parentId) {
|
|
54
|
+
// Insert at root level
|
|
55
|
+
if (index !== undefined) {
|
|
56
|
+
return [...components.slice(0, index), component, ...components.slice(index)];
|
|
57
|
+
}
|
|
58
|
+
return [...components, component];
|
|
59
|
+
}
|
|
60
|
+
// Insert into specific parent
|
|
61
|
+
return components.map(comp => {
|
|
62
|
+
if (comp.id === parentId) {
|
|
63
|
+
const children = comp.children || [];
|
|
64
|
+
const newChildren = index !== undefined
|
|
65
|
+
? [...children.slice(0, index), component, ...children.slice(index)]
|
|
66
|
+
: [...children, component];
|
|
67
|
+
return { ...comp, children: newChildren };
|
|
68
|
+
}
|
|
69
|
+
if (comp.children) {
|
|
70
|
+
return {
|
|
71
|
+
...comp,
|
|
72
|
+
children: insertComponentInTree(comp.children, component, parentId, index)
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return comp;
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Check if a component is a container (can accept children)
|
|
80
|
+
*/
|
|
81
|
+
export const isContainerComponent = (componentType) => {
|
|
82
|
+
const containerTypes = [
|
|
83
|
+
'Container', 'Group', 'Stack', 'Card', 'Paper', 'Box',
|
|
84
|
+
'Flex', 'Grid', 'GridCol', 'SimpleGrid', 'Tabs'
|
|
85
|
+
];
|
|
86
|
+
return containerTypes.includes(componentType);
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Get all parent IDs of a component (path from root to component)
|
|
90
|
+
*/
|
|
91
|
+
export const getComponentPath = (components, targetId, path = []) => {
|
|
92
|
+
for (const component of components) {
|
|
93
|
+
if (component.id === targetId) {
|
|
94
|
+
return path;
|
|
95
|
+
}
|
|
96
|
+
if (component.children && component.children.length > 0) {
|
|
97
|
+
const result = getComponentPath(component.children, targetId, [...path, component.id]);
|
|
98
|
+
if (result) {
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Check if one component is a descendant of another
|
|
107
|
+
*/
|
|
108
|
+
export const isDescendant = (components, ancestorId, descendantId) => {
|
|
109
|
+
const path = getComponentPath(components, descendantId);
|
|
110
|
+
return path ? path.includes(ancestorId) : false;
|
|
111
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Validation utility to test the parser fix
|
|
2
|
+
import { parseStoryUIToBuilder } from './storyToBuilder';
|
|
3
|
+
/**
|
|
4
|
+
* Test the JSX parser with the recipe card story
|
|
5
|
+
*/
|
|
6
|
+
export function validateParserFix() {
|
|
7
|
+
console.log('š§Ŗ Validating JSX Parser Fix');
|
|
8
|
+
console.log('='.repeat(40));
|
|
9
|
+
// Sample JSX from the recipe card story (simplified for testing)
|
|
10
|
+
const testJSX = `
|
|
11
|
+
export const Default: Story = {
|
|
12
|
+
render: () => (
|
|
13
|
+
<Card shadow="sm" padding="lg" radius="md" withBorder>
|
|
14
|
+
<Card.Section>
|
|
15
|
+
<Image
|
|
16
|
+
src="https://picsum.photos/400/200?random=1"
|
|
17
|
+
height={200}
|
|
18
|
+
alt="Test image"
|
|
19
|
+
/>
|
|
20
|
+
</Card.Section>
|
|
21
|
+
<Stack gap="md" mt="md">
|
|
22
|
+
<Group justify="space-between" align="flex-start">
|
|
23
|
+
<Text fw={500} size="lg">
|
|
24
|
+
Test Title
|
|
25
|
+
</Text>
|
|
26
|
+
<Badge color="green" variant="light">
|
|
27
|
+
30 min
|
|
28
|
+
</Badge>
|
|
29
|
+
</Group>
|
|
30
|
+
<Text size="sm" c="dimmed">
|
|
31
|
+
Test description text
|
|
32
|
+
</Text>
|
|
33
|
+
</Stack>
|
|
34
|
+
</Card>
|
|
35
|
+
),
|
|
36
|
+
};`;
|
|
37
|
+
try {
|
|
38
|
+
const result = parseStoryUIToBuilder(testJSX);
|
|
39
|
+
console.log('š Parse Results:');
|
|
40
|
+
console.log(` Components: ${result.components.length}`);
|
|
41
|
+
console.log(` Errors: ${result.errors.length}`);
|
|
42
|
+
console.log(` Warnings: ${result.warnings.length}`);
|
|
43
|
+
if (result.errors.length > 0) {
|
|
44
|
+
console.log('ā Errors:');
|
|
45
|
+
result.errors.forEach(error => console.log(` ${error}`));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// Test the component structure
|
|
49
|
+
if (result.components.length > 0) {
|
|
50
|
+
const rootComponent = result.components[0];
|
|
51
|
+
console.log(`\nšļø Root Component: ${rootComponent.type}`);
|
|
52
|
+
if (rootComponent.type === 'Card' && rootComponent.children) {
|
|
53
|
+
console.log(`ā
Card has ${rootComponent.children.length} children`);
|
|
54
|
+
// Check for Card.Section -> CardSection mapping
|
|
55
|
+
const cardSection = rootComponent.children.find(c => c.type === 'CardSection');
|
|
56
|
+
if (cardSection) {
|
|
57
|
+
console.log('ā
Found CardSection component');
|
|
58
|
+
console.log(` CardSection children: ${cardSection.children?.length || 0}`);
|
|
59
|
+
if (cardSection.children && cardSection.children.length > 0) {
|
|
60
|
+
const image = cardSection.children.find(c => c.type === 'Image');
|
|
61
|
+
if (image) {
|
|
62
|
+
console.log('ā
Found Image inside CardSection');
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log('ā Image not found inside CardSection');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.log('ā CardSection not found');
|
|
71
|
+
}
|
|
72
|
+
// Check for Stack component
|
|
73
|
+
const stack = rootComponent.children.find(c => c.type === 'Stack');
|
|
74
|
+
if (stack) {
|
|
75
|
+
console.log('ā
Found Stack component');
|
|
76
|
+
console.log(` Stack children: ${stack.children?.length || 0}`);
|
|
77
|
+
if (stack.children && stack.children.length >= 2) {
|
|
78
|
+
const group = stack.children.find(c => c.type === 'Group');
|
|
79
|
+
if (group) {
|
|
80
|
+
console.log('ā
Found Group inside Stack');
|
|
81
|
+
console.log(` Group children: ${group.children?.length || 0}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
console.log('ā Stack not found');
|
|
87
|
+
}
|
|
88
|
+
// Display full tree structure
|
|
89
|
+
console.log('\nš³ Full Component Tree:');
|
|
90
|
+
printComponentTree(result.components, 0);
|
|
91
|
+
// Success criteria
|
|
92
|
+
const hasCorrectNesting = rootComponent.type === 'Card' &&
|
|
93
|
+
rootComponent.children?.some(c => c.type === 'CardSection') &&
|
|
94
|
+
rootComponent.children?.some(c => c.type === 'Stack');
|
|
95
|
+
if (hasCorrectNesting) {
|
|
96
|
+
console.log('\nš SUCCESS: Parser correctly maintains nested structure!');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
console.log('\nā FAILED: Parser still losing nested structure');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
console.log('ā Root component is not Card or has no children');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
console.log('ā No components parsed');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error('ā Validation failed:', error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function printComponentTree(components, depth) {
|
|
115
|
+
const indent = ' '.repeat(depth);
|
|
116
|
+
components.forEach(comp => {
|
|
117
|
+
console.log(`${indent}š¦ ${comp.type} (${comp.id})`);
|
|
118
|
+
if (comp.children && comp.children.length > 0) {
|
|
119
|
+
printComponentTree(comp.children, depth + 1);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Story File Management System
|
|
3
|
+
*
|
|
4
|
+
* This replaces the complex multi-path save logic with a simple, predictable system:
|
|
5
|
+
* 1. Always save to the main /generated/ directory
|
|
6
|
+
* 2. Overwrite existing files by default
|
|
7
|
+
* 3. Optional backup creation (only when explicitly requested)
|
|
8
|
+
* 4. No subdirectories, no versioning, no confusion
|
|
9
|
+
*/
|
|
10
|
+
import { updateStoryFile } from './storyFileUpdater';
|
|
11
|
+
/**
|
|
12
|
+
* Save components to a story file using the new simplified architecture
|
|
13
|
+
* Always saves to the main /generated/ directory, never creates subdirectories
|
|
14
|
+
*/
|
|
15
|
+
export async function saveStoryFile(filePath, components, options = {}) {
|
|
16
|
+
try {
|
|
17
|
+
const fileName = filePath.split('/').pop() || filePath;
|
|
18
|
+
const storyName = options.storyName ||
|
|
19
|
+
fileName.replace('.stories.tsx', '').replace(/[-_]/g, ' ');
|
|
20
|
+
// Use the existing updateStoryFile function with createBackup option
|
|
21
|
+
const result = await updateStoryFile(filePath, components, storyName);
|
|
22
|
+
if (result.success) {
|
|
23
|
+
return {
|
|
24
|
+
success: true,
|
|
25
|
+
filePath,
|
|
26
|
+
fileName,
|
|
27
|
+
action: 'updated', // We don't distinguish between create/update anymore
|
|
28
|
+
hasBackup: options.createBackup,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return {
|
|
33
|
+
success: false,
|
|
34
|
+
action: 'updated',
|
|
35
|
+
error: result.error || 'Unknown error occurred'
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
return {
|
|
41
|
+
success: false,
|
|
42
|
+
action: 'updated',
|
|
43
|
+
error: error instanceof Error ? error.message : 'Unknown error occurred'
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get a clean filename for saving
|
|
49
|
+
* Removes duplicate prefixes and ensures .stories.tsx extension
|
|
50
|
+
*/
|
|
51
|
+
export function getCleanFileName(originalName) {
|
|
52
|
+
let cleanName = originalName;
|
|
53
|
+
// Remove duplicate "generated-" prefixes
|
|
54
|
+
while (cleanName.startsWith('generated-generated-')) {
|
|
55
|
+
cleanName = cleanName.replace(/^generated-/, '');
|
|
56
|
+
}
|
|
57
|
+
// Ensure .stories.tsx extension
|
|
58
|
+
if (!cleanName.endsWith('.stories.tsx')) {
|
|
59
|
+
cleanName = cleanName.replace(/\.tsx$/, '') + '.stories.tsx';
|
|
60
|
+
}
|
|
61
|
+
return cleanName;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Convert a file path to a story name
|
|
65
|
+
* Extracts a human-readable name from the file path
|
|
66
|
+
*/
|
|
67
|
+
export function filePathToStoryName(filePath) {
|
|
68
|
+
const fileName = filePath.split('/').pop() || filePath;
|
|
69
|
+
return fileName
|
|
70
|
+
.replace('.stories.tsx', '')
|
|
71
|
+
.replace(/[-_]/g, ' ')
|
|
72
|
+
.replace(/\b\w/g, l => l.toUpperCase()); // Title case
|
|
73
|
+
}
|