@bilalba/fig-mcp 1.0.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 (186) hide show
  1. package/README.md +112 -0
  2. package/dist/compare-get-vector.d.ts +2 -0
  3. package/dist/compare-get-vector.d.ts.map +1 -0
  4. package/dist/compare-get-vector.js +124 -0
  5. package/dist/compare-get-vector.js.map +1 -0
  6. package/dist/compare-mcp-vs-direct.d.ts +2 -0
  7. package/dist/compare-mcp-vs-direct.d.ts.map +1 -0
  8. package/dist/compare-mcp-vs-direct.js +173 -0
  9. package/dist/compare-mcp-vs-direct.js.map +1 -0
  10. package/dist/compare-renderers.d.ts +2 -0
  11. package/dist/compare-renderers.d.ts.map +1 -0
  12. package/dist/compare-renderers.js +110 -0
  13. package/dist/compare-renderers.js.map +1 -0
  14. package/dist/debug/debug-stroke-geom.d.ts +2 -0
  15. package/dist/debug/debug-stroke-geom.d.ts.map +1 -0
  16. package/dist/debug/debug-stroke-geom.js +67 -0
  17. package/dist/debug/debug-stroke-geom.js.map +1 -0
  18. package/dist/debug/debug-transforms.d.ts +2 -0
  19. package/dist/debug/debug-transforms.d.ts.map +1 -0
  20. package/dist/debug/debug-transforms.js +97 -0
  21. package/dist/debug/debug-transforms.js.map +1 -0
  22. package/dist/debug/debug-vertex.d.ts +2 -0
  23. package/dist/debug/debug-vertex.d.ts.map +1 -0
  24. package/dist/debug/debug-vertex.js +72 -0
  25. package/dist/debug/debug-vertex.js.map +1 -0
  26. package/dist/debug-group.d.ts +5 -0
  27. package/dist/debug-group.d.ts.map +1 -0
  28. package/dist/debug-group.js +44 -0
  29. package/dist/debug-group.js.map +1 -0
  30. package/dist/debug-stroke-geom.d.ts +2 -0
  31. package/dist/debug-stroke-geom.d.ts.map +1 -0
  32. package/dist/debug-stroke-geom.js +67 -0
  33. package/dist/debug-stroke-geom.js.map +1 -0
  34. package/dist/debug-transforms.d.ts +2 -0
  35. package/dist/debug-transforms.d.ts.map +1 -0
  36. package/dist/debug-transforms.js +97 -0
  37. package/dist/debug-transforms.js.map +1 -0
  38. package/dist/debug-vertex.d.ts +2 -0
  39. package/dist/debug-vertex.d.ts.map +1 -0
  40. package/dist/debug-vertex.js +72 -0
  41. package/dist/debug-vertex.js.map +1 -0
  42. package/dist/decode-vector-network.d.ts +5 -0
  43. package/dist/decode-vector-network.d.ts.map +1 -0
  44. package/dist/decode-vector-network.js +160 -0
  45. package/dist/decode-vector-network.js.map +1 -0
  46. package/dist/experimental/paint-utils.d.ts +35 -0
  47. package/dist/experimental/paint-utils.d.ts.map +1 -0
  48. package/dist/experimental/paint-utils.js +105 -0
  49. package/dist/experimental/paint-utils.js.map +1 -0
  50. package/dist/experimental/render-screen-v2.d.ts +32 -0
  51. package/dist/experimental/render-screen-v2.d.ts.map +1 -0
  52. package/dist/experimental/render-screen-v2.js +366 -0
  53. package/dist/experimental/render-screen-v2.js.map +1 -0
  54. package/dist/experimental/render-screen.d.ts +26 -0
  55. package/dist/experimental/render-screen.d.ts.map +1 -0
  56. package/dist/experimental/render-screen.js +547 -0
  57. package/dist/experimental/render-screen.js.map +1 -0
  58. package/dist/experimental/render-types.d.ts +43 -0
  59. package/dist/experimental/render-types.d.ts.map +1 -0
  60. package/dist/experimental/render-types.js +22 -0
  61. package/dist/experimental/render-types.js.map +1 -0
  62. package/dist/experimental/render-utils.d.ts +38 -0
  63. package/dist/experimental/render-utils.d.ts.map +1 -0
  64. package/dist/experimental/render-utils.js +126 -0
  65. package/dist/experimental/render-utils.js.map +1 -0
  66. package/dist/experimental/screenshot.d.ts +11 -0
  67. package/dist/experimental/screenshot.d.ts.map +1 -0
  68. package/dist/experimental/screenshot.js +26 -0
  69. package/dist/experimental/screenshot.js.map +1 -0
  70. package/dist/experimental/vector-renderer.d.ts +31 -0
  71. package/dist/experimental/vector-renderer.d.ts.map +1 -0
  72. package/dist/experimental/vector-renderer.js +427 -0
  73. package/dist/experimental/vector-renderer.js.map +1 -0
  74. package/dist/explore-images.d.ts +9 -0
  75. package/dist/explore-images.d.ts.map +1 -0
  76. package/dist/explore-images.js +307 -0
  77. package/dist/explore-images.js.map +1 -0
  78. package/dist/http-server.d.ts +8 -0
  79. package/dist/http-server.d.ts.map +1 -0
  80. package/dist/http-server.js +95 -0
  81. package/dist/http-server.js.map +1 -0
  82. package/dist/index.d.ts +9 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +34 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/inspect-fig.d.ts +16 -0
  87. package/dist/inspect-fig.d.ts.map +1 -0
  88. package/dist/inspect-fig.js +134 -0
  89. package/dist/inspect-fig.js.map +1 -0
  90. package/dist/inspect-frame.d.ts +2 -0
  91. package/dist/inspect-frame.d.ts.map +1 -0
  92. package/dist/inspect-frame.js +90 -0
  93. package/dist/inspect-frame.js.map +1 -0
  94. package/dist/inspect-nodes.d.ts +5 -0
  95. package/dist/inspect-nodes.d.ts.map +1 -0
  96. package/dist/inspect-nodes.js +193 -0
  97. package/dist/inspect-nodes.js.map +1 -0
  98. package/dist/mcp/server.d.ts +38 -0
  99. package/dist/mcp/server.d.ts.map +1 -0
  100. package/dist/mcp/server.js +1524 -0
  101. package/dist/mcp/server.js.map +1 -0
  102. package/dist/parser/fig-reader.d.ts +29 -0
  103. package/dist/parser/fig-reader.d.ts.map +1 -0
  104. package/dist/parser/fig-reader.js +182 -0
  105. package/dist/parser/fig-reader.js.map +1 -0
  106. package/dist/parser/index.d.ts +48 -0
  107. package/dist/parser/index.d.ts.map +1 -0
  108. package/dist/parser/index.js +106 -0
  109. package/dist/parser/index.js.map +1 -0
  110. package/dist/parser/kiwi-parser.d.ts +66 -0
  111. package/dist/parser/kiwi-parser.d.ts.map +1 -0
  112. package/dist/parser/kiwi-parser.js +491 -0
  113. package/dist/parser/kiwi-parser.js.map +1 -0
  114. package/dist/parser/layout-inference.d.ts +63 -0
  115. package/dist/parser/layout-inference.d.ts.map +1 -0
  116. package/dist/parser/layout-inference.js +446 -0
  117. package/dist/parser/layout-inference.js.map +1 -0
  118. package/dist/parser/types.d.ts +286 -0
  119. package/dist/parser/types.d.ts.map +1 -0
  120. package/dist/parser/types.js +6 -0
  121. package/dist/parser/types.js.map +1 -0
  122. package/dist/render-single.d.ts +2 -0
  123. package/dist/render-single.d.ts.map +1 -0
  124. package/dist/render-single.js +53 -0
  125. package/dist/render-single.js.map +1 -0
  126. package/dist/renderer/index.d.ts +16 -0
  127. package/dist/renderer/index.d.ts.map +1 -0
  128. package/dist/renderer/index.js +18 -0
  129. package/dist/renderer/index.js.map +1 -0
  130. package/dist/renderer/paint-utils.d.ts +35 -0
  131. package/dist/renderer/paint-utils.d.ts.map +1 -0
  132. package/dist/renderer/paint-utils.js +105 -0
  133. package/dist/renderer/paint-utils.js.map +1 -0
  134. package/dist/renderer/render-screen.d.ts +26 -0
  135. package/dist/renderer/render-screen.d.ts.map +1 -0
  136. package/dist/renderer/render-screen.js +547 -0
  137. package/dist/renderer/render-screen.js.map +1 -0
  138. package/dist/renderer/render-types.d.ts +43 -0
  139. package/dist/renderer/render-types.d.ts.map +1 -0
  140. package/dist/renderer/render-types.js +22 -0
  141. package/dist/renderer/render-types.js.map +1 -0
  142. package/dist/renderer/render-utils.d.ts +38 -0
  143. package/dist/renderer/render-utils.d.ts.map +1 -0
  144. package/dist/renderer/render-utils.js +126 -0
  145. package/dist/renderer/render-utils.js.map +1 -0
  146. package/dist/renderer/screenshot.d.ts +11 -0
  147. package/dist/renderer/screenshot.d.ts.map +1 -0
  148. package/dist/renderer/screenshot.js +26 -0
  149. package/dist/renderer/screenshot.js.map +1 -0
  150. package/dist/renderer/vector-renderer.d.ts +31 -0
  151. package/dist/renderer/vector-renderer.d.ts.map +1 -0
  152. package/dist/renderer/vector-renderer.js +427 -0
  153. package/dist/renderer/vector-renderer.js.map +1 -0
  154. package/dist/shared-config.d.ts +9 -0
  155. package/dist/shared-config.d.ts.map +1 -0
  156. package/dist/shared-config.js +9 -0
  157. package/dist/shared-config.js.map +1 -0
  158. package/dist/test-parser.d.ts +3 -0
  159. package/dist/test-parser.d.ts.map +1 -0
  160. package/dist/test-parser.js +74 -0
  161. package/dist/test-parser.js.map +1 -0
  162. package/dist/test-render-v2.d.ts +5 -0
  163. package/dist/test-render-v2.d.ts.map +1 -0
  164. package/dist/test-render-v2.js +76 -0
  165. package/dist/test-render-v2.js.map +1 -0
  166. package/dist/test-render.d.ts +5 -0
  167. package/dist/test-render.d.ts.map +1 -0
  168. package/dist/test-render.js +76 -0
  169. package/dist/test-render.js.map +1 -0
  170. package/dist/vector-export.d.ts +52 -0
  171. package/dist/vector-export.d.ts.map +1 -0
  172. package/dist/vector-export.js +628 -0
  173. package/dist/vector-export.js.map +1 -0
  174. package/dist/web-viewer/build-client.d.ts +6 -0
  175. package/dist/web-viewer/build-client.d.ts.map +1 -0
  176. package/dist/web-viewer/build-client.js +36 -0
  177. package/dist/web-viewer/build-client.js.map +1 -0
  178. package/dist/web-viewer/client/viewer.d.ts +7 -0
  179. package/dist/web-viewer/client/viewer.d.ts.map +1 -0
  180. package/dist/web-viewer/client/viewer.js +873 -0
  181. package/dist/web-viewer/client/viewer.js.map +1 -0
  182. package/dist/web-viewer/server.d.ts +16 -0
  183. package/dist/web-viewer/server.d.ts.map +1 -0
  184. package/dist/web-viewer/server.js +420 -0
  185. package/dist/web-viewer/server.js.map +1 -0
  186. package/package.json +66 -0
@@ -0,0 +1,366 @@
1
+ /**
2
+ * Render Screen V2 - Improved vector rendering
3
+ *
4
+ * Key improvements over v1:
5
+ * 1. For stroked vectors: Use vectorNetworkBlob or normalizedSize to get centerline, NOT strokeGeometry
6
+ * 2. strokeGeometry contains pre-outlined stroke - only use as fallback
7
+ * 3. Proper transform composition for rotated/positioned vectors
8
+ * 4. Better detection of stroked vs filled vectors
9
+ * 5. Mask rendering support (isMask flag handling)
10
+ * 6. Image embedding support
11
+ * 7. Full text styling (font-style, letter-spacing, etc.)
12
+ */
13
+ import { DEFAULT_RENDER_OPTIONS, IDENTITY_TRANSFORM } from "./render-types.js";
14
+ import { escapeXml, multiplyTransforms, getLocalTransform, transformPoint, } from "./render-utils.js";
15
+ import { getPaints, getVisiblePaint, paintToColor, paintToImageHash, detectImageFormat, getMimeType, } from "./paint-utils.js";
16
+ import { isStrokedVector, renderStrokedVector, renderFilledVector, } from "./vector-renderer.js";
17
+ // ============================================================================
18
+ // Text Rendering
19
+ // ============================================================================
20
+ function renderText(node, transform, output) {
21
+ const text = node.characters;
22
+ if (!text)
23
+ return false;
24
+ const fills = getPaints(node, "fills");
25
+ const fillColor = paintToColor(getVisiblePaint(fills)) ?? "#000";
26
+ const style = node.style;
27
+ const fontSize = style?.fontSize ?? 14;
28
+ const fontFamily = escapeXml(style?.fontFamily ?? "Inter");
29
+ const fontWeight = style?.fontWeight ?? 400;
30
+ const fontStyle = style?.fontStyle ?? "normal";
31
+ const lineHeight = style?.lineHeightPx ?? fontSize * 1.2;
32
+ const letterSpacing = style?.letterSpacing ?? 0;
33
+ const pos = transformPoint(0, 0, transform);
34
+ const safeText = escapeXml(text);
35
+ const lines = safeText.split(/\r?\n/);
36
+ // Handle text alignment
37
+ const anchor = style?.textAlignHorizontal?.toLowerCase() ?? "left";
38
+ const textAnchor = anchor === "center" ? "middle" : anchor === "right" ? "end" : "start";
39
+ const width = node.width ?? 0;
40
+ const startX = textAnchor === "middle" ? pos.x + width / 2 : textAnchor === "end" ? pos.x + width : pos.x;
41
+ const attrs = [
42
+ `x="${startX}"`,
43
+ `y="${pos.y}"`,
44
+ `font-family="${fontFamily}"`,
45
+ `font-size="${fontSize}"`,
46
+ `font-weight="${fontWeight}"`,
47
+ `font-style="${fontStyle}"`,
48
+ `fill="${fillColor}"`,
49
+ `dominant-baseline="text-before-edge"`,
50
+ `text-anchor="${textAnchor}"`,
51
+ ];
52
+ if (letterSpacing !== 0) {
53
+ attrs.push(`letter-spacing="${letterSpacing}"`);
54
+ }
55
+ if (node.opacity !== undefined && node.opacity < 1) {
56
+ attrs.push(`opacity="${node.opacity}"`);
57
+ }
58
+ if (style?.fontPostScriptName) {
59
+ attrs.push(`data-postscript="${escapeXml(style.fontPostScriptName)}"`);
60
+ }
61
+ // Multi-line text rendering with tspans
62
+ const spans = lines
63
+ .map((line, index) => {
64
+ const dy = index === 0 ? 0 : lineHeight;
65
+ return `<tspan x="${startX}" dy="${dy}">${line}</tspan>`;
66
+ })
67
+ .join("");
68
+ output.push(`<text ${attrs.join(" ")}>${spans}</text>`);
69
+ return true;
70
+ }
71
+ // ============================================================================
72
+ // Rectangle Rendering
73
+ // ============================================================================
74
+ function renderRectangle(node, transform, images, includeImages, output) {
75
+ const fills = getPaints(node, "fills");
76
+ const strokes = getPaints(node, "strokes");
77
+ const fillPaint = getVisiblePaint(fills);
78
+ const fillColor = paintToColor(fillPaint);
79
+ const strokeColor = paintToColor(getVisiblePaint(strokes));
80
+ // Check for image fill
81
+ let hasImageFill = false;
82
+ if (includeImages && fillPaint?.type === "IMAGE" && images) {
83
+ const hash = paintToImageHash(fillPaint);
84
+ const imageData = hash ? images.get(hash) : undefined;
85
+ if (imageData) {
86
+ hasImageFill = true;
87
+ const format = detectImageFormat(imageData);
88
+ const mimeType = getMimeType(format);
89
+ const base64 = Buffer.from(imageData).toString("base64");
90
+ const scaleMode = fillPaint.imageScaleMode ?? fillPaint.scaleMode;
91
+ const preserve = scaleMode === "FIT" ? "xMidYMid meet" : scaleMode === "STRETCH" ? "none" : "xMidYMid slice";
92
+ const pos = transformPoint(0, 0, transform);
93
+ const width = node.width ?? 0;
94
+ const height = node.height ?? 0;
95
+ const attrs = [
96
+ `x="${pos.x}"`,
97
+ `y="${pos.y}"`,
98
+ `width="${width}"`,
99
+ `height="${height}"`,
100
+ `preserveAspectRatio="${preserve}"`,
101
+ `href="data:${mimeType};base64,${base64}"`,
102
+ ];
103
+ if (node.opacity !== undefined && node.opacity < 1) {
104
+ attrs.push(`opacity="${node.opacity}"`);
105
+ }
106
+ output.push(`<image ${attrs.join(" ")} />`);
107
+ }
108
+ }
109
+ if (hasImageFill)
110
+ return true;
111
+ if (!fillColor && !strokeColor)
112
+ return false;
113
+ const width = node.width ?? 0;
114
+ const height = node.height ?? 0;
115
+ // Transform the four corners
116
+ const p0 = transformPoint(0, 0, transform);
117
+ const p1 = transformPoint(width, 0, transform);
118
+ const p2 = transformPoint(width, height, transform);
119
+ const p3 = transformPoint(0, height, transform);
120
+ // Check if it's still axis-aligned (no rotation)
121
+ const isAxisAligned = Math.abs(p0.y - p1.y) < 0.01 && Math.abs(p1.x - p2.x) < 0.01;
122
+ if (isAxisAligned) {
123
+ const attrs = [
124
+ `x="${p0.x}"`,
125
+ `y="${p0.y}"`,
126
+ `width="${width}"`,
127
+ `height="${height}"`,
128
+ ];
129
+ if (fillColor)
130
+ attrs.push(`fill="${fillColor}"`);
131
+ else
132
+ attrs.push(`fill="none"`);
133
+ if (strokeColor) {
134
+ attrs.push(`stroke="${strokeColor}"`);
135
+ attrs.push(`stroke-width="${node.strokeWeight ?? 1}"`);
136
+ }
137
+ const cornerRadius = typeof node.cornerRadius === "number" ? node.cornerRadius : undefined;
138
+ if (cornerRadius) {
139
+ attrs.push(`rx="${cornerRadius}"`);
140
+ attrs.push(`ry="${cornerRadius}"`);
141
+ }
142
+ if (node.opacity !== undefined && node.opacity < 1) {
143
+ attrs.push(`opacity="${node.opacity}"`);
144
+ }
145
+ output.push(`<rect ${attrs.join(" ")} />`);
146
+ }
147
+ else {
148
+ // Rotated - use path
149
+ const pathD = `M ${p0.x} ${p0.y} L ${p1.x} ${p1.y} L ${p2.x} ${p2.y} L ${p3.x} ${p3.y} Z`;
150
+ const attrs = [`d="${pathD}"`];
151
+ if (fillColor)
152
+ attrs.push(`fill="${fillColor}"`);
153
+ else
154
+ attrs.push(`fill="none"`);
155
+ if (strokeColor) {
156
+ attrs.push(`stroke="${strokeColor}"`);
157
+ attrs.push(`stroke-width="${node.strokeWeight ?? 1}"`);
158
+ }
159
+ if (node.opacity !== undefined && node.opacity < 1) {
160
+ attrs.push(`opacity="${node.opacity}"`);
161
+ }
162
+ output.push(`<path ${attrs.join(" ")} />`);
163
+ }
164
+ return true;
165
+ }
166
+ // ============================================================================
167
+ // Main Node Rendering
168
+ // ============================================================================
169
+ const VECTOR_TYPES = new Set(["VECTOR", "LINE", "STAR", "REGULAR_POLYGON", "ELLIPSE", "BOOLEAN_OPERATION"]);
170
+ const CONTAINER_TYPES = new Set(["FRAME", "GROUP", "COMPONENT", "INSTANCE"]);
171
+ /**
172
+ * Render a mask node to create a clipPath definition.
173
+ * Returns the clip path content for the mask.
174
+ */
175
+ function renderMaskContent(node, transform, blobs, ctx) {
176
+ const maskOutput = [];
177
+ const width = node.width ?? 0;
178
+ const height = node.height ?? 0;
179
+ // Try to render the mask using vector geometry if available
180
+ if (node.fillGeometry?.length) {
181
+ const tempOutput = [];
182
+ const rendered = renderFilledVector(node, transform, blobs, ctx, tempOutput);
183
+ if (rendered && tempOutput.length > 0) {
184
+ // Convert fill to white for mask
185
+ return tempOutput.join("").replace(/fill="[^"]*"/g, 'fill="white"');
186
+ }
187
+ }
188
+ // Fallback to simple rectangle
189
+ const pos = transformPoint(0, 0, transform);
190
+ return `<rect x="${pos.x}" y="${pos.y}" width="${width}" height="${height}" fill="white" />`;
191
+ }
192
+ function renderNode(node, parentTransform, depth, options, images, blobs, ctx, output) {
193
+ if (depth > options.maxDepth)
194
+ return;
195
+ if (node.visible === false)
196
+ return;
197
+ const sceneNode = node;
198
+ const localTransform = getLocalTransform(sceneNode);
199
+ const worldTransform = multiplyTransforms(parentTransform, localTransform);
200
+ let rendered = false;
201
+ // Handle different node types
202
+ if (node.type === "TEXT" && options.includeText) {
203
+ rendered = renderText(sceneNode, worldTransform, output);
204
+ }
205
+ else if (VECTOR_TYPES.has(node.type ?? "")) {
206
+ if (options.includeStrokes && isStrokedVector(sceneNode)) {
207
+ rendered = renderStrokedVector(sceneNode, worldTransform, blobs, ctx, output);
208
+ }
209
+ if (!rendered && options.includeFills) {
210
+ rendered = renderFilledVector(sceneNode, worldTransform, blobs, ctx, output);
211
+ }
212
+ }
213
+ else if (node.type === "RECTANGLE") {
214
+ if (options.includeFills || options.includeStrokes || options.includeImages) {
215
+ rendered = renderRectangle(sceneNode, worldTransform, images, options.includeImages, output);
216
+ }
217
+ }
218
+ else if (CONTAINER_TYPES.has(node.type ?? "")) {
219
+ if (options.includeFills || options.includeImages) {
220
+ const fills = getPaints(node, "fills");
221
+ const fillPaint = getVisiblePaint(fills);
222
+ const fillColor = paintToColor(fillPaint);
223
+ const hasImageFill = fillPaint?.type === "IMAGE";
224
+ if ((fillColor || (options.includeImages && hasImageFill)) && sceneNode.width && sceneNode.height) {
225
+ rendered = renderRectangle(sceneNode, worldTransform, images, options.includeImages, output);
226
+ }
227
+ }
228
+ }
229
+ // Render children with mask support
230
+ if (node.children) {
231
+ const children = node.children;
232
+ const childOutput = [];
233
+ const targetOutput = sceneNode.clipsContent ? childOutput : output;
234
+ let index = 0;
235
+ while (index < children.length) {
236
+ const child = children[index];
237
+ const childScene = child;
238
+ // Handle mask nodes
239
+ if (childScene.isMask) {
240
+ const maskId = `mask-${ctx.clipCounter++}`;
241
+ const childTransform = multiplyTransforms(worldTransform, getLocalTransform(childScene));
242
+ // Create mask clipPath
243
+ const maskContent = renderMaskContent(childScene, childTransform, blobs, ctx);
244
+ ctx.defs.push(`<clipPath id="${maskId}" clipPathUnits="userSpaceOnUse">${maskContent}</clipPath>`);
245
+ // Collect all siblings until the next mask
246
+ const groupOutput = [];
247
+ index += 1;
248
+ while (index < children.length) {
249
+ const sibling = children[index];
250
+ const siblingScene = sibling;
251
+ if (siblingScene.isMask)
252
+ break;
253
+ renderNode(sibling, worldTransform, depth + 1, options, images, blobs, ctx, groupOutput);
254
+ index += 1;
255
+ }
256
+ // Wrap masked content in a group with the clip-path
257
+ targetOutput.push(`<g clip-path="url(#${maskId})">${groupOutput.join("")}</g>`);
258
+ continue;
259
+ }
260
+ renderNode(child, worldTransform, depth + 1, options, images, blobs, ctx, childOutput);
261
+ index += 1;
262
+ }
263
+ // Handle clipping
264
+ if (sceneNode.clipsContent && sceneNode.width && sceneNode.height) {
265
+ const clipId = `clip-${ctx.clipCounter++}`;
266
+ const p0 = transformPoint(0, 0, worldTransform);
267
+ ctx.defs.push(`<clipPath id="${clipId}"><rect x="${p0.x}" y="${p0.y}" width="${sceneNode.width}" height="${sceneNode.height}" /></clipPath>`);
268
+ output.push(`<g clip-path="url(#${clipId})">${childOutput.join("")}</g>`);
269
+ }
270
+ }
271
+ }
272
+ // ============================================================================
273
+ // Bounds Calculation
274
+ // ============================================================================
275
+ function collectBounds(node, parentTransform) {
276
+ if (node.visible === false)
277
+ return null;
278
+ const sceneNode = node;
279
+ const localTransform = getLocalTransform(sceneNode);
280
+ const worldTransform = multiplyTransforms(parentTransform, localTransform);
281
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
282
+ // Include this node's bounds
283
+ if (sceneNode.width !== undefined && sceneNode.height !== undefined) {
284
+ const corners = [
285
+ transformPoint(0, 0, worldTransform),
286
+ transformPoint(sceneNode.width, 0, worldTransform),
287
+ transformPoint(sceneNode.width, sceneNode.height, worldTransform),
288
+ transformPoint(0, sceneNode.height, worldTransform),
289
+ ];
290
+ for (const p of corners) {
291
+ minX = Math.min(minX, p.x);
292
+ minY = Math.min(minY, p.y);
293
+ maxX = Math.max(maxX, p.x);
294
+ maxY = Math.max(maxY, p.y);
295
+ }
296
+ }
297
+ // Include children bounds
298
+ if (node.children) {
299
+ for (const child of node.children) {
300
+ const childBounds = collectBounds(child, worldTransform);
301
+ if (childBounds) {
302
+ minX = Math.min(minX, childBounds.minX);
303
+ minY = Math.min(minY, childBounds.minY);
304
+ maxX = Math.max(maxX, childBounds.maxX);
305
+ maxY = Math.max(maxY, childBounds.maxY);
306
+ }
307
+ }
308
+ }
309
+ if (!Number.isFinite(minX))
310
+ return null;
311
+ return { minX, minY, maxX, maxY };
312
+ }
313
+ // ============================================================================
314
+ // Main Export
315
+ // ============================================================================
316
+ /**
317
+ * Render a Figma node subtree to SVG.
318
+ *
319
+ * @param node - The root node to render
320
+ * @param images - Optional map of image hash -> image data for embedding
321
+ * @param blobs - Optional array of blob data for vector paths
322
+ * @param options - Rendering options
323
+ * @returns The rendered SVG and metadata
324
+ */
325
+ export function renderScreenV2(node, images, blobs, options = {}) {
326
+ const resolved = { ...DEFAULT_RENDER_OPTIONS, ...options };
327
+ const ctx = { defs: [], clipCounter: 0, warnings: [] };
328
+ // Calculate bounds
329
+ const bounds = collectBounds(node, IDENTITY_TRANSFORM);
330
+ if (!bounds) {
331
+ ctx.warnings.push("No bounds found for node subtree");
332
+ return { svg: "", width: 0, height: 0, warnings: ctx.warnings };
333
+ }
334
+ const width = Math.max(1, bounds.maxX - bounds.minX);
335
+ const height = Math.max(1, bounds.maxY - bounds.minY);
336
+ // Offset transform to bring content to origin
337
+ const offsetTransform = {
338
+ a: 1,
339
+ b: 0,
340
+ c: 0,
341
+ d: 1,
342
+ e: -bounds.minX,
343
+ f: -bounds.minY,
344
+ };
345
+ // Render
346
+ const output = [];
347
+ if (resolved.background) {
348
+ output.push(`<rect width="100%" height="100%" fill="${resolved.background}" />`);
349
+ }
350
+ renderNode(node, offsetTransform, 0, resolved, images, blobs, ctx, output);
351
+ // Build SVG
352
+ const defs = ctx.defs.length > 0 ? `<defs>${ctx.defs.join("")}</defs>` : "";
353
+ const scaledWidth = width * resolved.scale;
354
+ const scaledHeight = height * resolved.scale;
355
+ const svg = `<?xml version="1.0" encoding="UTF-8"?>` +
356
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${scaledWidth}" height="${scaledHeight}" viewBox="0 0 ${width} ${height}">` +
357
+ `${defs}${output.join("")}</svg>`;
358
+ return { svg, width, height, warnings: ctx.warnings };
359
+ }
360
+ /**
361
+ * Alias for backwards compatibility with V1 interface.
362
+ * V1 used: renderScreen(node, images, blobs, options)
363
+ * V2 uses: renderScreenV2(node, images, blobs, options)
364
+ */
365
+ export const renderScreen = renderScreenV2;
366
+ //# sourceMappingURL=render-screen-v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-screen-v2.js","sourceRoot":"","sources":["../../src/experimental/render-screen-v2.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Render Screen - Improved vector rendering
3
+ *
4
+ * Key improvements:
5
+ * 1. For stroked vectors: Use vectorNetworkBlob or normalizedSize to get centerline, NOT strokeGeometry
6
+ * 2. strokeGeometry contains pre-outlined stroke - only use as fallback
7
+ * 3. Proper transform composition for rotated/positioned vectors
8
+ * 4. Better detection of stroked vs filled vectors
9
+ * 5. Mask rendering support (isMask flag handling)
10
+ * 6. Image embedding support
11
+ * 7. Full text styling (font-style, letter-spacing, etc.)
12
+ */
13
+ import type { FigNode } from "../parser/types.js";
14
+ import type { BlobEntry, RenderScreenOptions, RenderScreenResult } from "./render-types.js";
15
+ export type { RenderScreenOptions, RenderScreenResult, } from "./render-types.js";
16
+ /**
17
+ * Render a node subtree to SVG.
18
+ *
19
+ * @param node - The root node to render
20
+ * @param images - Optional map of image hash -> image data for embedding
21
+ * @param blobs - Optional array of blob data for vector paths
22
+ * @param options - Rendering options
23
+ * @returns The rendered SVG and metadata
24
+ */
25
+ export declare function renderScreen(node: FigNode, images?: Map<string, Uint8Array>, blobs?: BlobEntry[], options?: RenderScreenOptions): RenderScreenResult;
26
+ //# sourceMappingURL=render-screen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-screen.d.ts","sourceRoot":"","sources":["../../src/experimental/render-screen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,OAAO,EAOR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAEV,SAAS,EAET,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAuB3B,YAAY,EACV,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAkqB3B;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,OAAO,EACb,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAChC,KAAK,CAAC,EAAE,SAAS,EAAE,EACnB,OAAO,GAAE,mBAAwB,GAChC,kBAAkB,CA8CpB"}