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.
- package/CHANGELOG.md +55 -0
- package/LICENSE +21 -0
- package/QUICKSTART.md +198 -0
- package/README.md +149 -0
- package/dist/FigmaToCodeAgent.d.ts +55 -0
- package/dist/FigmaToCodeAgent.d.ts.map +1 -0
- package/dist/FigmaToCodeAgent.js +251 -0
- package/dist/FigmaToCodeAgent.js.map +1 -0
- package/dist/assets/index.d.ts +6 -0
- package/dist/assets/index.d.ts.map +1 -0
- package/dist/assets/index.js +7 -0
- package/dist/assets/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +261 -0
- package/dist/cli.js.map +1 -0
- package/dist/extraction/FigmaAPIClient.d.ts +53 -0
- package/dist/extraction/FigmaAPIClient.d.ts.map +1 -0
- package/dist/extraction/FigmaAPIClient.js +275 -0
- package/dist/extraction/FigmaAPIClient.js.map +1 -0
- package/dist/extraction/FigmaCache.d.ts +28 -0
- package/dist/extraction/FigmaCache.d.ts.map +1 -0
- package/dist/extraction/FigmaCache.js +120 -0
- package/dist/extraction/FigmaCache.js.map +1 -0
- package/dist/extraction/MCPClient.d.ts +75 -0
- package/dist/extraction/MCPClient.d.ts.map +1 -0
- package/dist/extraction/MCPClient.js +254 -0
- package/dist/extraction/MCPClient.js.map +1 -0
- package/dist/extraction/index.d.ts +9 -0
- package/dist/extraction/index.d.ts.map +1 -0
- package/dist/extraction/index.js +27 -0
- package/dist/extraction/index.js.map +1 -0
- package/dist/extraction/types.d.ts +122 -0
- package/dist/extraction/types.d.ts.map +1 -0
- package/dist/extraction/types.js +6 -0
- package/dist/extraction/types.js.map +1 -0
- package/dist/generation/AICodeOptimizer.d.ts +10 -0
- package/dist/generation/AICodeOptimizer.d.ts.map +1 -0
- package/dist/generation/AICodeOptimizer.js +33 -0
- package/dist/generation/AICodeOptimizer.js.map +1 -0
- package/dist/generation/ReactGenerator.d.ts +27 -0
- package/dist/generation/ReactGenerator.d.ts.map +1 -0
- package/dist/generation/ReactGenerator.js +423 -0
- package/dist/generation/ReactGenerator.js.map +1 -0
- package/dist/generation/VueGenerator.d.ts +23 -0
- package/dist/generation/VueGenerator.d.ts.map +1 -0
- package/dist/generation/VueGenerator.js +337 -0
- package/dist/generation/VueGenerator.js.map +1 -0
- package/dist/generation/index.d.ts +6 -0
- package/dist/generation/index.d.ts.map +1 -0
- package/dist/generation/index.js +7 -0
- package/dist/generation/index.js.map +1 -0
- package/dist/generation/types.d.ts +24 -0
- package/dist/generation/types.d.ts.map +1 -0
- package/dist/generation/types.js +3 -0
- package/dist/generation/types.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/BedrockProvider.d.ts +8 -0
- package/dist/llm/BedrockProvider.d.ts.map +1 -0
- package/dist/llm/BedrockProvider.js +34 -0
- package/dist/llm/BedrockProvider.js.map +1 -0
- package/dist/llm/LLMFactory.d.ts +5 -0
- package/dist/llm/LLMFactory.d.ts.map +1 -0
- package/dist/llm/LLMFactory.js +21 -0
- package/dist/llm/LLMFactory.js.map +1 -0
- package/dist/llm/OpenAIProvider.d.ts +7 -0
- package/dist/llm/OpenAIProvider.d.ts.map +1 -0
- package/dist/llm/OpenAIProvider.js +34 -0
- package/dist/llm/OpenAIProvider.js.map +1 -0
- package/dist/llm/index.d.ts +5 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +21 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/types.d.ts +23 -0
- package/dist/llm/types.d.ts.map +1 -0
- package/dist/llm/types.js +3 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/transformation/ASTFactory.d.ts +92 -0
- package/dist/transformation/ASTFactory.d.ts.map +1 -0
- package/dist/transformation/ASTFactory.js +240 -0
- package/dist/transformation/ASTFactory.js.map +1 -0
- package/dist/transformation/ASTParser.d.ts +13 -0
- package/dist/transformation/ASTParser.d.ts.map +1 -0
- package/dist/transformation/ASTParser.js +177 -0
- package/dist/transformation/ASTParser.js.map +1 -0
- package/dist/transformation/TransformationPipeline.d.ts +31 -0
- package/dist/transformation/TransformationPipeline.d.ts.map +1 -0
- package/dist/transformation/TransformationPipeline.js +42 -0
- package/dist/transformation/TransformationPipeline.js.map +1 -0
- package/dist/transformation/index.d.ts +7 -0
- package/dist/transformation/index.d.ts.map +1 -0
- package/dist/transformation/index.js +25 -0
- package/dist/transformation/index.js.map +1 -0
- package/dist/transformation/transformers/AIComponentSplitter.d.ts +14 -0
- package/dist/transformation/transformers/AIComponentSplitter.d.ts.map +1 -0
- package/dist/transformation/transformers/AIComponentSplitter.js +71 -0
- package/dist/transformation/transformers/AIComponentSplitter.js.map +1 -0
- package/dist/transformation/transformers/AILayoutAnalyzer.d.ts +18 -0
- package/dist/transformation/transformers/AILayoutAnalyzer.d.ts.map +1 -0
- package/dist/transformation/transformers/AILayoutAnalyzer.js +125 -0
- package/dist/transformation/transformers/AILayoutAnalyzer.js.map +1 -0
- package/dist/transformation/transformers/AISemanticNamer.d.ts +12 -0
- package/dist/transformation/transformers/AISemanticNamer.d.ts.map +1 -0
- package/dist/transformation/transformers/AISemanticNamer.js +50 -0
- package/dist/transformation/transformers/AISemanticNamer.js.map +1 -0
- package/dist/transformation/transformers/ComponentExtractor.d.ts +16 -0
- package/dist/transformation/transformers/ComponentExtractor.d.ts.map +1 -0
- package/dist/transformation/transformers/ComponentExtractor.js +91 -0
- package/dist/transformation/transformers/ComponentExtractor.js.map +1 -0
- package/dist/transformation/transformers/FigmaLayerPreserver.d.ts +14 -0
- package/dist/transformation/transformers/FigmaLayerPreserver.d.ts.map +1 -0
- package/dist/transformation/transformers/FigmaLayerPreserver.js +48 -0
- package/dist/transformation/transformers/FigmaLayerPreserver.js.map +1 -0
- package/dist/transformation/transformers/FigmaStructureOptimizer.d.ts +16 -0
- package/dist/transformation/transformers/FigmaStructureOptimizer.d.ts.map +1 -0
- package/dist/transformation/transformers/FigmaStructureOptimizer.js +65 -0
- package/dist/transformation/transformers/FigmaStructureOptimizer.js.map +1 -0
- package/dist/transformation/transformers/FlattenTransformer.d.ts +15 -0
- package/dist/transformation/transformers/FlattenTransformer.d.ts.map +1 -0
- package/dist/transformation/transformers/FlattenTransformer.js +69 -0
- package/dist/transformation/transformers/FlattenTransformer.js.map +1 -0
- package/dist/transformation/transformers/LayoutOptimizer.d.ts +15 -0
- package/dist/transformation/transformers/LayoutOptimizer.d.ts.map +1 -0
- package/dist/transformation/transformers/LayoutOptimizer.js +63 -0
- package/dist/transformation/transformers/LayoutOptimizer.js.map +1 -0
- package/dist/transformation/transformers/SemanticNamer.d.ts +14 -0
- package/dist/transformation/transformers/SemanticNamer.d.ts.map +1 -0
- package/dist/transformation/transformers/SemanticNamer.js +65 -0
- package/dist/transformation/transformers/SemanticNamer.js.map +1 -0
- package/dist/transformation/transformers/SimplifyTransformer.d.ts +23 -0
- package/dist/transformation/transformers/SimplifyTransformer.d.ts.map +1 -0
- package/dist/transformation/transformers/SimplifyTransformer.js +138 -0
- package/dist/transformation/transformers/SimplifyTransformer.js.map +1 -0
- package/dist/transformation/types.d.ts +129 -0
- package/dist/transformation/types.d.ts.map +1 -0
- package/dist/transformation/types.js +7 -0
- package/dist/transformation/types.js.map +1 -0
- package/dist/validation/index.d.ts +6 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +7 -0
- package/dist/validation/index.js.map +1 -0
- package/package.json +81 -0
- package/test-app/test-react/index.html +19 -0
- package/test-app/test-react/package.json +16 -0
- package/test-app/test-react/src/Component.jsx +146 -0
- package/test-app/test-react/src/Component.module.css +572 -0
- package/test-app/test-react/src/Homepage.jsx +53 -0
- package/test-app/test-react/src/Homepage.module.css +218 -0
- package/test-app/test-react/src/ProductPage.jsx +74 -0
- package/test-app/test-react/src/ProductPage.module.css +357 -0
- package/test-app/test-react/src/ShoppingCart.jsx +151 -0
- package/test-app/test-react/src/ShoppingCart.module.css +739 -0
- package/test-app/test-react/src/main.jsx +9 -0
- package/test-app/test-react/vite.config.js +6 -0
- package/test-app/test-vue/index.html +19 -0
- package/test-app/test-vue/package.json +15 -0
- package/test-app/test-vue/src/App.vue +16 -0
- package/test-app/test-vue/src/Component.vue +723 -0
- package/test-app/test-vue/src/Homepage.vue +271 -0
- package/test-app/test-vue/src/ProductPage.vue +431 -0
- package/test-app/test-vue/src/ShoppingCart.vue +890 -0
- package/test-app/test-vue/src/main.js +4 -0
- package/test-app/test-vue/vite.config.js +6 -0
|
@@ -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
|