figma-preview-mcp 0.2.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 (42) hide show
  1. package/README.md +220 -0
  2. package/dist/ast-enricher.d.ts +80 -0
  3. package/dist/ast-enricher.d.ts.map +1 -0
  4. package/dist/ast-enricher.js +318 -0
  5. package/dist/ast-enricher.js.map +1 -0
  6. package/dist/ast-module-splitter.d.ts +106 -0
  7. package/dist/ast-module-splitter.d.ts.map +1 -0
  8. package/dist/ast-module-splitter.js +325 -0
  9. package/dist/ast-module-splitter.js.map +1 -0
  10. package/dist/bounds-cache.d.ts +48 -0
  11. package/dist/bounds-cache.d.ts.map +1 -0
  12. package/dist/bounds-cache.js +71 -0
  13. package/dist/bounds-cache.js.map +1 -0
  14. package/dist/image-downloader.d.ts +20 -0
  15. package/dist/image-downloader.d.ts.map +1 -0
  16. package/dist/image-downloader.js +248 -0
  17. package/dist/image-downloader.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +1554 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/layout-inference.d.ts +98 -0
  23. package/dist/layout-inference.d.ts.map +1 -0
  24. package/dist/layout-inference.js +486 -0
  25. package/dist/layout-inference.js.map +1 -0
  26. package/dist/layout-verifier.d.ts +91 -0
  27. package/dist/layout-verifier.d.ts.map +1 -0
  28. package/dist/layout-verifier.js +318 -0
  29. package/dist/layout-verifier.js.map +1 -0
  30. package/dist/parser.d.ts +120 -0
  31. package/dist/parser.d.ts.map +1 -0
  32. package/dist/parser.js +310 -0
  33. package/dist/parser.js.map +1 -0
  34. package/dist/renderer.d.ts +8 -0
  35. package/dist/renderer.d.ts.map +1 -0
  36. package/dist/renderer.js +639 -0
  37. package/dist/renderer.js.map +1 -0
  38. package/dist/server.d.ts +7 -0
  39. package/dist/server.d.ts.map +1 -0
  40. package/dist/server.js +93 -0
  41. package/dist/server.js.map +1 -0
  42. package/package.json +55 -0
@@ -0,0 +1,106 @@
1
+ import type { EnrichedAST, EnrichedASTNode } from './ast-enricher.js';
2
+ export interface ExportAsset {
3
+ nodeId: string;
4
+ name: string;
5
+ bounds: {
6
+ width: number;
7
+ height: number;
8
+ };
9
+ suggestedFormat: 'png' | 'svg' | 'jpg';
10
+ }
11
+ export interface ModuleEntry {
12
+ index: number;
13
+ name: string;
14
+ /** nodeId of the first child in this module group */
15
+ nodeId: string;
16
+ file: string;
17
+ nodeCount: number;
18
+ childNodeIds: string[];
19
+ bounds: {
20
+ y: number;
21
+ height: number;
22
+ };
23
+ }
24
+ export interface SkeletonChild {
25
+ nodeId: string;
26
+ name: string;
27
+ type: string;
28
+ bounds: {
29
+ x: number;
30
+ y: number;
31
+ width: number;
32
+ height: number;
33
+ };
34
+ moduleFile: string;
35
+ }
36
+ export interface ModuleMap {
37
+ fileKey: string;
38
+ rootNodeId: string;
39
+ totalNodes: number;
40
+ splitThreshold: number;
41
+ viewport: {
42
+ width: number;
43
+ height: number;
44
+ };
45
+ skeletonFile: string;
46
+ modules: ModuleEntry[];
47
+ exportAssets: ExportAsset[];
48
+ }
49
+ /**
50
+ * Convert a Figma node name to a kebab-case file-safe string.
51
+ * e.g. "Hero Section" → "hero-section", "FeatureCards_v2" → "featurecards-v2"
52
+ */
53
+ export declare function toKebabCase(name: string): string;
54
+ /**
55
+ * Recursively count all nodes in an EnrichedASTNode subtree.
56
+ * Graphic subtrees (flags.isGraphicSubtree) are counted as 1 since their
57
+ * children are already pruned by the enricher.
58
+ */
59
+ export declare function countSubtreeNodes(node: EnrichedASTNode): number;
60
+ /**
61
+ * Find the effective split point: if the root has a single child container
62
+ * whose subtree exceeds the threshold, "unwrap" one level and split its
63
+ * children instead. Returns the node whose .children should be grouped.
64
+ */
65
+ export declare function findSplitTarget(root: EnrichedASTNode, threshold: number): EnrichedASTNode;
66
+ /**
67
+ * Split root.children into module groups using greedy sequential grouping.
68
+ *
69
+ * Algorithm:
70
+ * - If root has a single large child, "unwrap" to split at the next level
71
+ * - Iterate children in order
72
+ * - Accumulate into current group until adding next child would exceed threshold
73
+ * - A single child whose subtree count > threshold is recursively split into
74
+ * sub-modules by diving into its children
75
+ * - Returns { splitTarget, modules } where splitTarget is the actual node being split
76
+ */
77
+ export interface SplitResult {
78
+ splitTarget: EnrichedASTNode;
79
+ modules: EnrichedASTNode[][];
80
+ }
81
+ export declare function splitIntoModules(root: EnrichedASTNode, threshold: number): SplitResult;
82
+ /**
83
+ * Build a skeleton AST: root node with full layout but children replaced
84
+ * by lightweight placeholders that reference their module file.
85
+ */
86
+ export declare function generateSkeleton(root: EnrichedASTNode, moduleEntries: ModuleEntry[]): Record<string, unknown>;
87
+ /**
88
+ * Traverse all nodes and collect graphic/image nodes for export.
89
+ */
90
+ export declare function collectExportAssets(root: EnrichedASTNode): ExportAsset[];
91
+ /**
92
+ * Build the module-map data structure.
93
+ */
94
+ export declare function buildModuleMap(ast: EnrichedAST, moduleGroups: EnrichedASTNode[][], exportAssets: ExportAsset[], threshold: number): ModuleMap;
95
+ /**
96
+ * Split an EnrichedAST into modules and write all files to outputDir.
97
+ *
98
+ * Files written:
99
+ * - module-map.json
100
+ * - skeleton.json
101
+ * - module-{index}-{name}.ast.json (one per module)
102
+ *
103
+ * Returns the ModuleMap for the caller to use as tool response.
104
+ */
105
+ export declare function writeModuleFiles(ast: EnrichedAST, outputDir: string, threshold: number): Promise<ModuleMap>;
106
+ //# sourceMappingURL=ast-module-splitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-module-splitter.d.ts","sourceRoot":"","sources":["../src/ast-module-splitter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAoB,MAAM,mBAAmB,CAAC;AAIxF,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,eAAe,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B;AAID;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQhD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAQ/D;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CAYzF;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,eAAe,CAAC;IAC7B,OAAO,EAAE,eAAe,EAAE,EAAE,CAAC;CAC9B;AA0DD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,MAAM,GAChB,WAAW,CA0Cb;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,eAAe,EACrB,aAAa,EAAE,WAAW,EAAE,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzB;AAID;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,WAAW,EAAE,CAuBxE;AAcD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,WAAW,EAChB,YAAY,EAAE,eAAe,EAAE,EAAE,EACjC,YAAY,EAAE,WAAW,EAAE,EAC3B,SAAS,EAAE,MAAM,GAChB,SAAS,CAgCX;AA8BD;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,SAAS,CAAC,CAwEpB"}
@@ -0,0 +1,325 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ // ─── Helpers ────────────────────────────────────────────────────────────────
4
+ /**
5
+ * Convert a Figma node name to a kebab-case file-safe string.
6
+ * e.g. "Hero Section" → "hero-section", "FeatureCards_v2" → "featurecards-v2"
7
+ */
8
+ export function toKebabCase(name) {
9
+ return name
10
+ .replace(/([a-z])([A-Z])/g, '$1-$2') // camelCase → camel-Case
11
+ .replace(/[\s_/\\]+/g, '-') // whitespace/underscores/slashes → dash
12
+ .replace(/[^a-zA-Z0-9-]/g, '') // strip non-alphanumeric
13
+ .replace(/-+/g, '-') // collapse multiple dashes
14
+ .replace(/^-|-$/g, '') // trim leading/trailing dashes
15
+ .toLowerCase();
16
+ }
17
+ /**
18
+ * Recursively count all nodes in an EnrichedASTNode subtree.
19
+ * Graphic subtrees (flags.isGraphicSubtree) are counted as 1 since their
20
+ * children are already pruned by the enricher.
21
+ */
22
+ export function countSubtreeNodes(node) {
23
+ let count = 1;
24
+ if (node.children) {
25
+ for (const child of node.children) {
26
+ count += countSubtreeNodes(child);
27
+ }
28
+ }
29
+ return count;
30
+ }
31
+ // ─── Core Splitting Algorithm ───────────────────────────────────────────────
32
+ /**
33
+ * Find the effective split point: if the root has a single child container
34
+ * whose subtree exceeds the threshold, "unwrap" one level and split its
35
+ * children instead. Returns the node whose .children should be grouped.
36
+ */
37
+ export function findSplitTarget(root, threshold) {
38
+ let target = root;
39
+ while (target.children &&
40
+ target.children.length === 1 &&
41
+ countSubtreeNodes(target.children[0]) > threshold &&
42
+ target.children[0].children &&
43
+ target.children[0].children.length > 1) {
44
+ target = target.children[0];
45
+ }
46
+ return target;
47
+ }
48
+ /**
49
+ * Recursively split a single oversized node into smaller groups.
50
+ * Dives into its children until groups fit within the threshold.
51
+ */
52
+ function splitOversizedNode(node, threshold) {
53
+ // Try to unwrap to find a level with multiple children
54
+ const target = findSplitTarget(node, threshold);
55
+ const children = target.children ?? [];
56
+ // If no children or only one child that can't be further split, return as-is
57
+ if (children.length <= 1) {
58
+ return [[node]];
59
+ }
60
+ const subModules = [];
61
+ let currentGroup = [];
62
+ let currentCount = 0;
63
+ for (const child of children) {
64
+ const childCount = countSubtreeNodes(child);
65
+ if (childCount > threshold) {
66
+ // Flush current group first
67
+ if (currentGroup.length > 0) {
68
+ subModules.push(currentGroup);
69
+ currentGroup = [];
70
+ currentCount = 0;
71
+ }
72
+ // Recursively split this oversized child
73
+ const deeperModules = splitOversizedNode(child, threshold);
74
+ subModules.push(...deeperModules);
75
+ }
76
+ else if (currentCount + childCount > threshold) {
77
+ // Adding this child would exceed threshold: flush and start new group
78
+ if (currentGroup.length > 0) {
79
+ subModules.push(currentGroup);
80
+ }
81
+ currentGroup = [child];
82
+ currentCount = childCount;
83
+ }
84
+ else {
85
+ // Fits in current group
86
+ currentGroup.push(child);
87
+ currentCount += childCount;
88
+ }
89
+ }
90
+ // Flush remaining
91
+ if (currentGroup.length > 0) {
92
+ subModules.push(currentGroup);
93
+ }
94
+ return subModules;
95
+ }
96
+ export function splitIntoModules(root, threshold) {
97
+ const splitTarget = findSplitTarget(root, threshold);
98
+ const children = splitTarget.children ?? [];
99
+ if (children.length === 0)
100
+ return { splitTarget, modules: [[]] };
101
+ const modules = [];
102
+ let currentGroup = [];
103
+ let currentCount = 0;
104
+ for (const child of children) {
105
+ const childCount = countSubtreeNodes(child);
106
+ if (childCount > threshold) {
107
+ // Flush current group first
108
+ if (currentGroup.length > 0) {
109
+ modules.push(currentGroup);
110
+ currentGroup = [];
111
+ currentCount = 0;
112
+ }
113
+ // Recursively split this oversized child into sub-modules
114
+ const subModules = splitOversizedNode(child, threshold);
115
+ modules.push(...subModules);
116
+ }
117
+ else if (currentCount + childCount > threshold) {
118
+ // Adding this child would exceed threshold: flush and start new group
119
+ if (currentGroup.length > 0) {
120
+ modules.push(currentGroup);
121
+ }
122
+ currentGroup = [child];
123
+ currentCount = childCount;
124
+ }
125
+ else {
126
+ // Fits in current group
127
+ currentGroup.push(child);
128
+ currentCount += childCount;
129
+ }
130
+ }
131
+ // Flush remaining
132
+ if (currentGroup.length > 0) {
133
+ modules.push(currentGroup);
134
+ }
135
+ return { splitTarget, modules };
136
+ }
137
+ // ─── Skeleton Generation ────────────────────────────────────────────────────
138
+ /**
139
+ * Build a skeleton AST: root node with full layout but children replaced
140
+ * by lightweight placeholders that reference their module file.
141
+ */
142
+ export function generateSkeleton(root, moduleEntries) {
143
+ // Build a map from childNodeId → moduleFile for quick lookup
144
+ const childToModuleFile = new Map();
145
+ for (const mod of moduleEntries) {
146
+ for (const childId of mod.childNodeIds) {
147
+ childToModuleFile.set(childId, mod.file);
148
+ }
149
+ }
150
+ const placeholderChildren = (root.children ?? []).map(child => ({
151
+ nodeId: child.nodeId,
152
+ name: child.name,
153
+ type: child.type,
154
+ bounds: { ...child.bounds },
155
+ moduleFile: childToModuleFile.get(child.nodeId) ?? 'unknown',
156
+ }));
157
+ return {
158
+ nodeId: root.nodeId,
159
+ name: root.name,
160
+ type: root.type,
161
+ bounds: { ...root.bounds },
162
+ layout: { ...root.layout },
163
+ ...(root.style ? { style: { ...root.style } } : {}),
164
+ children: placeholderChildren,
165
+ };
166
+ }
167
+ // ─── Export Asset Collection ────────────────────────────────────────────────
168
+ /**
169
+ * Traverse all nodes and collect graphic/image nodes for export.
170
+ */
171
+ export function collectExportAssets(root) {
172
+ const assets = [];
173
+ const seenIds = new Set();
174
+ function walk(node) {
175
+ if ((node.flags?.isGraphicSubtree || node.image) && !seenIds.has(node.nodeId)) {
176
+ seenIds.add(node.nodeId);
177
+ assets.push({
178
+ nodeId: node.nodeId,
179
+ name: node.name,
180
+ bounds: { width: node.bounds.width, height: node.bounds.height },
181
+ suggestedFormat: node.image?.suggestedFormat ?? 'svg',
182
+ });
183
+ }
184
+ if (node.children) {
185
+ for (const child of node.children) {
186
+ walk(child);
187
+ }
188
+ }
189
+ }
190
+ walk(root);
191
+ return assets;
192
+ }
193
+ // ─── Module Map Builder ─────────────────────────────────────────────────────
194
+ /**
195
+ * Compute the combined bounds (y, height) of a group of children.
196
+ */
197
+ function computeGroupBounds(children) {
198
+ if (children.length === 0)
199
+ return { y: 0, height: 0 };
200
+ const minY = Math.min(...children.map(c => c.bounds.y));
201
+ const maxBottom = Math.max(...children.map(c => c.bounds.y + c.bounds.height));
202
+ return { y: minY, height: maxBottom - minY };
203
+ }
204
+ /**
205
+ * Build the module-map data structure.
206
+ */
207
+ export function buildModuleMap(ast, moduleGroups, exportAssets, threshold) {
208
+ const moduleEntries = moduleGroups.map((group, index) => {
209
+ const firstName = group[0]?.name ?? `module-${index}`;
210
+ const kebabName = toKebabCase(firstName);
211
+ const fileName = `module-${index}-${kebabName}.ast.json`;
212
+ let nodeCount = 0;
213
+ for (const child of group) {
214
+ nodeCount += countSubtreeNodes(child);
215
+ }
216
+ return {
217
+ index,
218
+ name: firstName,
219
+ nodeId: group[0]?.nodeId ?? '',
220
+ file: fileName,
221
+ nodeCount,
222
+ childNodeIds: group.map(c => c.nodeId),
223
+ bounds: computeGroupBounds(group),
224
+ };
225
+ });
226
+ return {
227
+ fileKey: ast.fileKey,
228
+ rootNodeId: ast.rootNodeId,
229
+ totalNodes: ast.stats.totalNodes,
230
+ splitThreshold: threshold,
231
+ viewport: { ...ast.viewport },
232
+ skeletonFile: 'skeleton.json',
233
+ modules: moduleEntries,
234
+ exportAssets,
235
+ };
236
+ }
237
+ // ─── Build stats for a sub-AST ──────────────────────────────────────────────
238
+ function buildSubStats(nodes) {
239
+ const stats = {
240
+ totalNodes: 0,
241
+ figmaLayoutNodes: 0,
242
+ inferredLayoutNodes: 0,
243
+ absoluteNodes: 0,
244
+ needsDetailFetch: 0,
245
+ };
246
+ function walk(node) {
247
+ stats.totalNodes++;
248
+ if (node.layout.source === 'figma')
249
+ stats.figmaLayoutNodes++;
250
+ else if (node.layout.source === 'inferred')
251
+ stats.inferredLayoutNodes++;
252
+ else if (node.layout.source === 'absolute')
253
+ stats.absoluteNodes++;
254
+ if (node.flags?.needsDetailFetch)
255
+ stats.needsDetailFetch++;
256
+ if (node.children)
257
+ node.children.forEach(walk);
258
+ }
259
+ for (const node of nodes) {
260
+ walk(node);
261
+ }
262
+ return stats;
263
+ }
264
+ // ─── File Writing (Main Entry Point) ────────────────────────────────────────
265
+ /**
266
+ * Split an EnrichedAST into modules and write all files to outputDir.
267
+ *
268
+ * Files written:
269
+ * - module-map.json
270
+ * - skeleton.json
271
+ * - module-{index}-{name}.ast.json (one per module)
272
+ *
273
+ * Returns the ModuleMap for the caller to use as tool response.
274
+ */
275
+ export async function writeModuleFiles(ast, outputDir, threshold) {
276
+ // 1. Split into module groups (may unwrap single-child containers)
277
+ const { splitTarget, modules: moduleGroups } = splitIntoModules(ast.root, threshold);
278
+ // 2. Collect export assets (from full tree)
279
+ const exportAssets = collectExportAssets(ast.root);
280
+ // 3. Build module map (using splitTarget as the effective root)
281
+ const moduleMap = buildModuleMap(ast, moduleGroups, exportAssets, threshold);
282
+ // 4. Generate skeleton from splitTarget (the node whose children are split)
283
+ const skeleton = generateSkeleton(splitTarget, moduleMap.modules);
284
+ // 5. Create output directory
285
+ await fs.promises.mkdir(outputDir, { recursive: true });
286
+ // 6. Write module-map.json
287
+ await fs.promises.writeFile(path.join(outputDir, 'module-map.json'), JSON.stringify(moduleMap, null, 2), 'utf-8');
288
+ // 7. Write skeleton.json
289
+ await fs.promises.writeFile(path.join(outputDir, 'skeleton.json'), JSON.stringify(skeleton, null, 2), 'utf-8');
290
+ // 8. Write each module AST file
291
+ for (let i = 0; i < moduleGroups.length; i++) {
292
+ const group = moduleGroups[i];
293
+ const entry = moduleMap.modules[i];
294
+ const stats = buildSubStats(group);
295
+ // Build a synthetic root node that wraps this module's children
296
+ // Use the splitTarget's layout for the synthetic wrapper
297
+ const syntheticRoot = {
298
+ nodeId: splitTarget.nodeId,
299
+ name: `${splitTarget.name} [module-${i}]`,
300
+ type: splitTarget.type,
301
+ bounds: {
302
+ x: splitTarget.bounds.x,
303
+ y: entry.bounds.y,
304
+ width: splitTarget.bounds.width,
305
+ height: entry.bounds.height,
306
+ },
307
+ layout: { ...splitTarget.layout },
308
+ children: group,
309
+ };
310
+ const moduleAst = {
311
+ version: '1.0',
312
+ fileKey: ast.fileKey,
313
+ rootNodeId: ast.rootNodeId,
314
+ viewport: {
315
+ width: ast.viewport.width,
316
+ height: entry.bounds.height,
317
+ },
318
+ stats,
319
+ root: syntheticRoot,
320
+ };
321
+ await fs.promises.writeFile(path.join(outputDir, entry.file), JSON.stringify(moduleAst, null, 2), 'utf-8');
322
+ }
323
+ return moduleMap;
324
+ }
325
+ //# sourceMappingURL=ast-module-splitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-module-splitter.js","sourceRoot":"","sources":["../src/ast-module-splitter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { ParsedFigmaData } from './parser.js';
2
+ /**
3
+ * Bounds data for a single node, relative to the root node origin.
4
+ */
5
+ export interface NodeBounds {
6
+ x: number;
7
+ y: number;
8
+ width: number;
9
+ height: number;
10
+ }
11
+ /**
12
+ * Metadata for a single node used in diagnostic context.
13
+ */
14
+ export interface NodeMeta {
15
+ name: string;
16
+ type: string;
17
+ parentId: string | null;
18
+ }
19
+ /**
20
+ * Cached layout bounds data produced by render_preview,
21
+ * consumed by generate_layout_ast and verify_layout_bounds.
22
+ */
23
+ export interface LayoutBoundsCache {
24
+ fileKey: string;
25
+ rootNodeId: string;
26
+ rootWidth: number;
27
+ rootHeight: number;
28
+ /** nodeId → absolute bounds relative to root node */
29
+ bounds: Map<string, NodeBounds>;
30
+ /** nodeId → node metadata (name, type, parentId) */
31
+ nodeInfo: Map<string, NodeMeta>;
32
+ /** The full parsed node tree (for AST enrichment) */
33
+ nodeTree: ParsedFigmaData;
34
+ }
35
+ /**
36
+ * Build and store a LayoutBoundsCache from a fully processed nodeTree
37
+ * (after injectBounds has been called).
38
+ */
39
+ export declare function buildBoundsCache(nodeTree: ParsedFigmaData, fileKey: string, rootNodeId: string): LayoutBoundsCache;
40
+ /**
41
+ * Retrieve a cached LayoutBoundsCache, or null if not found.
42
+ */
43
+ export declare function getBoundsCache(fileKey: string, rootNodeId: string): LayoutBoundsCache | null;
44
+ /**
45
+ * Manually set a LayoutBoundsCache entry (e.g. for testing).
46
+ */
47
+ export declare function setBoundsCache(entry: LayoutBoundsCache): void;
48
+ //# sourceMappingURL=bounds-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounds-cache.d.ts","sourceRoot":"","sources":["../src/bounds-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAChC,oDAAoD;IACpD,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChC,qDAAqD;IACrD,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAWD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,iBAAiB,CAqDnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAG5F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAG7D"}
@@ -0,0 +1,71 @@
1
+ // Process-level singleton cache: cacheKey → LayoutBoundsCache
2
+ const cache = new Map();
3
+ function cacheKey(fileKey, rootNodeId) {
4
+ // Normalize ID format (colons)
5
+ const normalizedId = rootNodeId.replace(/-/g, ':');
6
+ return `${fileKey}:${normalizedId}`;
7
+ }
8
+ /**
9
+ * Build and store a LayoutBoundsCache from a fully processed nodeTree
10
+ * (after injectBounds has been called).
11
+ */
12
+ export function buildBoundsCache(nodeTree, fileKey, rootNodeId) {
13
+ const bounds = new Map();
14
+ const nodeInfo = new Map();
15
+ const rootNode = nodeTree.nodes[0];
16
+ const rootWidth = rootNode?.layout?.width ?? 0;
17
+ const rootHeight = rootNode?.layout?.height ?? 0;
18
+ function walk(node, parentId) {
19
+ const id = node.id;
20
+ // Store bounds (use _absX/_absY if available, fall back to layout x/y)
21
+ bounds.set(id, {
22
+ x: node._absX ?? node.layout?.x ?? 0,
23
+ y: node._absY ?? node.layout?.y ?? 0,
24
+ width: node.layout?.width ?? 0,
25
+ height: node.layout?.height ?? 0,
26
+ });
27
+ // Store metadata
28
+ nodeInfo.set(id, {
29
+ name: node.name,
30
+ type: node.type,
31
+ parentId,
32
+ });
33
+ // Recurse children
34
+ if (node.children) {
35
+ for (const child of node.children) {
36
+ walk(child, id);
37
+ }
38
+ }
39
+ }
40
+ for (const rootN of nodeTree.nodes) {
41
+ walk(rootN, null);
42
+ }
43
+ const entry = {
44
+ fileKey,
45
+ rootNodeId: rootNodeId.replace(/-/g, ':'),
46
+ rootWidth,
47
+ rootHeight,
48
+ bounds,
49
+ nodeInfo,
50
+ nodeTree,
51
+ };
52
+ // Store in singleton cache (overwrites existing entry for same key)
53
+ const key = cacheKey(fileKey, rootNodeId);
54
+ cache.set(key, entry);
55
+ return entry;
56
+ }
57
+ /**
58
+ * Retrieve a cached LayoutBoundsCache, or null if not found.
59
+ */
60
+ export function getBoundsCache(fileKey, rootNodeId) {
61
+ const key = cacheKey(fileKey, rootNodeId);
62
+ return cache.get(key) ?? null;
63
+ }
64
+ /**
65
+ * Manually set a LayoutBoundsCache entry (e.g. for testing).
66
+ */
67
+ export function setBoundsCache(entry) {
68
+ const key = cacheKey(entry.fileKey, entry.rootNodeId);
69
+ cache.set(key, entry);
70
+ }
71
+ //# sourceMappingURL=bounds-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounds-cache.js","sourceRoot":"","sources":["../src/bounds-cache.ts"],"names":[],"mappings":"AAsCA,8DAA8D;AAC9D,MAAM,KAAK,GAAG,IAAI,GAAG,EAA6B,CAAC;AAEnD,SAAS,QAAQ,CAAC,OAAe,EAAE,UAAkB;IACnD,+BAA+B;IAC/B,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,GAAG,OAAO,IAAI,YAAY,EAAE,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAAyB,EACzB,OAAe,EACf,UAAkB;IAElB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,QAAQ,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC;IAEjD,SAAS,IAAI,CAAC,IAAe,EAAE,QAAuB;QACpD,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QAEnB,uEAAuE;QACvE,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE;YACb,CAAC,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC;YACpC,CAAC,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC;YACpC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC;YAC9B,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;SACjC,CAAC,CAAC;QAEH,iBAAiB;QACjB,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ;SACT,CAAC,CAAC;QAEH,mBAAmB;QACnB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,KAAK,GAAsB;QAC/B,OAAO;QACP,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;QACzC,SAAS;QACT,UAAU;QACV,MAAM;QACN,QAAQ;QACR,QAAQ;KACT,CAAC;IAEF,oEAAoE;IACpE,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC1C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAEtB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,UAAkB;IAChE,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC1C,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAwB;IACrD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACtD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ParsedFigmaData } from './parser.js';
2
+ export type ImageMap = Map<string, string>;
3
+ /**
4
+ * Download a PNG screenshot of the given node (usually the root/preview node).
5
+ * Returns the local file path, or null on failure.
6
+ * Skips download if the file is already cached.
7
+ */
8
+ export declare function downloadRootScreenshot(fileKey: string, nodeId: string, token: string): Promise<string | null>;
9
+ /**
10
+ * Fetch absoluteBoundingBox for all given nodeIds from Figma REST API.
11
+ * Returns a map of nodeId -> { x, y, width, height } relative to the root node origin.
12
+ */
13
+ export declare function fetchAbsoluteBounds(fileKey: string, nodeIds: string[], token: string): Promise<Map<string, {
14
+ x: number;
15
+ y: number;
16
+ width: number;
17
+ height: number;
18
+ }>>;
19
+ export declare function downloadImages(data: ParsedFigmaData, fileKey: string, token: string): Promise<ImageMap>;
20
+ //# sourceMappingURL=image-downloader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-downloader.d.ts","sourceRoot":"","sources":["../src/image-downloader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAI3C;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA+CxB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAqD/E;AA0FD,wBAAsB,cAAc,CAClC,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,QAAQ,CAAC,CAgDnB"}