figma-to-code-agent 0.3.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.
Files changed (166) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/LICENSE +21 -0
  3. package/QUICKSTART.md +198 -0
  4. package/README.md +149 -0
  5. package/dist/FigmaToCodeAgent.d.ts +55 -0
  6. package/dist/FigmaToCodeAgent.d.ts.map +1 -0
  7. package/dist/FigmaToCodeAgent.js +251 -0
  8. package/dist/FigmaToCodeAgent.js.map +1 -0
  9. package/dist/assets/index.d.ts +6 -0
  10. package/dist/assets/index.d.ts.map +1 -0
  11. package/dist/assets/index.js +7 -0
  12. package/dist/assets/index.js.map +1 -0
  13. package/dist/cli.d.ts +3 -0
  14. package/dist/cli.d.ts.map +1 -0
  15. package/dist/cli.js +261 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/extraction/FigmaAPIClient.d.ts +53 -0
  18. package/dist/extraction/FigmaAPIClient.d.ts.map +1 -0
  19. package/dist/extraction/FigmaAPIClient.js +275 -0
  20. package/dist/extraction/FigmaAPIClient.js.map +1 -0
  21. package/dist/extraction/FigmaCache.d.ts +28 -0
  22. package/dist/extraction/FigmaCache.d.ts.map +1 -0
  23. package/dist/extraction/FigmaCache.js +120 -0
  24. package/dist/extraction/FigmaCache.js.map +1 -0
  25. package/dist/extraction/MCPClient.d.ts +75 -0
  26. package/dist/extraction/MCPClient.d.ts.map +1 -0
  27. package/dist/extraction/MCPClient.js +254 -0
  28. package/dist/extraction/MCPClient.js.map +1 -0
  29. package/dist/extraction/index.d.ts +9 -0
  30. package/dist/extraction/index.d.ts.map +1 -0
  31. package/dist/extraction/index.js +27 -0
  32. package/dist/extraction/index.js.map +1 -0
  33. package/dist/extraction/types.d.ts +122 -0
  34. package/dist/extraction/types.d.ts.map +1 -0
  35. package/dist/extraction/types.js +6 -0
  36. package/dist/extraction/types.js.map +1 -0
  37. package/dist/generation/AICodeOptimizer.d.ts +10 -0
  38. package/dist/generation/AICodeOptimizer.d.ts.map +1 -0
  39. package/dist/generation/AICodeOptimizer.js +33 -0
  40. package/dist/generation/AICodeOptimizer.js.map +1 -0
  41. package/dist/generation/ReactGenerator.d.ts +27 -0
  42. package/dist/generation/ReactGenerator.d.ts.map +1 -0
  43. package/dist/generation/ReactGenerator.js +423 -0
  44. package/dist/generation/ReactGenerator.js.map +1 -0
  45. package/dist/generation/VueGenerator.d.ts +23 -0
  46. package/dist/generation/VueGenerator.d.ts.map +1 -0
  47. package/dist/generation/VueGenerator.js +337 -0
  48. package/dist/generation/VueGenerator.js.map +1 -0
  49. package/dist/generation/index.d.ts +6 -0
  50. package/dist/generation/index.d.ts.map +1 -0
  51. package/dist/generation/index.js +7 -0
  52. package/dist/generation/index.js.map +1 -0
  53. package/dist/generation/types.d.ts +24 -0
  54. package/dist/generation/types.d.ts.map +1 -0
  55. package/dist/generation/types.js +3 -0
  56. package/dist/generation/types.js.map +1 -0
  57. package/dist/index.d.ts +10 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +17 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/llm/BedrockProvider.d.ts +8 -0
  62. package/dist/llm/BedrockProvider.d.ts.map +1 -0
  63. package/dist/llm/BedrockProvider.js +34 -0
  64. package/dist/llm/BedrockProvider.js.map +1 -0
  65. package/dist/llm/LLMFactory.d.ts +5 -0
  66. package/dist/llm/LLMFactory.d.ts.map +1 -0
  67. package/dist/llm/LLMFactory.js +21 -0
  68. package/dist/llm/LLMFactory.js.map +1 -0
  69. package/dist/llm/OpenAIProvider.d.ts +7 -0
  70. package/dist/llm/OpenAIProvider.d.ts.map +1 -0
  71. package/dist/llm/OpenAIProvider.js +34 -0
  72. package/dist/llm/OpenAIProvider.js.map +1 -0
  73. package/dist/llm/index.d.ts +5 -0
  74. package/dist/llm/index.d.ts.map +1 -0
  75. package/dist/llm/index.js +21 -0
  76. package/dist/llm/index.js.map +1 -0
  77. package/dist/llm/types.d.ts +23 -0
  78. package/dist/llm/types.d.ts.map +1 -0
  79. package/dist/llm/types.js +3 -0
  80. package/dist/llm/types.js.map +1 -0
  81. package/dist/transformation/ASTFactory.d.ts +92 -0
  82. package/dist/transformation/ASTFactory.d.ts.map +1 -0
  83. package/dist/transformation/ASTFactory.js +240 -0
  84. package/dist/transformation/ASTFactory.js.map +1 -0
  85. package/dist/transformation/ASTParser.d.ts +13 -0
  86. package/dist/transformation/ASTParser.d.ts.map +1 -0
  87. package/dist/transformation/ASTParser.js +177 -0
  88. package/dist/transformation/ASTParser.js.map +1 -0
  89. package/dist/transformation/TransformationPipeline.d.ts +31 -0
  90. package/dist/transformation/TransformationPipeline.d.ts.map +1 -0
  91. package/dist/transformation/TransformationPipeline.js +42 -0
  92. package/dist/transformation/TransformationPipeline.js.map +1 -0
  93. package/dist/transformation/index.d.ts +7 -0
  94. package/dist/transformation/index.d.ts.map +1 -0
  95. package/dist/transformation/index.js +25 -0
  96. package/dist/transformation/index.js.map +1 -0
  97. package/dist/transformation/transformers/AIComponentSplitter.d.ts +14 -0
  98. package/dist/transformation/transformers/AIComponentSplitter.d.ts.map +1 -0
  99. package/dist/transformation/transformers/AIComponentSplitter.js +71 -0
  100. package/dist/transformation/transformers/AIComponentSplitter.js.map +1 -0
  101. package/dist/transformation/transformers/AILayoutAnalyzer.d.ts +18 -0
  102. package/dist/transformation/transformers/AILayoutAnalyzer.d.ts.map +1 -0
  103. package/dist/transformation/transformers/AILayoutAnalyzer.js +125 -0
  104. package/dist/transformation/transformers/AILayoutAnalyzer.js.map +1 -0
  105. package/dist/transformation/transformers/AISemanticNamer.d.ts +12 -0
  106. package/dist/transformation/transformers/AISemanticNamer.d.ts.map +1 -0
  107. package/dist/transformation/transformers/AISemanticNamer.js +50 -0
  108. package/dist/transformation/transformers/AISemanticNamer.js.map +1 -0
  109. package/dist/transformation/transformers/ComponentExtractor.d.ts +16 -0
  110. package/dist/transformation/transformers/ComponentExtractor.d.ts.map +1 -0
  111. package/dist/transformation/transformers/ComponentExtractor.js +91 -0
  112. package/dist/transformation/transformers/ComponentExtractor.js.map +1 -0
  113. package/dist/transformation/transformers/FigmaLayerPreserver.d.ts +14 -0
  114. package/dist/transformation/transformers/FigmaLayerPreserver.d.ts.map +1 -0
  115. package/dist/transformation/transformers/FigmaLayerPreserver.js +48 -0
  116. package/dist/transformation/transformers/FigmaLayerPreserver.js.map +1 -0
  117. package/dist/transformation/transformers/FigmaStructureOptimizer.d.ts +16 -0
  118. package/dist/transformation/transformers/FigmaStructureOptimizer.d.ts.map +1 -0
  119. package/dist/transformation/transformers/FigmaStructureOptimizer.js +65 -0
  120. package/dist/transformation/transformers/FigmaStructureOptimizer.js.map +1 -0
  121. package/dist/transformation/transformers/FlattenTransformer.d.ts +15 -0
  122. package/dist/transformation/transformers/FlattenTransformer.d.ts.map +1 -0
  123. package/dist/transformation/transformers/FlattenTransformer.js +69 -0
  124. package/dist/transformation/transformers/FlattenTransformer.js.map +1 -0
  125. package/dist/transformation/transformers/LayoutOptimizer.d.ts +15 -0
  126. package/dist/transformation/transformers/LayoutOptimizer.d.ts.map +1 -0
  127. package/dist/transformation/transformers/LayoutOptimizer.js +63 -0
  128. package/dist/transformation/transformers/LayoutOptimizer.js.map +1 -0
  129. package/dist/transformation/transformers/SemanticNamer.d.ts +14 -0
  130. package/dist/transformation/transformers/SemanticNamer.d.ts.map +1 -0
  131. package/dist/transformation/transformers/SemanticNamer.js +65 -0
  132. package/dist/transformation/transformers/SemanticNamer.js.map +1 -0
  133. package/dist/transformation/transformers/SimplifyTransformer.d.ts +23 -0
  134. package/dist/transformation/transformers/SimplifyTransformer.d.ts.map +1 -0
  135. package/dist/transformation/transformers/SimplifyTransformer.js +138 -0
  136. package/dist/transformation/transformers/SimplifyTransformer.js.map +1 -0
  137. package/dist/transformation/types.d.ts +129 -0
  138. package/dist/transformation/types.d.ts.map +1 -0
  139. package/dist/transformation/types.js +7 -0
  140. package/dist/transformation/types.js.map +1 -0
  141. package/dist/validation/index.d.ts +6 -0
  142. package/dist/validation/index.d.ts.map +1 -0
  143. package/dist/validation/index.js +7 -0
  144. package/dist/validation/index.js.map +1 -0
  145. package/package.json +81 -0
  146. package/test-app/test-react/index.html +19 -0
  147. package/test-app/test-react/package.json +16 -0
  148. package/test-app/test-react/src/Component.jsx +146 -0
  149. package/test-app/test-react/src/Component.module.css +572 -0
  150. package/test-app/test-react/src/Homepage.jsx +53 -0
  151. package/test-app/test-react/src/Homepage.module.css +218 -0
  152. package/test-app/test-react/src/ProductPage.jsx +74 -0
  153. package/test-app/test-react/src/ProductPage.module.css +357 -0
  154. package/test-app/test-react/src/ShoppingCart.jsx +151 -0
  155. package/test-app/test-react/src/ShoppingCart.module.css +739 -0
  156. package/test-app/test-react/src/main.jsx +9 -0
  157. package/test-app/test-react/vite.config.js +6 -0
  158. package/test-app/test-vue/index.html +19 -0
  159. package/test-app/test-vue/package.json +15 -0
  160. package/test-app/test-vue/src/App.vue +16 -0
  161. package/test-app/test-vue/src/Component.vue +723 -0
  162. package/test-app/test-vue/src/Homepage.vue +271 -0
  163. package/test-app/test-vue/src/ProductPage.vue +431 -0
  164. package/test-app/test-vue/src/ShoppingCart.vue +890 -0
  165. package/test-app/test-vue/src/main.js +4 -0
  166. package/test-app/test-vue/vite.config.js +6 -0
@@ -0,0 +1,7 @@
1
+ /**
2
+ * AST Transformation Layer
3
+ * Converts Figma nodes to optimized intermediate representation
4
+ */
5
+ export * from './types';
6
+ export * from './ASTFactory';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transformation/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,cAAc,cAAc,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * AST Transformation Layer
4
+ * Converts Figma nodes to optimized intermediate representation
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ // Export all types
22
+ __exportStar(require("./types"), exports);
23
+ // Export factory functions
24
+ __exportStar(require("./ASTFactory"), exports);
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transformation/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AAEH,mBAAmB;AACnB,0CAAwB;AAExB,2BAA2B;AAC3B,+CAA6B"}
@@ -0,0 +1,14 @@
1
+ import type { ASTNode } from '../types';
2
+ import type { Transformer } from '../TransformationPipeline';
3
+ import type { LLMProvider } from '../../llm/types';
4
+ export declare class AIComponentSplitter implements Transformer {
5
+ private llm;
6
+ name: string;
7
+ constructor(llm: LLMProvider);
8
+ transform(node: ASTNode): Promise<ASTNode>;
9
+ private shouldAnalyze;
10
+ private analyzeComponent;
11
+ private simplifyNode;
12
+ private splitComponent;
13
+ }
14
+ //# sourceMappingURL=AIComponentSplitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AIComponentSplitter.d.ts","sourceRoot":"","sources":["../../../src/transformation/transformers/AIComponentSplitter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,qBAAa,mBAAoB,YAAW,WAAW;IAGzC,OAAO,CAAC,GAAG;IAFvB,IAAI,SAAyB;gBAET,GAAG,EAAE,WAAW;IAE9B,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBhD,OAAO,CAAC,aAAa;YAIP,gBAAgB;IAkB9B,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,cAAc;CA2BvB"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AIComponentSplitter = void 0;
4
+ class AIComponentSplitter {
5
+ constructor(llm) {
6
+ this.llm = llm;
7
+ this.name = 'AIComponentSplitter';
8
+ }
9
+ async transform(node) {
10
+ if (this.shouldAnalyze(node)) {
11
+ const decision = await this.analyzeComponent(node);
12
+ if (decision.shouldSplit) {
13
+ return this.splitComponent(node, decision.splitPoints);
14
+ }
15
+ }
16
+ if (node.children) {
17
+ node.children = await Promise.all(node.children.map((child) => this.transform(child)));
18
+ }
19
+ return node;
20
+ }
21
+ shouldAnalyze(node) {
22
+ return node.type === 'Container' && (node.children?.length || 0) > 5;
23
+ }
24
+ async analyzeComponent(node) {
25
+ const response = await this.llm.chat([
26
+ {
27
+ role: 'system',
28
+ content: 'You are a UI architecture expert. Analyze component structure and decide if it should be split into smaller components. Return JSON: {"shouldSplit": boolean, "splitPoints": [indices]}',
29
+ },
30
+ {
31
+ role: 'user',
32
+ content: `Analyze this component:\n${JSON.stringify(this.simplifyNode(node), null, 2)}`,
33
+ },
34
+ ]);
35
+ return JSON.parse(response.content);
36
+ }
37
+ simplifyNode(node) {
38
+ return {
39
+ type: node.type,
40
+ name: node.name,
41
+ childCount: node.children?.length || 0,
42
+ children: node.children?.map((c) => ({ type: c.type, name: c.name })),
43
+ };
44
+ }
45
+ splitComponent(node, splitPoints) {
46
+ // Simple split logic - can be enhanced
47
+ const newChildren = [];
48
+ let currentGroup = [];
49
+ node.children?.forEach((child, i) => {
50
+ currentGroup.push(child);
51
+ if (splitPoints.includes(i)) {
52
+ newChildren.push({
53
+ ...node,
54
+ name: `${node.name}Part${newChildren.length + 1}`,
55
+ children: currentGroup,
56
+ });
57
+ currentGroup = [];
58
+ }
59
+ });
60
+ if (currentGroup.length > 0) {
61
+ newChildren.push({
62
+ ...node,
63
+ name: `${node.name}Part${newChildren.length + 1}`,
64
+ children: currentGroup,
65
+ });
66
+ }
67
+ return { ...node, children: newChildren };
68
+ }
69
+ }
70
+ exports.AIComponentSplitter = AIComponentSplitter;
71
+ //# sourceMappingURL=AIComponentSplitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AIComponentSplitter.js","sourceRoot":"","sources":["../../../src/transformation/transformers/AIComponentSplitter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { ASTNode } from '../types';
2
+ import type { Transformer } from '../TransformationPipeline';
3
+ import type { LLMProvider } from '../../llm';
4
+ /**
5
+ * Use AI to analyze and restructure the layout for better readability
6
+ * Identifies semantic components like: Header, Nav, Card, Button, etc.
7
+ */
8
+ export declare class AILayoutAnalyzer implements Transformer {
9
+ private llm;
10
+ name: string;
11
+ constructor(llm: LLMProvider);
12
+ transform(node: ASTNode): Promise<ASTNode>;
13
+ private analyzeStructure;
14
+ private simplifyForAI;
15
+ private applyAnalysis;
16
+ private applyComponentTypes;
17
+ }
18
+ //# sourceMappingURL=AILayoutAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AILayoutAnalyzer.d.ts","sourceRoot":"","sources":["../../../src/transformation/transformers/AILayoutAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C;;;GAGG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAGtC,OAAO,CAAC,GAAG;IAFvB,IAAI,SAAwB;gBAER,GAAG,EAAE,WAAW;IAE9B,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YAQlC,gBAAgB;IAsD9B,OAAO,CAAC,aAAa;IAuBrB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,mBAAmB;CAiC5B"}
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AILayoutAnalyzer = void 0;
4
+ /**
5
+ * Use AI to analyze and restructure the layout for better readability
6
+ * Identifies semantic components like: Header, Nav, Card, Button, etc.
7
+ */
8
+ class AILayoutAnalyzer {
9
+ constructor(llm) {
10
+ this.llm = llm;
11
+ this.name = 'ai-layout-analyzer';
12
+ }
13
+ async transform(node) {
14
+ // Analyze top-level structure
15
+ if (node.children.length > 0) {
16
+ return await this.analyzeStructure(node);
17
+ }
18
+ return node;
19
+ }
20
+ async analyzeStructure(node) {
21
+ // Create a simplified representation for AI
22
+ const structure = this.simplifyForAI(node);
23
+ const prompt = `Analyze this UI structure and identify semantic components.
24
+
25
+ Structure:
26
+ ${JSON.stringify(structure, null, 2)}
27
+
28
+ Identify:
29
+ 1. Component types (Header, Nav, Card, Button, List, Grid, etc.)
30
+ 2. Semantic groupings (which nodes should be grouped together)
31
+ 3. Unnecessary nesting (which containers can be removed)
32
+
33
+ Return JSON format:
34
+ {
35
+ "components": [
36
+ {
37
+ "nodeId": "node-id",
38
+ "type": "Header|Nav|Card|Button|List|Grid|Section|Article|Aside|Footer",
39
+ "name": "descriptive-name",
40
+ "children": ["child-node-ids"]
41
+ }
42
+ ],
43
+ "removeNodes": ["node-ids-to-remove"],
44
+ "mergeGroups": [
45
+ {
46
+ "parentId": "parent-node-id",
47
+ "childIds": ["child-ids-to-merge"]
48
+ }
49
+ ]
50
+ }`;
51
+ try {
52
+ const response = await this.llm.chat([
53
+ {
54
+ role: 'system',
55
+ content: 'You are a UI/UX expert. Analyze component structures and provide semantic improvements. Return ONLY valid JSON.',
56
+ },
57
+ {
58
+ role: 'user',
59
+ content: prompt,
60
+ },
61
+ ]);
62
+ const analysis = JSON.parse(response.content);
63
+ return this.applyAnalysis(node, analysis);
64
+ }
65
+ catch (error) {
66
+ console.warn('AI layout analysis failed, using original structure:', error);
67
+ return node;
68
+ }
69
+ }
70
+ simplifyForAI(node, depth = 0) {
71
+ // Limit depth to avoid token overflow
72
+ if (depth > 5) {
73
+ return { id: node.id, name: node.name, type: node.type, childCount: node.children.length };
74
+ }
75
+ return {
76
+ id: node.id,
77
+ name: node.name,
78
+ type: node.type,
79
+ layout: {
80
+ display: node.layout.display,
81
+ flexDirection: node.layout.flexDirection,
82
+ size: node.layout.size,
83
+ },
84
+ hasBackground: !!node.styles.backgroundColor,
85
+ hasBorder: !!node.styles.border,
86
+ hasText: node.type === 'Text',
87
+ hasImage: node.type === 'Image',
88
+ children: node.children.map((child) => this.simplifyForAI(child, depth + 1)),
89
+ };
90
+ }
91
+ applyAnalysis(node, analysis) {
92
+ // Apply component type identification
93
+ const componentMap = new Map((analysis.components || []).map((c) => [c.nodeId, c]));
94
+ // Apply transformations
95
+ return this.applyComponentTypes(node, componentMap, analysis.removeNodes || []);
96
+ }
97
+ applyComponentTypes(node, componentMap, removeNodes) {
98
+ // Skip removed nodes
99
+ if (removeNodes.includes(node.id)) {
100
+ return null;
101
+ }
102
+ // Apply component type if identified
103
+ const component = componentMap.get(node.id);
104
+ if (component) {
105
+ node = {
106
+ ...node,
107
+ metadata: {
108
+ ...node.metadata,
109
+ componentName: component.name,
110
+ // Store semantic type in metadata for later use
111
+ },
112
+ };
113
+ }
114
+ // Recursively apply to children
115
+ const children = node.children
116
+ .map((child) => this.applyComponentTypes(child, componentMap, removeNodes))
117
+ .filter((child) => child !== null);
118
+ return {
119
+ ...node,
120
+ children,
121
+ };
122
+ }
123
+ }
124
+ exports.AILayoutAnalyzer = AILayoutAnalyzer;
125
+ //# sourceMappingURL=AILayoutAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AILayoutAnalyzer.js","sourceRoot":"","sources":["../../../src/transformation/transformers/AILayoutAnalyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { ASTNode } from '../types';
2
+ import type { Transformer } from '../TransformationPipeline';
3
+ import type { LLMProvider } from '../../llm/types';
4
+ export declare class AISemanticNamer implements Transformer {
5
+ private llm;
6
+ name: string;
7
+ constructor(llm: LLMProvider);
8
+ transform(node: ASTNode): Promise<ASTNode>;
9
+ private generateName;
10
+ private buildContext;
11
+ }
12
+ //# sourceMappingURL=AISemanticNamer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AISemanticNamer.d.ts","sourceRoot":"","sources":["../../../src/transformation/transformers/AISemanticNamer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,qBAAa,eAAgB,YAAW,WAAW;IAGrC,OAAO,CAAC,GAAG;IAFvB,IAAI,SAAqB;gBAEL,GAAG,EAAE,WAAW;IAE9B,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YAalC,YAAY;IAiB1B,OAAO,CAAC,YAAY;CAiBrB"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AISemanticNamer = void 0;
4
+ class AISemanticNamer {
5
+ constructor(llm) {
6
+ this.llm = llm;
7
+ this.name = 'AISemanticNamer';
8
+ }
9
+ async transform(node) {
10
+ if (node.type === 'Component' || node.type === 'Container') {
11
+ const name = await this.generateName(node);
12
+ node.name = name;
13
+ }
14
+ if (node.children) {
15
+ node.children = await Promise.all(node.children.map((child) => this.transform(child)));
16
+ }
17
+ return node;
18
+ }
19
+ async generateName(node) {
20
+ const context = this.buildContext(node);
21
+ const response = await this.llm.chat([
22
+ {
23
+ role: 'system',
24
+ content: 'You are a UI component naming expert. Generate semantic, descriptive component names following React/Vue conventions. Return ONLY the component name, nothing else.',
25
+ },
26
+ {
27
+ role: 'user',
28
+ content: `Generate a component name for:\n${context}`,
29
+ },
30
+ ]);
31
+ return response.content.trim().replace(/[^a-zA-Z0-9]/g, '');
32
+ }
33
+ buildContext(node) {
34
+ const parts = [
35
+ `Type: ${node.type}`,
36
+ `Original name: ${node.name}`,
37
+ `Layout: ${node.layout?.display || 'none'}`,
38
+ `Children: ${node.children?.length || 0}`,
39
+ ];
40
+ if (node.children?.some((c) => c.type === 'Text')) {
41
+ parts.push('Contains text');
42
+ }
43
+ if (node.children?.some((c) => c.type === 'Image')) {
44
+ parts.push('Contains image');
45
+ }
46
+ return parts.join('\n');
47
+ }
48
+ }
49
+ exports.AISemanticNamer = AISemanticNamer;
50
+ //# sourceMappingURL=AISemanticNamer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AISemanticNamer.js","sourceRoot":"","sources":["../../../src/transformation/transformers/AISemanticNamer.ts"],"names":[],"mappings":";;;AAIA,MAAa,eAAe;IAG1B,YAAoB,GAAgB;QAAhB,QAAG,GAAH,GAAG,CAAa;QAFpC,SAAI,GAAG,iBAAiB,CAAC;IAEc,CAAC;IAExC,KAAK,CAAC,SAAS,CAAC,IAAa;QAC3B,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC3D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACnB,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzF,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,IAAa;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YACnC;gBACE,IAAI,EAAE,QAAQ;gBACd,OAAO,EACL,qKAAqK;aACxK;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,mCAAmC,OAAO,EAAE;aACtD;SACF,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAEO,YAAY,CAAC,IAAa;QAChC,MAAM,KAAK,GAAG;YACZ,SAAS,IAAI,CAAC,IAAI,EAAE;YACpB,kBAAkB,IAAI,CAAC,IAAI,EAAE;YAC7B,WAAW,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,MAAM,EAAE;YAC3C,aAAa,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAE;SAC1C,CAAC;QAEF,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,CAAC;YAC3D,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,CAAC;YAC5D,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC/B,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF;AApDD,0CAoDC"}
@@ -0,0 +1,16 @@
1
+ import type { ASTNode } from '../types';
2
+ import type { Transformer } from '../TransformationPipeline';
3
+ /**
4
+ * Extract reusable components from the AST
5
+ * Identifies repeated patterns and marks them as components
6
+ */
7
+ export declare class ComponentExtractor implements Transformer {
8
+ name: string;
9
+ private componentMap;
10
+ transform(node: ASTNode): ASTNode;
11
+ private collectComponents;
12
+ private markComponents;
13
+ private generateSignature;
14
+ private generateComponentName;
15
+ }
16
+ //# sourceMappingURL=ComponentExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComponentExtractor.d.ts","sourceRoot":"","sources":["../../../src/transformation/transformers/ComponentExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,WAAW;IACpD,IAAI,SAAyB;IAC7B,OAAO,CAAC,YAAY,CAAgC;IAEpD,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;IAQjC,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,cAAc;IAgCtB,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,qBAAqB;CAkB9B"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ComponentExtractor = void 0;
4
+ /**
5
+ * Extract reusable components from the AST
6
+ * Identifies repeated patterns and marks them as components
7
+ */
8
+ class ComponentExtractor {
9
+ constructor() {
10
+ this.name = 'component-extractor';
11
+ this.componentMap = new Map();
12
+ }
13
+ transform(node) {
14
+ // First pass: collect potential components
15
+ this.collectComponents(node);
16
+ // Second pass: mark repeated patterns as components
17
+ return this.markComponents(node);
18
+ }
19
+ collectComponents(node) {
20
+ // Skip if already a component
21
+ if (node.metadata.isComponent) {
22
+ return;
23
+ }
24
+ // Generate a signature for this node
25
+ const signature = this.generateSignature(node);
26
+ // Add to component map
27
+ if (!this.componentMap.has(signature)) {
28
+ this.componentMap.set(signature, []);
29
+ }
30
+ this.componentMap.get(signature).push(node);
31
+ // Recursively collect from children
32
+ node.children.forEach((child) => this.collectComponents(child));
33
+ }
34
+ markComponents(node) {
35
+ const signature = this.generateSignature(node);
36
+ const instances = this.componentMap.get(signature) || [];
37
+ // Mark as component if repeated (appears more than once)
38
+ // But NEVER convert Text, Image, or Shape nodes to Component
39
+ if (instances.length > 1 &&
40
+ !node.metadata.isComponent &&
41
+ node.type !== 'Text' &&
42
+ node.type !== 'Image' &&
43
+ node.type !== 'Shape') {
44
+ return {
45
+ ...node,
46
+ type: 'Component',
47
+ metadata: {
48
+ ...node.metadata,
49
+ isComponent: true,
50
+ componentName: this.generateComponentName(node),
51
+ },
52
+ children: node.children.map((child) => this.markComponents(child)),
53
+ };
54
+ }
55
+ // Recursively process children
56
+ return {
57
+ ...node,
58
+ children: node.children.map((child) => this.markComponents(child)),
59
+ };
60
+ }
61
+ generateSignature(node) {
62
+ // Generate a signature based on structure and styles
63
+ const parts = [
64
+ node.type,
65
+ node.children.length.toString(),
66
+ node.layout.display,
67
+ JSON.stringify(node.styles.backgroundColor),
68
+ node.styles.borderRadius?.toString() || '',
69
+ ];
70
+ return parts.join('|');
71
+ }
72
+ generateComponentName(node) {
73
+ // Generate a meaningful component name
74
+ if (node.name && node.name !== 'Frame' && node.name !== 'Group') {
75
+ return node.name;
76
+ }
77
+ // Generate based on type
78
+ switch (node.type) {
79
+ case 'Text':
80
+ return 'TextComponent';
81
+ case 'Image':
82
+ return 'ImageComponent';
83
+ case 'Shape':
84
+ return 'ShapeComponent';
85
+ default:
86
+ return 'Component';
87
+ }
88
+ }
89
+ }
90
+ exports.ComponentExtractor = ComponentExtractor;
91
+ //# sourceMappingURL=ComponentExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComponentExtractor.js","sourceRoot":"","sources":["../../../src/transformation/transformers/ComponentExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ASTNode } from '../types';
2
+ import type { Transformer } from '../TransformationPipeline';
3
+ /**
4
+ * Preserve Figma layer structure for better readability
5
+ * Instead of aggressive flattening, keep meaningful layer hierarchy
6
+ */
7
+ export declare class FigmaLayerPreserver implements Transformer {
8
+ name: string;
9
+ transform(node: ASTNode): ASTNode;
10
+ private preserveStructure;
11
+ private shouldRemove;
12
+ private groupBySemanticMeaning;
13
+ }
14
+ //# sourceMappingURL=FigmaLayerPreserver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FigmaLayerPreserver.d.ts","sourceRoot":"","sources":["../../../src/transformation/transformers/FigmaLayerPreserver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,WAAW;IACrD,IAAI,SAA0B;IAE9B,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;IAIjC,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,sBAAsB;CAK/B"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FigmaLayerPreserver = void 0;
4
+ /**
5
+ * Preserve Figma layer structure for better readability
6
+ * Instead of aggressive flattening, keep meaningful layer hierarchy
7
+ */
8
+ class FigmaLayerPreserver {
9
+ constructor() {
10
+ this.name = 'figma-layer-preserver';
11
+ }
12
+ transform(node) {
13
+ return this.preserveStructure(node);
14
+ }
15
+ preserveStructure(node) {
16
+ // Recursively process children first
17
+ const processedChildren = node.children
18
+ .map(child => this.preserveStructure(child))
19
+ .filter(child => !this.shouldRemove(child));
20
+ // Group children by semantic meaning
21
+ const groupedChildren = this.groupBySemanticMeaning(processedChildren);
22
+ return {
23
+ ...node,
24
+ children: groupedChildren,
25
+ metadata: {
26
+ ...node.metadata,
27
+ // Preserve original Figma layer name for reference
28
+ figmaLayerName: node.name,
29
+ },
30
+ };
31
+ }
32
+ shouldRemove(node) {
33
+ // Only remove truly invisible or empty nodes
34
+ if (node.styles.opacity === 0)
35
+ return true;
36
+ if (node.layout.size.width === 0 && node.layout.size.height === 0)
37
+ return true;
38
+ // Keep everything else to preserve Figma structure
39
+ return false;
40
+ }
41
+ groupBySemanticMeaning(children) {
42
+ // Don't flatten - keep the original structure
43
+ // This makes the generated code match Figma layers 1:1
44
+ return children;
45
+ }
46
+ }
47
+ exports.FigmaLayerPreserver = FigmaLayerPreserver;
48
+ //# sourceMappingURL=FigmaLayerPreserver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FigmaLayerPreserver.js","sourceRoot":"","sources":["../../../src/transformation/transformers/FigmaLayerPreserver.ts"],"names":[],"mappings":";;;AAGA;;;GAGG;AACH,MAAa,mBAAmB;IAAhC;QACE,SAAI,GAAG,uBAAuB,CAAA;IAwChC,CAAC;IAtCC,SAAS,CAAC,IAAa;QACrB,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAA;IACrC,CAAC;IAEO,iBAAiB,CAAC,IAAa;QACrC,qCAAqC;QACrC,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ;aACpC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;aAC3C,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;QAE7C,qCAAqC;QACrC,MAAM,eAAe,GAAG,IAAI,CAAC,sBAAsB,CAAC,iBAAiB,CAAC,CAAA;QAEtE,OAAO;YACL,GAAG,IAAI;YACP,QAAQ,EAAE,eAAe;YACzB,QAAQ,EAAE;gBACR,GAAG,IAAI,CAAC,QAAQ;gBAChB,mDAAmD;gBACnD,cAAc,EAAE,IAAI,CAAC,IAAI;aAC1B;SACF,CAAA;IACH,CAAC;IAEO,YAAY,CAAC,IAAa;QAChC,6CAA6C;QAC7C,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QAC1C,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QAE9E,mDAAmD;QACnD,OAAO,KAAK,CAAA;IACd,CAAC;IAEO,sBAAsB,CAAC,QAAmB;QAChD,8CAA8C;QAC9C,uDAAuD;QACvD,OAAO,QAAQ,CAAA;IACjB,CAAC;CACF;AAzCD,kDAyCC"}
@@ -0,0 +1,16 @@
1
+ import type { ASTNode } from '../types';
2
+ import type { Transformer } from '../TransformationPipeline';
3
+ /**
4
+ * Optimize AST structure while preserving Figma layer hierarchy
5
+ * - Remove only truly invisible/empty nodes
6
+ * - Keep meaningful layer names
7
+ * - Preserve semantic structure
8
+ */
9
+ export declare class FigmaStructureOptimizer implements Transformer {
10
+ name: string;
11
+ transform(node: ASTNode): ASTNode;
12
+ private optimizeNode;
13
+ private isInvisible;
14
+ private isEmptyContainer;
15
+ }
16
+ //# sourceMappingURL=FigmaStructureOptimizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FigmaStructureOptimizer.d.ts","sourceRoot":"","sources":["../../../src/transformation/transformers/FigmaStructureOptimizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,uBAAwB,YAAW,WAAW;IACzD,IAAI,SAA+B;IAEnC,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;IAMjC,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,gBAAgB;CAezB"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FigmaStructureOptimizer = void 0;
4
+ /**
5
+ * Optimize AST structure while preserving Figma layer hierarchy
6
+ * - Remove only truly invisible/empty nodes
7
+ * - Keep meaningful layer names
8
+ * - Preserve semantic structure
9
+ */
10
+ class FigmaStructureOptimizer {
11
+ constructor() {
12
+ this.name = 'figma-structure-optimizer';
13
+ }
14
+ transform(node) {
15
+ const optimized = this.optimizeNode(node);
16
+ // Root node should never be null
17
+ return optimized || node;
18
+ }
19
+ optimizeNode(node) {
20
+ // Remove invisible nodes
21
+ if (this.isInvisible(node)) {
22
+ return null;
23
+ }
24
+ // Recursively optimize children
25
+ const optimizedChildren = node.children
26
+ .map((child) => this.optimizeNode(child))
27
+ .filter((child) => child !== null);
28
+ // Remove empty containers without visual properties
29
+ if (this.isEmptyContainer(node, optimizedChildren)) {
30
+ return null;
31
+ }
32
+ return {
33
+ ...node,
34
+ children: optimizedChildren,
35
+ };
36
+ }
37
+ isInvisible(node) {
38
+ // Only remove if truly invisible
39
+ if (node.styles.opacity === 0)
40
+ return true;
41
+ if (node.layout.size.width === 0 && node.layout.size.height === 0)
42
+ return true;
43
+ return false;
44
+ }
45
+ isEmptyContainer(node, children) {
46
+ // Don't remove if has children
47
+ if (children.length > 0)
48
+ return false;
49
+ // Don't remove if has visual styles
50
+ if (node.styles.backgroundColor)
51
+ return false;
52
+ if (node.styles.border)
53
+ return false;
54
+ if (node.styles.borderRadius)
55
+ return false;
56
+ if (node.styles.boxShadow && node.styles.boxShadow.length > 0)
57
+ return false;
58
+ // Don't remove if it's an image or text
59
+ if (node.type === 'Image' || node.type === 'Text')
60
+ return false;
61
+ return true;
62
+ }
63
+ }
64
+ exports.FigmaStructureOptimizer = FigmaStructureOptimizer;
65
+ //# sourceMappingURL=FigmaStructureOptimizer.js.map