openfig-core 0.3.5 → 0.3.7

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parser.ts","../src/utils.ts","../src/encoder.ts","../src/schema.ts","../src/template.ts","../src/gradient.ts","../src/vector.ts","../src/color.ts","../src/svgPath.ts"],"sourcesContent":["/**\n * Isomorphic .fig binary parser.\n *\n * .fig files are ZIP archives containing:\n * - canvas.fig (binary: prelude + version + kiwi-encoded chunks)\n * - meta.json (optional)\n * - thumbnail.png (optional)\n * - images/ (optional)\n *\n * Parsing flow:\n * 1. Unzip → extract canvas.fig\n * 2. Read 8-byte prelude + 4-byte version\n * 3. Chunk 0: deflateRaw → kiwi binary schema\n * 4. Chunk 1: zstd or deflateRaw → kiwi message (nodeChanges[])\n * 5. Build node maps\n */\n\nimport { unzipSync, inflateSync } from \"fflate\";\nimport { decodeBinarySchema, compileSchema } from \"kiwi-schema\";\nimport { decompress as zstdDecompress } from \"fzstd\";\nimport type { FigDocument, FigNode } from \"./types.js\";\nimport { nodeId } from \"./utils.js\";\n\n/**\n * Parse raw canvas.fig binary data (the blob inside the ZIP).\n * Use this if you extract the ZIP yourself.\n */\nexport function parseFigBinary(data: Uint8Array): FigDocument {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n // Read 8-byte prelude + 4-byte version\n const prelude = String.fromCharCode(...data.subarray(0, 8));\n if (!prelude.startsWith(\"fig-\")) {\n throw new Error(`Unknown prelude: ${prelude}`);\n }\n const version = view.getUint32(8, true);\n\n // Read length-prefixed chunks\n const chunks: Uint8Array[] = [];\n let off = 12;\n while (off < data.byteLength) {\n const len = view.getUint32(off, true);\n off += 4;\n chunks.push(data.subarray(off, off + len));\n off += len;\n }\n\n if (chunks.length < 2) {\n throw new Error(\"Expected at least 2 chunks in .fig binary\");\n }\n\n // Chunk 0: kiwi schema (deflateRaw compressed)\n const schemaData = inflateSync(chunks[0]);\n const schema = decodeBinarySchema(schemaData);\n const compiled = compileSchema(schema);\n\n // Chunk 1: message (zstd or deflateRaw — auto-detect by magic bytes)\n let msgData: Uint8Array;\n const c1 = chunks[1];\n if (c1[0] === 0x28 && c1[1] === 0xb5 && c1[2] === 0x2f && c1[3] === 0xfd) {\n msgData = zstdDecompress(c1);\n } else {\n msgData = inflateSync(c1);\n }\n const message = compiled.decodeMessage(msgData);\n\n // Build maps\n const nodes: FigNode[] = message.nodeChanges;\n const nodeMap = new Map<string, FigNode>();\n const childrenMap = new Map<string, FigNode[]>();\n\n for (const node of nodes) {\n const id = nodeId(node);\n if (id) nodeMap.set(id, node);\n }\n\n for (const node of nodes) {\n if (!node.parentIndex?.guid) continue;\n const pid = `${node.parentIndex.guid.sessionID}:${node.parentIndex.guid.localID}`;\n if (!childrenMap.has(pid)) childrenMap.set(pid, []);\n childrenMap.get(pid)!.push(node);\n }\n\n return {\n header: { prelude: prelude.trim(), version },\n nodes,\n nodeMap,\n childrenMap,\n schema,\n compiledSchema: compiled,\n rawChunks: chunks,\n message,\n images: new Map(),\n };\n}\n\n/**\n * Parse a complete .fig file (ZIP archive).\n * Extracts canvas.fig, meta.json, thumbnail.png, and images/*.\n */\nexport function parseFig(data: Uint8Array): FigDocument {\n // Check ZIP header\n if (data[0] !== 0x50 || data[1] !== 0x4b) {\n throw new Error(\"Not a valid .fig file (missing ZIP header)\");\n }\n\n const unzipped = unzipSync(data);\n\n // Find and parse canvas.fig\n const canvasKey = Object.keys(unzipped).find((k) => k.endsWith(\"canvas.fig\"));\n if (!canvasKey) {\n throw new Error(\"No canvas.fig found in .fig archive\");\n }\n const doc = parseFigBinary(unzipped[canvasKey]);\n\n // Extract meta.json\n const metaKey = Object.keys(unzipped).find((k) => k.endsWith(\"meta.json\"));\n if (metaKey) {\n try {\n doc.meta = JSON.parse(new TextDecoder().decode(unzipped[metaKey]));\n } catch { /* ignore malformed meta */ }\n }\n\n // Extract thumbnail\n const thumbKey = Object.keys(unzipped).find((k) => k.endsWith(\"thumbnail.png\"));\n if (thumbKey) {\n doc.thumbnail = unzipped[thumbKey];\n }\n\n // Extract images\n for (const key of Object.keys(unzipped)) {\n if (key.includes(\"images/\") && key !== \"images/\") {\n const filename = key.split(\"/\").pop()!;\n doc.images.set(filename, unzipped[key]);\n }\n }\n\n return doc;\n}\n","import type { FigNode } from \"./types.js\";\n\n/**\n * Returns the string ID for a node (\"sessionID:localID\"), or null if no guid.\n */\nexport function nodeId(node: FigNode): string | null {\n if (!node?.guid) return null;\n return `${node.guid.sessionID}:${node.guid.localID}`;\n}\n","/**\n * .fig file encoder — the write side of the roundtrip.\n *\n * Encodes a FigDocument back to .fig binary format.\n * Zstd compression of chunk 1 (message) is NOT included — the caller\n * provides pre-compressed bytes. This keeps openfig-core isomorphic\n * (no WASM dependency).\n *\n * Encoding flow:\n * 1. compiledSchema.encodeMessage(message) → kiwi binary\n * 2. encodeBinarySchema(schema) + deflateSync → compressed chunk 0\n * 3. Caller zstd-compresses the message → compressed chunk 1\n * 4. assembleCanvasFig() builds the binary\n * 5. createFigZip() packages into ZIP\n */\n\nimport { deflateSync, zipSync } from \"fflate\";\nimport { encodeBinarySchema } from \"kiwi-schema\";\nimport type { FigDocument } from \"./types.js\";\n\nexport interface EncodedFigParts {\n /** deflateRaw-compressed kiwi schema (ready for chunk 0) */\n schemaCompressed: Uint8Array;\n /** Raw kiwi-encoded message — caller MUST zstd-compress this for chunk 1 */\n messageRaw: Uint8Array;\n /** Original prelude string (e.g., \"fig-kiwi\") */\n prelude: string;\n /** Original version number */\n version: number;\n /** Passthrough chunks (rawChunks[2+]) — included as-is */\n passThrough: Uint8Array[];\n}\n\nexport interface AssembleCanvasFigInput {\n prelude: string;\n version: number;\n schemaCompressed: Uint8Array;\n messageCompressed: Uint8Array;\n passThrough?: Uint8Array[];\n}\n\nexport interface CreateFigZipInput {\n canvasFig: Uint8Array;\n meta?: Record<string, any>;\n thumbnail?: Uint8Array;\n images?: Map<string, Uint8Array>;\n}\n\n/**\n * Encode a FigDocument into parts ready for assembly.\n * The message is returned as raw kiwi bytes — caller must zstd-compress it.\n */\nexport function encodeFigParts(doc: FigDocument): EncodedFigParts {\n if (!doc.compiledSchema || !doc.message) {\n throw new Error(\"FigDocument missing compiledSchema or message — cannot encode\");\n }\n if (!doc.schema) {\n throw new Error(\"FigDocument missing schema — cannot encode\");\n }\n\n // Encode kiwi message\n const messageRaw = new Uint8Array(doc.compiledSchema.encodeMessage(doc.message));\n\n // Encode + deflateRaw-compress kiwi schema\n const schemaRaw = encodeBinarySchema(doc.schema);\n const schemaCompressed = deflateSync(new Uint8Array(schemaRaw));\n\n // Passthrough chunks 2+\n const passThrough = doc.rawChunks.slice(2);\n\n return {\n schemaCompressed,\n messageRaw,\n prelude: doc.header.prelude,\n version: doc.header.version,\n passThrough,\n };\n}\n\n/**\n * Assemble a canvas.fig binary from pre-compressed chunks.\n *\n * Format: [prelude 8B][version uint32 LE][len uint32 LE][chunk0][len][chunk1][len][chunk2+]...\n */\nexport function assembleCanvasFig(input: AssembleCanvasFigInput): Uint8Array {\n const { prelude, version, schemaCompressed, messageCompressed, passThrough = [] } = input;\n\n const chunks = [schemaCompressed, messageCompressed, ...passThrough];\n\n // Calculate total size: 8 (prelude) + 4 (version) + sum(4 + chunk.length)\n const headerSize = 8 + 4;\n const totalSize = chunks.reduce((sz, c) => sz + 4 + c.byteLength, headerSize);\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n\n // Write prelude (8 bytes, padded with spaces if shorter)\n let off = 0;\n const enc = new TextEncoder();\n const preludeBytes = enc.encode(prelude);\n buf.set(preludeBytes, 0);\n // Pad to 8 bytes if needed\n for (let i = preludeBytes.length; i < 8; i++) {\n buf[i] = 0x20; // space\n }\n off = 8;\n\n // Write version (uint32 LE)\n view.setUint32(off, version, true);\n off += 4;\n\n // Write length-prefixed chunks\n for (const chunk of chunks) {\n view.setUint32(off, chunk.byteLength, true);\n off += 4;\n buf.set(chunk, off);\n off += chunk.byteLength;\n }\n\n return buf;\n}\n\n/**\n * Create a .fig/.deck ZIP archive from canvas.fig + optional metadata.\n * Uses store mode (no compression) via fflate.\n */\nexport function createFigZip(input: CreateFigZipInput): Uint8Array {\n const opts: Record<string, [Uint8Array, { level: 0 }]> = {};\n\n opts[\"canvas.fig\"] = [input.canvasFig, { level: 0 }];\n\n if (input.meta) {\n opts[\"meta.json\"] = [new TextEncoder().encode(JSON.stringify(input.meta)), { level: 0 }];\n }\n\n if (input.thumbnail) {\n opts[\"thumbnail.png\"] = [input.thumbnail, { level: 0 }];\n }\n\n if (input.images) {\n for (const [name, data] of input.images) {\n opts[`images/${name}`] = [data, { level: 0 }];\n }\n }\n\n return zipSync(opts);\n}\n","/** Pre-built empty .fig template — generated by src/utilities/generateTemplate.ts */\n/** @deprecated-backup Figma-derived blob (kept for rollback only):\n * UEsDBBQAAAAAALu8cFyLpHS2wWcAAMFnAAAKAAAAY2FudmFzLmZpZ2ZpZy1raXdpZQAAAJJlAAC0fQuY...\n */\nexport const emptyFigTemplate = \"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\";\n","/**\n * Creates an empty FigDocument by parsing a pre-built template.\n * The template was created from a valid .fig file with user content\n * marked as REMOVED — proven to open in Figma.\n */\n\nimport { parseFig } from \"./parser.js\";\nimport { emptyFigTemplate } from \"./schema.js\";\nimport type { FigDocument } from \"./types.js\";\n\nfunction b64decode(b64: string): Uint8Array {\n const bin = atob(b64);\n const bytes = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nexport function createEmptyFigDoc(): FigDocument {\n const bytes = b64decode(emptyFigTemplate);\n return parseFig(bytes);\n}\n","import type { FigGradientStop, FigPaint, FigTransform } from \"./types.js\";\n\nexport type GradientKind = \"linear\" | \"radial\";\n\nexport interface GradientFillLike {\n type: GradientKind;\n transform: FigTransform;\n}\n\nexport interface RenderableGradientFill extends GradientFillLike {\n opacity: number;\n stops: FigGradientStop[];\n}\n\nexport interface GradientPoint {\n x: number;\n y: number;\n}\n\nexport interface ResolvedLinearGradientGeometry {\n type: \"linear\";\n start: GradientPoint;\n end: GradientPoint;\n}\n\nexport interface ResolvedRadialGradientGeometry {\n type: \"radial\";\n center: GradientPoint;\n radiusX: number;\n radiusY: number;\n angle: number;\n}\n\nexport type ResolvedGradientGeometry =\n | ResolvedLinearGradientGeometry\n | ResolvedRadialGradientGeometry;\n\nconst IDENTITY_TRANSFORM: FigTransform = {\n m00: 1,\n m01: 0,\n m02: 0,\n m10: 0,\n m11: 1,\n m12: 0,\n};\n\nfunction cloneTransform(transform?: FigTransform): FigTransform {\n if (!transform) return { ...IDENTITY_TRANSFORM };\n return {\n m00: transform.m00,\n m01: transform.m01,\n m02: transform.m02,\n m10: transform.m10,\n m11: transform.m11,\n m12: transform.m12,\n };\n}\n\nfunction isRenderableGradientPaint(\n paint: FigPaint | null | undefined,\n): paint is FigPaint & { type: \"GRADIENT_LINEAR\" | \"GRADIENT_RADIAL\"; stops: FigGradientStop[] } {\n return !!paint &&\n paint.visible !== false &&\n (paint.type === \"GRADIENT_LINEAR\" || paint.type === \"GRADIENT_RADIAL\") &&\n Array.isArray(paint.stops) &&\n paint.stops.length > 0;\n}\n\nexport function extractRenderableGradientFill(\n paints: FigPaint[] | null | undefined,\n): RenderableGradientFill | null {\n const paint = paints?.find((entry) => isRenderableGradientPaint(entry));\n if (!paint) return null;\n\n return {\n type: paint.type === \"GRADIENT_LINEAR\" ? \"linear\" : \"radial\",\n opacity: paint.opacity ?? 1,\n transform: cloneTransform(paint.transform),\n stops: [...paint.stops]\n .sort((a, b) => a.position - b.position)\n .map((stop) => ({\n position: stop.position,\n color: { ...stop.color },\n colorVar: stop.colorVar,\n })),\n };\n}\n\nexport function resolveGradientGeometry(\n fill: GradientFillLike,\n width: number,\n height: number,\n): ResolvedGradientGeometry | null {\n if (width <= 0 || height <= 0) return null;\n\n const transform = fill.transform ?? IDENTITY_TRANSFORM;\n const { m00, m01, m02, m10, m11, m12 } = transform;\n const det = m00 * m11 - m10 * m01;\n if (Math.abs(det) < 1e-12) return null;\n\n // Figma stores paint.transform as node-space -> gradient-space.\n // Consumers usually need the inverse: gradient-space -> node-space.\n const ia = m11 / det;\n const ic = -m01 / det;\n const ie = (m01 * m12 - m11 * m02) / det;\n const ib = -m10 / det;\n const iid = m00 / det;\n const iif = (m10 * m02 - m00 * m12) / det;\n\n const point = (gx: number, gy: number): GradientPoint => ({\n x: (ia * gx + ic * gy + ie) * width,\n y: (ib * gx + iid * gy + iif) * height,\n });\n\n if (fill.type === \"linear\") {\n return {\n type: \"linear\",\n start: point(0, 0.5),\n end: point(1, 0.5),\n };\n }\n\n const center = point(0.5, 0.5);\n const xAxisPoint = point(1, 0.5);\n const yAxisPoint = point(0.5, 1);\n\n return {\n type: \"radial\",\n center,\n radiusX: Math.hypot(xAxisPoint.x - center.x, xAxisPoint.y - center.y),\n radiusY: Math.hypot(yAxisPoint.x - center.x, yAxisPoint.y - center.y),\n angle: Math.atan2(xAxisPoint.y - center.y, xAxisPoint.x - center.x),\n };\n}\n","import type { FigDocument, FigNode, FigPaint } from \"./types.js\";\n\nconst CMD_CLOSE = 0;\nconst CMD_MOVE_TO = 1;\nconst CMD_LINE_TO = 2;\nconst CMD_CUBIC_TO = 4;\nconst SEGMENT_LINE = 0;\nconst SEGMENT_CUBIC = 4;\nconst DEFAULT_HANDLE_MIRRORING = 4;\n\ntype GeometryRef = {\n commandsBlob?: number;\n windingRule?: string;\n styleID?: number;\n};\n\ntype StyleOverride = {\n styleID?: number;\n fillPaints?: FigPaint[];\n};\n\nexport interface ResolvedGeometryPath {\n blobIndex: number;\n commandsBlob: Uint8Array;\n svgPath: string;\n windingRule?: string;\n styleID: number;\n paints?: FigPaint[];\n}\n\nexport interface ResolvedVectorNodePaths {\n fill: ResolvedGeometryPath[];\n stroke: ResolvedGeometryPath[];\n}\n\nexport type VectorPathCommand =\n | { type: \"M\"; x: number; y: number }\n | { type: \"L\"; x: number; y: number }\n | { type: \"C\"; c1x: number; c1y: number; c2x: number; c2y: number; x: number; y: number }\n | { type: \"Z\" };\n\nfunction quadraticToCubic(\n x0: number,\n y0: number,\n qx: number,\n qy: number,\n x: number,\n y: number,\n): Extract<VectorPathCommand, { type: \"C\" }> {\n return {\n type: \"C\",\n c1x: x0 + (2 / 3) * (qx - x0),\n c1y: y0 + (2 / 3) * (qy - y0),\n c2x: x + (2 / 3) * (qx - x),\n c2y: y + (2 / 3) * (qy - y),\n x,\n y,\n };\n}\n\nexport interface VectorGeometryInput {\n svgPath?: string;\n commands?: readonly VectorPathCommand[];\n windingRule?: string;\n styleID?: number;\n}\n\nexport interface VectorStyleOverride {\n styleID: number;\n fillPaints?: FigPaint[];\n [key: string]: any;\n}\n\nexport interface AppendVectorPayloadInput {\n width: number;\n height: number;\n normalizedWidth?: number;\n normalizedHeight?: number;\n fillPaths?: readonly VectorGeometryInput[];\n /**\n * Stroke geometry is expected to already be expanded into outline paths.\n * This helper does not expand SVG strokes into strokeGeometry.\n */\n strokePaths?: readonly VectorGeometryInput[];\n styleOverrideTable?: readonly VectorStyleOverride[];\n}\n\nexport interface AuthoredVectorPayload {\n fillGeometry: GeometryRef[];\n strokeGeometry: GeometryRef[];\n vectorData: {\n vectorNetworkBlob: number;\n normalizedSize: { x: number; y: number };\n styleOverrideTable?: VectorStyleOverride[];\n };\n}\n\nexport function roundPathNumber(n: number, decimals = 2): number {\n const factor = 10 ** decimals;\n return Math.round(n * factor) / factor;\n}\n\nexport function getBlobBytes(doc: FigDocument, blobIndex: number | null | undefined): Uint8Array | null {\n if (blobIndex == null || blobIndex < 0) return null;\n\n const blob = doc.message?.blobs?.[blobIndex];\n if (!blob) return null;\n\n if (blob instanceof Uint8Array) return blob;\n if (blob.bytes instanceof Uint8Array) return blob.bytes;\n if (Array.isArray(blob.bytes)) return Uint8Array.from(blob.bytes);\n\n if (blob.bytes && typeof blob.bytes === \"object\") {\n const values = Object.values(blob.bytes);\n if (values.every((value) => typeof value === \"number\")) {\n return Uint8Array.from(values as number[]);\n }\n }\n\n return null;\n}\n\nexport function geometryBlobToSVGPath(blob: Uint8Array): string {\n if (!blob.length) return \"\";\n\n const view = new DataView(blob.buffer, blob.byteOffset, blob.byteLength);\n let offset = 0;\n const parts: string[] = [];\n\n const canRead = (byteLength: number) => offset + byteLength <= blob.length;\n\n while (offset < blob.length) {\n const cmd = blob[offset++];\n\n switch (cmd) {\n case CMD_CLOSE:\n parts.push(\"Z\");\n break;\n\n case CMD_MOVE_TO: {\n if (!canRead(8)) return parts.join(\"\");\n const x = roundPathNumber(view.getFloat32(offset, true));\n const y = roundPathNumber(view.getFloat32(offset + 4, true));\n offset += 8;\n parts.push(`M${x} ${y}`);\n break;\n }\n\n case CMD_LINE_TO: {\n if (!canRead(8)) return parts.join(\"\");\n const x = roundPathNumber(view.getFloat32(offset, true));\n const y = roundPathNumber(view.getFloat32(offset + 4, true));\n offset += 8;\n parts.push(`L${x} ${y}`);\n break;\n }\n\n case CMD_CUBIC_TO: {\n if (!canRead(24)) return parts.join(\"\");\n const x1 = roundPathNumber(view.getFloat32(offset, true));\n const y1 = roundPathNumber(view.getFloat32(offset + 4, true));\n const x2 = roundPathNumber(view.getFloat32(offset + 8, true));\n const y2 = roundPathNumber(view.getFloat32(offset + 12, true));\n const x = roundPathNumber(view.getFloat32(offset + 16, true));\n const y = roundPathNumber(view.getFloat32(offset + 20, true));\n offset += 24;\n parts.push(`C${x1} ${y1} ${x2} ${y2} ${x} ${y}`);\n break;\n }\n\n default:\n return parts.join(\"\");\n }\n }\n\n return parts.join(\"\");\n}\n\nexport function parseSVGPathData(svgPath: string): VectorPathCommand[] {\n const tokens: Array<string | number> = [];\n const re = /([MmLlCcSsQqTtHhVvZz])|([+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(svgPath)) !== null) {\n if (match[1]) tokens.push(match[1]);\n else tokens.push(Number.parseFloat(match[2]));\n }\n\n const commands: VectorPathCommand[] = [];\n let i = 0;\n let cx = 0;\n let cy = 0;\n let startX = 0;\n let startY = 0;\n let prevC2x = 0;\n let prevC2y = 0;\n let prevQuadraticX = 0;\n let prevQuadraticY = 0;\n let cmd = \"\";\n const num = () => {\n const value = tokens[i++];\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n throw new Error(`Invalid SVG path data near token index ${i - 1}`);\n }\n return value;\n };\n\n while (i < tokens.length) {\n if (typeof tokens[i] === \"string\") cmd = tokens[i++] as string;\n switch (cmd) {\n case \"M\":\n cx = num(); cy = num(); startX = cx; startY = cy;\n commands.push({ type: \"M\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n cmd = \"L\";\n break;\n case \"m\":\n cx += num(); cy += num(); startX = cx; startY = cy;\n commands.push({ type: \"M\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n cmd = \"l\";\n break;\n case \"L\":\n cx = num(); cy = num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"l\":\n cx += num(); cy += num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"H\":\n cx = num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"h\":\n cx += num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"V\":\n cy = num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"v\":\n cy += num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"C\": {\n const c1x = num();\n const c1y = num();\n const c2x = num();\n const c2y = num();\n cx = num();\n cy = num();\n prevC2x = c2x;\n prevC2y = c2y;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n commands.push({ type: \"C\", c1x, c1y, c2x, c2y, x: cx, y: cy });\n break;\n }\n case \"c\": {\n const c1x = cx + num();\n const c1y = cy + num();\n const c2x = cx + num();\n const c2y = cy + num();\n cx += num();\n cy += num();\n prevC2x = c2x;\n prevC2y = c2y;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n commands.push({ type: \"C\", c1x, c1y, c2x, c2y, x: cx, y: cy });\n break;\n }\n case \"S\": {\n const c1x = 2 * cx - prevC2x;\n const c1y = 2 * cy - prevC2y;\n const c2x = num();\n const c2y = num();\n cx = num();\n cy = num();\n prevC2x = c2x;\n prevC2y = c2y;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n commands.push({ type: \"C\", c1x, c1y, c2x, c2y, x: cx, y: cy });\n break;\n }\n case \"s\": {\n const c1x = 2 * cx - prevC2x;\n const c1y = 2 * cy - prevC2y;\n const c2x = cx + num();\n const c2y = cy + num();\n cx += num();\n cy += num();\n prevC2x = c2x;\n prevC2y = c2y;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n commands.push({ type: \"C\", c1x, c1y, c2x, c2y, x: cx, y: cy });\n break;\n }\n case \"Q\": {\n const qx = num();\n const qy = num();\n const x = num();\n const y = num();\n const cubic = quadraticToCubic(cx, cy, qx, qy, x, y);\n commands.push(cubic);\n prevQuadraticX = qx;\n prevQuadraticY = qy;\n prevC2x = cubic.c2x;\n prevC2y = cubic.c2y;\n cx = x;\n cy = y;\n break;\n }\n case \"q\": {\n const qx = cx + num();\n const qy = cy + num();\n const x = cx + num();\n const y = cy + num();\n const cubic = quadraticToCubic(cx, cy, qx, qy, x, y);\n commands.push(cubic);\n prevQuadraticX = qx;\n prevQuadraticY = qy;\n prevC2x = cubic.c2x;\n prevC2y = cubic.c2y;\n cx = x;\n cy = y;\n break;\n }\n case \"T\": {\n const qx = 2 * cx - prevQuadraticX;\n const qy = 2 * cy - prevQuadraticY;\n const x = num();\n const y = num();\n const cubic = quadraticToCubic(cx, cy, qx, qy, x, y);\n commands.push(cubic);\n prevQuadraticX = qx;\n prevQuadraticY = qy;\n prevC2x = cubic.c2x;\n prevC2y = cubic.c2y;\n cx = x;\n cy = y;\n break;\n }\n case \"t\": {\n const qx = 2 * cx - prevQuadraticX;\n const qy = 2 * cy - prevQuadraticY;\n const x = cx + num();\n const y = cy + num();\n const cubic = quadraticToCubic(cx, cy, qx, qy, x, y);\n commands.push(cubic);\n prevQuadraticX = qx;\n prevQuadraticY = qy;\n prevC2x = cubic.c2x;\n prevC2y = cubic.c2y;\n cx = x;\n cy = y;\n break;\n }\n case \"Z\":\n case \"z\":\n commands.push({ type: \"Z\" });\n cx = startX;\n cy = startY;\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"\":\n i++;\n break;\n default:\n throw new Error(`Unsupported SVG path command: ${cmd}`);\n }\n }\n\n return commands;\n}\n\nexport function encodeCommandsBlob(\n commands: readonly VectorPathCommand[],\n scaleX = 1,\n scaleY = 1,\n): Uint8Array {\n let byteLength = 0;\n for (const command of commands) {\n byteLength += 1;\n if (command.type === \"M\" || command.type === \"L\") byteLength += 8;\n else if (command.type === \"C\") byteLength += 24;\n }\n\n const buffer = new ArrayBuffer(byteLength);\n const view = new DataView(buffer);\n let offset = 0;\n\n for (const command of commands) {\n switch (command.type) {\n case \"M\":\n view.setUint8(offset++, CMD_MOVE_TO);\n view.setFloat32(offset, command.x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.y * scaleY, true); offset += 4;\n break;\n case \"L\":\n view.setUint8(offset++, CMD_LINE_TO);\n view.setFloat32(offset, command.x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.y * scaleY, true); offset += 4;\n break;\n case \"C\":\n view.setUint8(offset++, CMD_CUBIC_TO);\n view.setFloat32(offset, command.c1x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.c1y * scaleY, true); offset += 4;\n view.setFloat32(offset, command.c2x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.c2y * scaleY, true); offset += 4;\n view.setFloat32(offset, command.x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.y * scaleY, true); offset += 4;\n break;\n case \"Z\":\n view.setUint8(offset++, CMD_CLOSE);\n break;\n }\n }\n\n return new Uint8Array(buffer, 0, offset);\n}\n\nexport function encodeVectorNetworkBlob(pathCommandsList: readonly (readonly VectorPathCommand[])[]): Uint8Array {\n const vertices: Array<{ x: number; y: number }> = [];\n const segments: Array<{ s: number; tsx: number; tsy: number; e: number; tex: number; tey: number; t: number }> = [];\n const regions: number[][] = [];\n\n for (const pathCommands of pathCommandsList) {\n let regionSegments: number[] = [];\n let firstVertex = -1;\n let prevVertex = -1;\n let prevX = 0;\n let prevY = 0;\n\n for (const command of pathCommands) {\n if (command.type === \"M\") {\n // Each sub-path (M...Z sequence) becomes its own region so Figma\n // strokes compound paths correctly (e.g. counter holes in letters).\n if (regionSegments.length > 0) {\n regions.push(regionSegments);\n regionSegments = [];\n }\n const vertexIndex = vertices.length;\n vertices.push({ x: command.x, y: command.y });\n firstVertex = vertexIndex;\n prevVertex = vertexIndex;\n prevX = command.x;\n prevY = command.y;\n } else if (command.type === \"L\") {\n const vertexIndex = vertices.length;\n vertices.push({ x: command.x, y: command.y });\n if (prevVertex >= 0) {\n regionSegments.push(segments.length);\n segments.push({ s: prevVertex, tsx: 0, tsy: 0, e: vertexIndex, tex: 0, tey: 0, t: SEGMENT_LINE });\n }\n prevVertex = vertexIndex;\n prevX = command.x;\n prevY = command.y;\n } else if (command.type === \"C\") {\n const vertexIndex = vertices.length;\n vertices.push({ x: command.x, y: command.y });\n if (prevVertex >= 0) {\n regionSegments.push(segments.length);\n segments.push({\n s: prevVertex,\n tsx: command.c1x - prevX,\n tsy: command.c1y - prevY,\n e: vertexIndex,\n tex: command.c2x - command.x,\n tey: command.c2y - command.y,\n t: SEGMENT_CUBIC,\n });\n }\n prevVertex = vertexIndex;\n prevX = command.x;\n prevY = command.y;\n } else if (command.type === \"Z\") {\n if (prevVertex >= 0 && prevVertex !== firstVertex) {\n const lastPos = vertices[prevVertex];\n const firstPos = vertices[firstVertex];\n const dx = lastPos.x - firstPos.x;\n const dy = lastPos.y - firstPos.y;\n if (dx * dx + dy * dy < 1e-4) {\n // Path already returned to start — merge the duplicate end vertex\n // into firstVertex so Figma sees one vertex with correct incoming\n // and outgoing bezier tangent handles for miter join computation.\n // Without this, a zero-length closing LINE segment would give Figma\n // a degenerate tangent, producing wrong miter angles (visible as\n // notches at sharp corners like the \"g\" terminal).\n const lastSeg = segments[segments.length - 1];\n if (lastSeg && lastSeg.e === prevVertex) {\n lastSeg.e = firstVertex;\n vertices.pop();\n }\n } else {\n regionSegments.push(segments.length);\n segments.push({ s: prevVertex, tsx: 0, tsy: 0, e: firstVertex, tex: 0, tey: 0, t: SEGMENT_LINE });\n }\n }\n if (firstVertex >= 0) {\n prevVertex = firstVertex;\n prevX = vertices[firstVertex].x;\n prevY = vertices[firstVertex].y;\n }\n }\n }\n\n regions.push(regionSegments);\n }\n\n let regionsByteLength = 0;\n for (const region of regions) regionsByteLength += 4 + 4 + (region.length * 4) + 4;\n const totalByteLength = 16 + (vertices.length * 12) + (segments.length * 28) + regionsByteLength;\n\n const buffer = new ArrayBuffer(totalByteLength);\n const view = new DataView(buffer);\n let offset = 0;\n\n view.setUint32(offset, vertices.length, true); offset += 4;\n view.setUint32(offset, segments.length, true); offset += 4;\n view.setUint32(offset, regions.length, true); offset += 4;\n view.setUint32(offset, 1, true); offset += 4;\n\n for (const vertex of vertices) {\n view.setFloat32(offset, vertex.x, true); offset += 4;\n view.setFloat32(offset, vertex.y, true); offset += 4;\n view.setUint32(offset, DEFAULT_HANDLE_MIRRORING, true); offset += 4;\n }\n\n for (const segment of segments) {\n view.setUint32(offset, segment.s, true); offset += 4;\n view.setFloat32(offset, segment.tsx, true); offset += 4;\n view.setFloat32(offset, segment.tsy, true); offset += 4;\n view.setUint32(offset, segment.e, true); offset += 4;\n view.setFloat32(offset, segment.tex, true); offset += 4;\n view.setFloat32(offset, segment.tey, true); offset += 4;\n view.setUint32(offset, segment.t, true); offset += 4;\n }\n\n for (const region of regions) {\n view.setUint32(offset, 1, true); offset += 4;\n view.setUint32(offset, region.length, true); offset += 4;\n for (const segmentIndex of region) {\n view.setUint32(offset, segmentIndex, true); offset += 4;\n }\n view.setUint32(offset, 1, true); offset += 4;\n }\n\n return new Uint8Array(buffer, 0, offset);\n}\n\nfunction cloneStyleOverrides(styleOverrideTable: readonly VectorStyleOverride[] | undefined): VectorStyleOverride[] | undefined {\n if (!styleOverrideTable?.length) return undefined;\n return JSON.parse(JSON.stringify(styleOverrideTable));\n}\n\nfunction toCommands(input: VectorGeometryInput): VectorPathCommand[] {\n if (Array.isArray(input.commands) && input.commands.length > 0) {\n return input.commands.map((command) => ({ ...command }));\n }\n if (input.svgPath) return parseSVGPathData(input.svgPath);\n throw new Error(\"Vector geometry input requires either svgPath or commands\");\n}\n\nexport function appendVectorPayloadToDocument(\n doc: FigDocument,\n input: AppendVectorPayloadInput,\n): AuthoredVectorPayload {\n const blobs: any[] = doc.message?.blobs ?? (doc.message.blobs = []);\n const normalizedWidth = input.normalizedWidth ?? input.width;\n const normalizedHeight = input.normalizedHeight ?? input.height;\n const scaleX = normalizedWidth === 0 ? 1 : input.width / normalizedWidth;\n const scaleY = normalizedHeight === 0 ? 1 : input.height / normalizedHeight;\n\n const fillPaths = (input.fillPaths ?? []).map(toCommands);\n const strokePaths = (input.strokePaths ?? []).map(toCommands);\n if (fillPaths.length === 0 && strokePaths.length === 0) {\n throw new Error(\"Vector payload requires at least one fill or stroke path\");\n }\n\n const fillGeometry: GeometryRef[] = [];\n for (let i = 0; i < fillPaths.length; i++) {\n const bytes = encodeCommandsBlob(fillPaths[i], scaleX, scaleY);\n blobs.push({ bytes });\n const path = input.fillPaths?.[i];\n fillGeometry.push({\n windingRule: path?.windingRule ?? \"NONZERO\",\n commandsBlob: blobs.length - 1,\n styleID: path?.styleID ?? 0,\n });\n }\n\n const strokeGeometry: GeometryRef[] = [];\n for (let i = 0; i < strokePaths.length; i++) {\n const bytes = encodeCommandsBlob(strokePaths[i], scaleX, scaleY);\n blobs.push({ bytes });\n const path = input.strokePaths?.[i];\n strokeGeometry.push({\n windingRule: path?.windingRule ?? \"NONZERO\",\n commandsBlob: blobs.length - 1,\n styleID: path?.styleID ?? 0,\n });\n }\n\n const vectorNetworkBlob = encodeVectorNetworkBlob([...fillPaths, ...strokePaths]);\n blobs.push({ bytes: vectorNetworkBlob });\n\n return {\n fillGeometry,\n strokeGeometry,\n vectorData: {\n vectorNetworkBlob: blobs.length - 1,\n normalizedSize: { x: normalizedWidth, y: normalizedHeight },\n ...(cloneStyleOverrides(input.styleOverrideTable)?.length\n ? { styleOverrideTable: cloneStyleOverrides(input.styleOverrideTable) }\n : {}),\n },\n };\n}\n\nfunction getStyleOverrideTable(node: FigNode): StyleOverride[] {\n const table = node.vectorData?.styleOverrideTable;\n return Array.isArray(table) ? table : [];\n}\n\nfunction resolveFillPaints(node: FigNode, styleID: number): FigPaint[] | undefined {\n if (!styleID) return node.fillPaints;\n const override = getStyleOverrideTable(node).find((entry) => entry?.styleID === styleID);\n if (!override || !(\"fillPaints\" in override)) return node.fillPaints;\n return override.fillPaints;\n}\n\nfunction resolveGeometry(\n doc: FigDocument,\n node: FigNode,\n geometry: GeometryRef[] | undefined,\n kind: \"fill\" | \"stroke\",\n): ResolvedGeometryPath[] {\n if (!Array.isArray(geometry) || geometry.length === 0) return [];\n\n const resolved: Array<ResolvedGeometryPath | null> = geometry.map((entry) => {\n if (typeof entry?.commandsBlob !== \"number\") return null;\n const bytes = getBlobBytes(doc, entry.commandsBlob);\n if (!bytes) return null;\n const svgPath = geometryBlobToSVGPath(bytes);\n if (!svgPath) return null;\n\n const path: ResolvedGeometryPath = {\n blobIndex: entry.commandsBlob,\n commandsBlob: bytes,\n svgPath,\n windingRule: entry.windingRule,\n styleID: entry.styleID || 0,\n paints: kind === \"fill\" ? resolveFillPaints(node, entry.styleID || 0) : node.strokePaints,\n };\n\n return path;\n });\n\n return resolved.filter((entry): entry is ResolvedGeometryPath => entry !== null);\n}\n\nexport function resolveVectorNodePaths(doc: FigDocument, node: FigNode): ResolvedVectorNodePaths {\n return {\n fill: resolveGeometry(doc, node, node.fillGeometry as GeometryRef[] | undefined, \"fill\"),\n stroke: resolveGeometry(doc, node, node.strokeGeometry as GeometryRef[] | undefined, \"stroke\"),\n };\n}\n","/**\n * CSS / hex color ↔ Figma normalized RGBA color helpers.\n *\n * All functions are isomorphic (no DOM required).\n * For named CSS colors (e.g. \"coral\"), pass an optional `resolveNamed`\n * callback that uses the browser's computed-style machinery.\n */\n\nimport type { FigColor, FigPaint } from \"./types.js\";\n\nexport function hexToFigColor(hex: string): FigColor {\n if (!hex || hex === \"transparent\") return { r: 0, g: 0, b: 0, a: 0 };\n const h = hex.replace(\"#\", \"\");\n const r = parseInt(h.substring(0, 2), 16) / 255;\n const g = parseInt(h.substring(2, 4), 16) / 255;\n const b = parseInt(h.substring(4, 6), 16) / 255;\n const a = h.length >= 8 ? parseInt(h.substring(6, 8), 16) / 255 : 1;\n return { r, g, b, a };\n}\n\nexport function parseCssRgbColor(value: string): FigColor | null {\n const match = value.trim().match(/^rgba?\\((.+)\\)$/i);\n if (!match) return null;\n const parts = match[1].split(\",\").map((part) => part.trim());\n if (parts.length < 3) return null;\n const r = Number.parseFloat(parts[0]);\n const g = Number.parseFloat(parts[1]);\n const b = Number.parseFloat(parts[2]);\n const a = parts.length >= 4 ? Number.parseFloat(parts[3]) : 1;\n if ([r, g, b, a].some((n) => Number.isNaN(n))) return null;\n return { r: r / 255, g: g / 255, b: b / 255, a };\n}\n\nexport function cssColorToFigColor(\n value: string,\n resolveNamed?: (name: string) => FigColor | null,\n): FigColor {\n const trimmed = value.trim();\n if (trimmed === \"transparent\" || trimmed === \"none\") return { r: 0, g: 0, b: 0, a: 0 };\n if (trimmed.startsWith(\"#\")) return hexToFigColor(trimmed);\n const rgba = parseCssRgbColor(trimmed);\n if (rgba) return rgba;\n\n if (resolveNamed) {\n const resolved = resolveNamed(trimmed);\n if (resolved) return resolved;\n }\n\n throw new Error(`Unsupported CSS color: ${value}`);\n}\n\nexport function makeSolidPaint(\n fill: string,\n resolveNamed?: (name: string) => FigColor | null,\n): FigPaint {\n const color = cssColorToFigColor(fill, resolveNamed);\n return {\n type: \"SOLID\",\n color: { r: color.r, g: color.g, b: color.b, a: 1 },\n opacity: color.a,\n visible: true,\n blendMode: \"NORMAL\",\n };\n}\n","/**\n * SVG path serialization, transformation, and stroke/cap enum mapping.\n */\n\nimport { parseSVGPathData } from \"./vector.js\";\nimport type { VectorPathCommand } from \"./vector.js\";\n\nexport function serializeSvgPathData(commands: readonly VectorPathCommand[]): string {\n return commands\n .map((command) => {\n switch (command.type) {\n case \"M\":\n return `M${command.x} ${command.y}`;\n case \"L\":\n return `L${command.x} ${command.y}`;\n case \"C\":\n return `C${command.c1x} ${command.c1y} ${command.c2x} ${command.c2y} ${command.x} ${command.y}`;\n case \"Z\":\n return \"Z\";\n }\n })\n .join(\" \");\n}\n\nexport function transformSvgPathData(\n svgPath: string,\n {\n scaleX = 1,\n scaleY = 1,\n translateX = 0,\n translateY = 0,\n }: { scaleX?: number; scaleY?: number; translateX?: number; translateY?: number },\n): string {\n const commands = parseSVGPathData(svgPath).map((command) => {\n switch (command.type) {\n case \"M\":\n case \"L\":\n return {\n ...command,\n x: command.x * scaleX + translateX,\n y: command.y * scaleY + translateY,\n };\n case \"C\":\n return {\n ...command,\n c1x: command.c1x * scaleX + translateX,\n c1y: command.c1y * scaleY + translateY,\n c2x: command.c2x * scaleX + translateX,\n c2y: command.c2y * scaleY + translateY,\n x: command.x * scaleX + translateX,\n y: command.y * scaleY + translateY,\n };\n case \"Z\":\n return command;\n }\n });\n\n return serializeSvgPathData(commands);\n}\n\nexport function mapStrokeJoin(value: string | undefined): string {\n switch ((value || \"\").toLowerCase()) {\n case \"round\":\n return \"ROUND\";\n case \"bevel\":\n return \"BEVEL\";\n default:\n return \"MITER\";\n }\n}\n\nexport function mapStrokeCap(value: string | undefined): string {\n switch ((value || \"\").toLowerCase()) {\n case \"round\":\n return \"ROUND\";\n case \"square\":\n return \"SQUARE\";\n default:\n return \"NONE\";\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/parser.ts","../src/utils.ts","../src/encoder.ts","../src/convert.ts","../src/schema.ts","../src/template.ts","../src/gradient.ts","../src/vector.ts","../src/color.ts","../src/svgPath.ts"],"sourcesContent":["/**\n * Isomorphic .fig binary parser.\n *\n * .fig files are ZIP archives containing:\n * - canvas.fig (binary: prelude + version + kiwi-encoded chunks)\n * - meta.json (optional)\n * - thumbnail.png (optional)\n * - images/ (optional)\n *\n * Parsing flow:\n * 1. Unzip → extract canvas.fig\n * 2. Read 8-byte prelude + 4-byte version\n * 3. Chunk 0: deflateRaw → kiwi binary schema\n * 4. Chunk 1: zstd or deflateRaw → kiwi message (nodeChanges[])\n * 5. Build node maps\n */\n\nimport { unzipSync, inflateSync } from \"fflate\";\nimport { decodeBinarySchema, compileSchema } from \"kiwi-schema\";\nimport { decompress as zstdDecompress } from \"fzstd\";\nimport type { FigDocument, FigNode } from \"./types.js\";\nimport { nodeId } from \"./utils.js\";\n\n/**\n * Parse raw canvas.fig binary data (the blob inside the ZIP).\n * Use this if you extract the ZIP yourself.\n */\nexport function parseFigBinary(data: Uint8Array): FigDocument {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n // Read 8-byte prelude + 4-byte version\n const prelude = String.fromCharCode(...data.subarray(0, 8));\n if (!prelude.startsWith(\"fig-\")) {\n throw new Error(`Unknown prelude: ${prelude}`);\n }\n const version = view.getUint32(8, true);\n\n // Read length-prefixed chunks\n const chunks: Uint8Array[] = [];\n let off = 12;\n while (off < data.byteLength) {\n const len = view.getUint32(off, true);\n off += 4;\n chunks.push(data.subarray(off, off + len));\n off += len;\n }\n\n if (chunks.length < 2) {\n throw new Error(\"Expected at least 2 chunks in .fig binary\");\n }\n\n // Chunk 0: kiwi schema (deflateRaw compressed)\n const schemaData = inflateSync(chunks[0]);\n const schema = decodeBinarySchema(schemaData);\n const compiled = compileSchema(schema);\n\n // Chunk 1: message (zstd or deflateRaw — auto-detect by magic bytes)\n let msgData: Uint8Array;\n const c1 = chunks[1];\n if (c1[0] === 0x28 && c1[1] === 0xb5 && c1[2] === 0x2f && c1[3] === 0xfd) {\n msgData = zstdDecompress(c1);\n } else {\n msgData = inflateSync(c1);\n }\n const message = compiled.decodeMessage(msgData);\n\n // Build maps\n const nodes: FigNode[] = message.nodeChanges;\n const nodeMap = new Map<string, FigNode>();\n const childrenMap = new Map<string, FigNode[]>();\n\n for (const node of nodes) {\n const id = nodeId(node);\n if (id) nodeMap.set(id, node);\n }\n\n for (const node of nodes) {\n if (!node.parentIndex?.guid) continue;\n const pid = `${node.parentIndex.guid.sessionID}:${node.parentIndex.guid.localID}`;\n if (!childrenMap.has(pid)) childrenMap.set(pid, []);\n childrenMap.get(pid)!.push(node);\n }\n\n return {\n header: { prelude: prelude.trim(), version },\n nodes,\n nodeMap,\n childrenMap,\n schema,\n compiledSchema: compiled,\n rawChunks: chunks,\n message,\n images: new Map(),\n };\n}\n\n/**\n * Parse a complete .fig file (ZIP archive).\n * Extracts canvas.fig, meta.json, thumbnail.png, and images/*.\n */\nexport function parseFig(data: Uint8Array): FigDocument {\n // Check ZIP header\n if (data[0] !== 0x50 || data[1] !== 0x4b) {\n throw new Error(\"Not a valid .fig file (missing ZIP header)\");\n }\n\n const unzipped = unzipSync(data);\n\n // Find and parse canvas.fig\n const canvasKey = Object.keys(unzipped).find((k) => k.endsWith(\"canvas.fig\"));\n if (!canvasKey) {\n throw new Error(\"No canvas.fig found in .fig archive\");\n }\n const doc = parseFigBinary(unzipped[canvasKey]);\n\n // Extract meta.json\n const metaKey = Object.keys(unzipped).find((k) => k.endsWith(\"meta.json\"));\n if (metaKey) {\n try {\n doc.meta = JSON.parse(new TextDecoder().decode(unzipped[metaKey]));\n } catch { /* ignore malformed meta */ }\n }\n\n // Extract thumbnail\n const thumbKey = Object.keys(unzipped).find((k) => k.endsWith(\"thumbnail.png\"));\n if (thumbKey) {\n doc.thumbnail = unzipped[thumbKey];\n }\n\n // Extract images\n for (const key of Object.keys(unzipped)) {\n if (key.includes(\"images/\") && key !== \"images/\") {\n const filename = key.split(\"/\").pop()!;\n doc.images.set(filename, unzipped[key]);\n }\n }\n\n return doc;\n}\n","import type { FigNode } from \"./types.js\";\n\n/**\n * Returns the string ID for a node (\"sessionID:localID\"), or null if no guid.\n */\nexport function nodeId(node: FigNode): string | null {\n if (!node?.guid) return null;\n return `${node.guid.sessionID}:${node.guid.localID}`;\n}\n","/**\n * .fig file encoder — the write side of the roundtrip.\n *\n * Encodes a FigDocument back to .fig binary format.\n * Zstd compression of chunk 1 (message) is NOT included — the caller\n * provides pre-compressed bytes. This keeps openfig-core isomorphic\n * (no WASM dependency).\n *\n * Encoding flow:\n * 1. compiledSchema.encodeMessage(message) → kiwi binary\n * 2. encodeBinarySchema(schema) + deflateSync → compressed chunk 0\n * 3. Caller zstd-compresses the message → compressed chunk 1\n * 4. assembleCanvasFig() builds the binary\n * 5. createFigZip() packages into ZIP\n */\n\nimport { deflateSync, zipSync } from \"fflate\";\nimport { encodeBinarySchema } from \"kiwi-schema\";\nimport type { FigDocument } from \"./types.js\";\n\nexport interface EncodedFigParts {\n /** deflateRaw-compressed kiwi schema (ready for chunk 0) */\n schemaCompressed: Uint8Array;\n /** Raw kiwi-encoded message — caller MUST zstd-compress this for chunk 1 */\n messageRaw: Uint8Array;\n /** Original prelude string (e.g., \"fig-kiwi\") */\n prelude: string;\n /** Original version number */\n version: number;\n /** Passthrough chunks (rawChunks[2+]) — included as-is */\n passThrough: Uint8Array[];\n}\n\nexport interface AssembleCanvasFigInput {\n prelude: string;\n version: number;\n schemaCompressed: Uint8Array;\n messageCompressed: Uint8Array;\n passThrough?: Uint8Array[];\n}\n\nexport interface CreateFigZipInput {\n canvasFig: Uint8Array;\n meta?: Record<string, any>;\n thumbnail?: Uint8Array;\n images?: Map<string, Uint8Array>;\n}\n\n/**\n * Encode a FigDocument into parts ready for assembly.\n * The message is returned as raw kiwi bytes — caller must zstd-compress it.\n */\nexport function encodeFigParts(doc: FigDocument): EncodedFigParts {\n if (!doc.compiledSchema || !doc.message) {\n throw new Error(\"FigDocument missing compiledSchema or message — cannot encode\");\n }\n if (!doc.schema) {\n throw new Error(\"FigDocument missing schema — cannot encode\");\n }\n\n // Encode kiwi message\n const messageRaw = new Uint8Array(doc.compiledSchema.encodeMessage(doc.message));\n\n // Encode + deflateRaw-compress kiwi schema\n const schemaRaw = encodeBinarySchema(doc.schema);\n const schemaCompressed = deflateSync(new Uint8Array(schemaRaw));\n\n // Passthrough chunks 2+\n const passThrough = doc.rawChunks.slice(2);\n\n return {\n schemaCompressed,\n messageRaw,\n prelude: doc.header.prelude,\n version: doc.header.version,\n passThrough,\n };\n}\n\n/**\n * Assemble a canvas.fig binary from pre-compressed chunks.\n *\n * Format: [prelude 8B][version uint32 LE][len uint32 LE][chunk0][len][chunk1][len][chunk2+]...\n */\nexport function assembleCanvasFig(input: AssembleCanvasFigInput): Uint8Array {\n const { prelude, version, schemaCompressed, messageCompressed, passThrough = [] } = input;\n\n const chunks = [schemaCompressed, messageCompressed, ...passThrough];\n\n // Calculate total size: 8 (prelude) + 4 (version) + sum(4 + chunk.length)\n const headerSize = 8 + 4;\n const totalSize = chunks.reduce((sz, c) => sz + 4 + c.byteLength, headerSize);\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n\n // Write prelude (8 bytes, padded with spaces if shorter)\n let off = 0;\n const enc = new TextEncoder();\n const preludeBytes = enc.encode(prelude);\n buf.set(preludeBytes, 0);\n // Pad to 8 bytes if needed\n for (let i = preludeBytes.length; i < 8; i++) {\n buf[i] = 0x20; // space\n }\n off = 8;\n\n // Write version (uint32 LE)\n view.setUint32(off, version, true);\n off += 4;\n\n // Write length-prefixed chunks\n for (const chunk of chunks) {\n view.setUint32(off, chunk.byteLength, true);\n off += 4;\n buf.set(chunk, off);\n off += chunk.byteLength;\n }\n\n return buf;\n}\n\n/**\n * Create a .fig/.deck ZIP archive from canvas.fig + optional metadata.\n * Uses store mode (no compression) via fflate.\n */\nexport function createFigZip(input: CreateFigZipInput): Uint8Array {\n const opts: Record<string, [Uint8Array, { level: 0 }]> = {};\n\n opts[\"canvas.fig\"] = [input.canvasFig, { level: 0 }];\n\n if (input.meta) {\n opts[\"meta.json\"] = [new TextEncoder().encode(JSON.stringify(input.meta)), { level: 0 }];\n }\n\n if (input.thumbnail) {\n opts[\"thumbnail.png\"] = [input.thumbnail, { level: 0 }];\n }\n\n if (input.images) {\n for (const [name, data] of input.images) {\n opts[`images/${name}`] = [data, { level: 0 }];\n }\n }\n\n return zipSync(opts);\n}\n","import type { FigDocument, FigNode, FigGuid, FigPaint } from \"./types.js\";\n\nexport interface ConvertOptions {\n title?: string;\n layout?: \"row\" | \"grid\";\n gap?: number;\n wrap?: number;\n}\n\nfunction guidToString(guid: FigGuid): string {\n return `${guid.sessionID}:${guid.localID}`;\n}\n\nfunction safeDeepClone<T>(val: T): T {\n if (val === null || val === undefined) return val;\n if (val instanceof Uint8Array) {\n return new Uint8Array(val) as any;\n }\n if (Array.isArray(val)) {\n return val.map(safeDeepClone) as any;\n }\n if (typeof val === \"object\") {\n const copy: any = {};\n for (const k of Object.keys(val)) {\n copy[k] = safeDeepClone((val as any)[k]);\n }\n return copy;\n }\n return val;\n}\n\nexport function convertDeckToFig(\n deckDoc: FigDocument,\n options: ConvertOptions = {}\n): FigDocument {\n const {\n title,\n layout = \"row\",\n gap = 200,\n wrap = 5,\n } = options;\n\n // 1. Find all active slide nodes\n const activeSlides = deckDoc.nodes\n .filter((n) => n.type === \"SLIDE\" && n.phase !== \"REMOVED\")\n // Sort by lexical order of their parentIndex.position or parent MODULE's position if nested\n .sort((a, b) => {\n const posA = a.parentIndex?.position ?? \"\";\n const posB = b.parentIndex?.position ?? \"\";\n return posA.localeCompare(posB);\n });\n\n // Calculate maximum local ID in the source document\n let maxLocalId = 0;\n for (const node of deckDoc.nodes) {\n if (node.guid?.localID > maxLocalId) {\n maxLocalId = node.guid.localID;\n }\n }\n let nextLocalId = maxLocalId + 1;\n const sessionId = 1;\n\n function generateGuid(): FigGuid {\n return { sessionID: sessionId, localID: nextLocalId++ };\n }\n\n // 2. Create the output FigDocument skeleton\n const documentNode = deckDoc.nodes.find((n) => n.type === \"DOCUMENT\");\n const docGuid = documentNode?.guid ?? { sessionID: 0, localID: 0 };\n\n const canvasGuid = generateGuid();\n const canvasName = title || deckDoc.meta?.file_name || \"Page 1\";\n\n const newCanvasNode: FigNode = {\n guid: canvasGuid,\n type: \"CANVAS\",\n name: canvasName,\n phase: \"CREATED\",\n parentIndex: {\n guid: docGuid,\n position: \"!\",\n },\n visible: true,\n };\n\n const outputNodes: FigNode[] = [];\n // Keep the DOCUMENT node\n if (documentNode) {\n outputNodes.push(safeDeepClone(documentNode));\n }\n outputNodes.push(newCanvasNode);\n\n const outputBlobs: any[] = [];\n const blobRemap = new Map<number, number>();\n\n function copyBlob(sourceIdx: number | undefined | null): number | undefined {\n if (sourceIdx === undefined || sourceIdx === null || sourceIdx < 0) return undefined;\n if (!deckDoc.message?.blobs || sourceIdx >= deckDoc.message.blobs.length) return sourceIdx;\n\n if (blobRemap.has(sourceIdx)) {\n return blobRemap.get(sourceIdx)!;\n }\n\n const newIdx = outputBlobs.length;\n outputBlobs.push(safeDeepClone(deckDoc.message.blobs[sourceIdx]));\n blobRemap.set(sourceIdx, newIdx);\n return newIdx;\n }\n\n // 3. Process each slide\n const totalSlides = activeSlides.length;\n const paddingWidth = Math.max(2, String(totalSlides).length);\n\n activeSlides.forEach((slide, index) => {\n const slideId = guidToString(slide.guid);\n \n // Determine frame size - standard is 1920x1080\n const slideSize = slide.size ?? { x: 1920, y: 1080 };\n const width = slideSize.x;\n const height = slideSize.y;\n\n // Calculate layout position\n let x = 0;\n let y = 0;\n if (layout === \"grid\") {\n const col = index % wrap;\n const row = Math.floor(index / wrap);\n x = col * (width + gap);\n y = row * (height + gap);\n } else {\n x = index * (width + gap);\n y = 0;\n }\n\n // Try to resolve frame name: first text node or fallback\n let slideTitle = \"\";\n const children = deckDoc.childrenMap.get(slideId) || [];\n const instanceNode = children.find((c) => c.type === \"INSTANCE\");\n\n if (instanceNode?.symbolData?.symbolID) {\n const symGuidStr = guidToString(instanceNode.symbolData.symbolID);\n const symNode = deckDoc.nodeMap.get(symGuidStr);\n if (symNode) {\n // Look in the symbol subtree for the first text node\n const firstText = findFirstTextNode(deckDoc, symGuidStr);\n if (firstText) {\n // Check if there is an override in the instance for this text node\n const originalTextGuid = firstText.guid;\n const overrides = instanceNode.symbolData?.symbolOverrides || [];\n const ov = overrides.find(\n (o: any) =>\n o.guidPath?.guids?.length === 1 &&\n o.guidPath.guids[0].sessionID === originalTextGuid.sessionID &&\n o.guidPath.guids[0].localID === originalTextGuid.localID &&\n o.textData?.characters\n );\n slideTitle = ov?.textData?.characters || firstText.textData?.characters || \"\";\n }\n }\n }\n\n // Clean up title\n slideTitle = slideTitle.trim();\n const frameIndexStr = String(index + 1).padStart(paddingWidth, \"0\");\n const frameName = slideTitle ? `${frameIndexStr} · ${slideTitle}` : `${frameIndexStr} · Slide ${frameIndexStr}`;\n\n // Create the slide FRAME\n const frameGuid = generateGuid();\n const frameNode: FigNode = {\n guid: frameGuid,\n type: \"FRAME\",\n name: frameName,\n phase: \"CREATED\",\n parentIndex: {\n guid: canvasGuid,\n position: String.fromCharCode(0x21 + index),\n },\n size: { x: width, y: height },\n transform: { m00: 1, m01: 0, m02: x, m10: 0, m11: 1, m12: y },\n visible: true,\n opacity: 1,\n frameMaskDisabled: false,\n // Inherit fill paints and geometry from the SLIDE node\n fillPaints: slide.fillPaints ? safeDeepClone(slide.fillPaints) : [],\n fillGeometry: slide.fillGeometry ? safeDeepClone(slide.fillGeometry) : [],\n strokePaints: slide.strokePaints ? safeDeepClone(slide.strokePaints) : [],\n strokeWeight: slide.strokeWeight ?? 0,\n strokeAlign: slide.strokeAlign ?? \"INSIDE\",\n };\n\n // Re-index frame fill blobs\n if (frameNode.fillGeometry) {\n for (const fg of frameNode.fillGeometry) {\n if (fg.commandsBlob !== undefined) {\n fg.commandsBlob = copyBlob(fg.commandsBlob);\n }\n }\n }\n\n outputNodes.push(frameNode);\n\n // 4. Bake the INSTANCE contents into the frame\n if (instanceNode && instanceNode.symbolData?.symbolID) {\n const symGuidStr = guidToString(instanceNode.symbolData.symbolID);\n const symbolNode = deckDoc.nodeMap.get(symGuidStr);\n\n if (symbolNode) {\n // Collect all nodes in the symbol subtree\n const subtree: FigNode[] = [];\n const visited = new Set<string>();\n\n function collectSubtree(id: string) {\n if (visited.has(id)) return;\n visited.add(id);\n\n const node = deckDoc.nodeMap.get(id);\n if (!node || node.phase === \"REMOVED\") return;\n subtree.push(node);\n\n const kids = deckDoc.childrenMap.get(id) || [];\n for (const kid of kids) {\n collectSubtree(guidToString(kid.guid));\n }\n }\n\n // Collect children of the SYMBOL node, but not the SYMBOL node itself\n const symbolChildren = deckDoc.childrenMap.get(symGuidStr) || [];\n for (const child of symbolChildren) {\n collectSubtree(guidToString(child.guid));\n }\n\n // Create ID remap map for cloned symbol subtree\n const idRemap = new Map<string, FigGuid>();\n for (const node of subtree) {\n idRemap.set(guidToString(node.guid), generateGuid());\n }\n\n // Clone and apply overrides\n const clonedSubtree = subtree.map((node) => {\n const clone = safeDeepClone(node);\n const origIdStr = guidToString(node.guid);\n const newGuid = idRemap.get(origIdStr)!;\n clone.guid = newGuid;\n clone.phase = \"CREATED\";\n\n // Remove slide-scaffolding parameters\n delete clone.slideThumbnailHash;\n delete clone.editInfo;\n delete clone.prototypeInteractions;\n\n // Re-parent\n if (clone.parentIndex?.guid) {\n const parentIdStr = guidToString(clone.parentIndex.guid);\n if (parentIdStr === symGuidStr) {\n // Root of subtree is parented directly to the slide's new FRAME\n clone.parentIndex.guid = frameGuid;\n } else if (idRemap.has(parentIdStr)) {\n // Internal parent reference\n clone.parentIndex.guid = idRemap.get(parentIdStr)!;\n }\n }\n\n // Apply overrides from the instance\n const overrides = instanceNode.symbolData?.symbolOverrides || [];\n const matchingOverrides = overrides.filter((o: any) => {\n if (!o.guidPath?.guids?.length) return false;\n const lastGuid = o.guidPath.guids[o.guidPath.guids.length - 1];\n return (\n lastGuid.sessionID === node.guid.sessionID &&\n lastGuid.localID === node.guid.localID\n );\n });\n\n for (const ov of matchingOverrides) {\n if (ov.textData && clone.textData) {\n let chars = ov.textData.characters || \"\";\n if (chars === \"\") chars = \" \"; // Prevent Figma silent crashes\n clone.textData.characters = chars;\n }\n if (ov.fillPaints) {\n clone.fillPaints = safeDeepClone(ov.fillPaints);\n }\n if (ov.strokePaints) {\n clone.strokePaints = safeDeepClone(ov.strokePaints);\n }\n }\n\n // Re-index geometry blobs\n if (clone.fillGeometry) {\n for (const fg of clone.fillGeometry) {\n if (fg.commandsBlob !== undefined) {\n fg.commandsBlob = copyBlob(fg.commandsBlob);\n }\n }\n }\n if (clone.strokeGeometry) {\n for (const sg of clone.strokeGeometry) {\n if (sg.commandsBlob !== undefined) {\n sg.commandsBlob = copyBlob(sg.commandsBlob);\n }\n }\n }\n if (clone.vectorNetworkBlob !== undefined) {\n clone.vectorNetworkBlob = copyBlob(clone.vectorNetworkBlob);\n }\n\n return clone;\n });\n\n // Push baked nodes to output list\n outputNodes.push(...clonedSubtree);\n }\n }\n\n // 5. Clone and re-parent slide sibling nodes (non-INSTANCE children of the SLIDE node)\n for (const sibling of children) {\n if (sibling.type === \"INSTANCE\" || sibling.phase === \"REMOVED\") continue;\n\n const subtree: FigNode[] = [];\n const visited = new Set<string>();\n\n function collectSiblingSubtree(id: string) {\n if (visited.has(id)) return;\n visited.add(id);\n\n const node = deckDoc.nodeMap.get(id);\n if (!node || node.phase === \"REMOVED\") return;\n subtree.push(node);\n\n const kids = deckDoc.childrenMap.get(id) || [];\n for (const kid of kids) {\n collectSiblingSubtree(guidToString(kid.guid));\n }\n }\n\n collectSiblingSubtree(guidToString(sibling.guid));\n\n // Remap GUIDs to ensure uniqueness and clean reparenting\n const sibIdRemap = new Map<string, FigGuid>();\n for (const node of subtree) {\n sibIdRemap.set(guidToString(node.guid), generateGuid());\n }\n\n const clonedSibNodes = subtree.map((node) => {\n const clone = safeDeepClone(node);\n const origIdStr = guidToString(node.guid);\n const newGuid = sibIdRemap.get(origIdStr)!;\n clone.guid = newGuid;\n clone.phase = \"CREATED\";\n\n if (clone.parentIndex?.guid) {\n const parentIdStr = guidToString(clone.parentIndex.guid);\n if (parentIdStr === slideId) {\n clone.parentIndex.guid = frameGuid;\n } else if (sibIdRemap.has(parentIdStr)) {\n clone.parentIndex.guid = sibIdRemap.get(parentIdStr)!;\n }\n }\n\n // Re-index geometry blobs\n if (clone.fillGeometry) {\n for (const fg of clone.fillGeometry) {\n if (fg.commandsBlob !== undefined) {\n fg.commandsBlob = copyBlob(fg.commandsBlob);\n }\n }\n }\n if (clone.strokeGeometry) {\n for (const sg of clone.strokeGeometry) {\n if (sg.commandsBlob !== undefined) {\n sg.commandsBlob = copyBlob(sg.commandsBlob);\n }\n }\n }\n if (clone.vectorNetworkBlob !== undefined) {\n clone.vectorNetworkBlob = copyBlob(clone.vectorNetworkBlob);\n }\n\n return clone;\n });\n\n outputNodes.push(...clonedSibNodes);\n }\n });\n\n // 6. Keep global variables or theme metadata if present\n const globalSupportTypes = new Set([\n \"VARIABLE\",\n \"VARIABLE_SET\",\n \"VARIABLE_COLLECTION\",\n \"PUBLISHED_VARIABLE_COLLECTION\",\n ]);\n const supportNodes = deckDoc.nodes.filter((n) =>\n globalSupportTypes.has(n.type) && n.phase !== \"REMOVED\"\n );\n for (const sNode of supportNodes) {\n outputNodes.push(safeDeepClone(sNode));\n }\n\n // Build target childrenMap and nodeMap\n const nodeMap = new Map<string, FigNode>();\n const childrenMap = new Map<string, FigNode[]>();\n\n for (const node of outputNodes) {\n const id = guidToString(node.guid);\n nodeMap.set(id, node);\n }\n\n for (const node of outputNodes) {\n if (!node.parentIndex?.guid) continue;\n const pid = guidToString(node.parentIndex.guid);\n if (!childrenMap.has(pid)) {\n childrenMap.set(pid, []);\n }\n childrenMap.get(pid)!.push(node);\n }\n\n // Carry over meta and images\n const targetMeta = safeDeepClone(deckDoc.meta) || {};\n targetMeta.file_name = canvasName;\n\n // Build the new FigDocument\n const newDoc: FigDocument = {\n header: { prelude: \"fig-kiwi\", version: deckDoc.header.version },\n nodes: outputNodes,\n nodeMap,\n childrenMap,\n schema: safeDeepClone(deckDoc.schema),\n compiledSchema: deckDoc.compiledSchema,\n rawChunks: [\n deckDoc.rawChunks[0], // Schema chunk (will be re-deflated or kept as-is)\n new Uint8Array(0), // Placeholder for chunk 1 (pre-compressed canvas message)\n ...deckDoc.rawChunks.slice(2), // Remaining passthrough chunks\n ],\n message: {\n ...safeDeepClone(deckDoc.message),\n nodeChanges: outputNodes,\n blobs: outputBlobs,\n },\n meta: targetMeta,\n thumbnail: safeDeepClone(deckDoc.thumbnail),\n images: safeDeepClone(deckDoc.images),\n };\n\n return newDoc;\n}\n\n/** Helper to find the first TEXT node in a component subtree recursively. */\nfunction findFirstTextNode(doc: FigDocument, id: string): FigNode | null {\n const node = doc.nodeMap.get(id);\n if (!node || node.phase === \"REMOVED\") return null;\n if (node.type === \"TEXT\" && node.textData?.characters) return node;\n\n const children = doc.childrenMap.get(id) || [];\n for (const child of children) {\n const found = findFirstTextNode(doc, guidToString(child.guid));\n if (found) return found;\n }\n return null;\n}\n","/** Pre-built empty .fig template — generated by src/utilities/generateTemplate.ts */\n/** @deprecated-backup Figma-derived blob (kept for rollback only):\n * UEsDBBQAAAAAALu8cFyLpHS2wWcAAMFnAAAKAAAAY2FudmFzLmZpZ2ZpZy1raXdpZQAAAJJlAAC0fQuY...\n */\nexport const emptyFigTemplate = \"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\";\n","/**\n * Creates an empty FigDocument by parsing a pre-built template.\n * The template was created from a valid .fig file with user content\n * marked as REMOVED — proven to open in Figma.\n */\n\nimport { parseFig } from \"./parser.js\";\nimport { emptyFigTemplate } from \"./schema.js\";\nimport type { FigDocument } from \"./types.js\";\n\nfunction b64decode(b64: string): Uint8Array {\n const bin = atob(b64);\n const bytes = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\nexport function createEmptyFigDoc(): FigDocument {\n const bytes = b64decode(emptyFigTemplate);\n return parseFig(bytes);\n}\n","import type { FigGradientStop, FigPaint, FigTransform } from \"./types.js\";\n\nexport type GradientKind = \"linear\" | \"radial\";\n\nexport interface GradientFillLike {\n type: GradientKind;\n transform: FigTransform;\n}\n\nexport interface RenderableGradientFill extends GradientFillLike {\n opacity: number;\n stops: FigGradientStop[];\n}\n\nexport interface GradientPoint {\n x: number;\n y: number;\n}\n\nexport interface ResolvedLinearGradientGeometry {\n type: \"linear\";\n start: GradientPoint;\n end: GradientPoint;\n}\n\nexport interface ResolvedRadialGradientGeometry {\n type: \"radial\";\n center: GradientPoint;\n radiusX: number;\n radiusY: number;\n angle: number;\n}\n\nexport type ResolvedGradientGeometry =\n | ResolvedLinearGradientGeometry\n | ResolvedRadialGradientGeometry;\n\nconst IDENTITY_TRANSFORM: FigTransform = {\n m00: 1,\n m01: 0,\n m02: 0,\n m10: 0,\n m11: 1,\n m12: 0,\n};\n\nfunction cloneTransform(transform?: FigTransform): FigTransform {\n if (!transform) return { ...IDENTITY_TRANSFORM };\n return {\n m00: transform.m00,\n m01: transform.m01,\n m02: transform.m02,\n m10: transform.m10,\n m11: transform.m11,\n m12: transform.m12,\n };\n}\n\nfunction isRenderableGradientPaint(\n paint: FigPaint | null | undefined,\n): paint is FigPaint & { type: \"GRADIENT_LINEAR\" | \"GRADIENT_RADIAL\"; stops: FigGradientStop[] } {\n return !!paint &&\n paint.visible !== false &&\n (paint.type === \"GRADIENT_LINEAR\" || paint.type === \"GRADIENT_RADIAL\") &&\n Array.isArray(paint.stops) &&\n paint.stops.length > 0;\n}\n\nexport function extractRenderableGradientFill(\n paints: FigPaint[] | null | undefined,\n): RenderableGradientFill | null {\n const paint = paints?.find((entry) => isRenderableGradientPaint(entry));\n if (!paint) return null;\n\n return {\n type: paint.type === \"GRADIENT_LINEAR\" ? \"linear\" : \"radial\",\n opacity: paint.opacity ?? 1,\n transform: cloneTransform(paint.transform),\n stops: [...paint.stops]\n .sort((a, b) => a.position - b.position)\n .map((stop) => ({\n position: stop.position,\n color: { ...stop.color },\n colorVar: stop.colorVar,\n })),\n };\n}\n\nexport function resolveGradientGeometry(\n fill: GradientFillLike,\n width: number,\n height: number,\n): ResolvedGradientGeometry | null {\n if (width <= 0 || height <= 0) return null;\n\n const transform = fill.transform ?? IDENTITY_TRANSFORM;\n const { m00, m01, m02, m10, m11, m12 } = transform;\n const det = m00 * m11 - m10 * m01;\n if (Math.abs(det) < 1e-12) return null;\n\n // Figma stores paint.transform as node-space -> gradient-space.\n // Consumers usually need the inverse: gradient-space -> node-space.\n const ia = m11 / det;\n const ic = -m01 / det;\n const ie = (m01 * m12 - m11 * m02) / det;\n const ib = -m10 / det;\n const iid = m00 / det;\n const iif = (m10 * m02 - m00 * m12) / det;\n\n const point = (gx: number, gy: number): GradientPoint => ({\n x: (ia * gx + ic * gy + ie) * width,\n y: (ib * gx + iid * gy + iif) * height,\n });\n\n if (fill.type === \"linear\") {\n return {\n type: \"linear\",\n start: point(0, 0.5),\n end: point(1, 0.5),\n };\n }\n\n const center = point(0.5, 0.5);\n const xAxisPoint = point(1, 0.5);\n const yAxisPoint = point(0.5, 1);\n\n return {\n type: \"radial\",\n center,\n radiusX: Math.hypot(xAxisPoint.x - center.x, xAxisPoint.y - center.y),\n radiusY: Math.hypot(yAxisPoint.x - center.x, yAxisPoint.y - center.y),\n angle: Math.atan2(xAxisPoint.y - center.y, xAxisPoint.x - center.x),\n };\n}\n","import type { FigDocument, FigNode, FigPaint } from \"./types.js\";\n\nconst CMD_CLOSE = 0;\nconst CMD_MOVE_TO = 1;\nconst CMD_LINE_TO = 2;\nconst CMD_CUBIC_TO = 4;\nconst SEGMENT_LINE = 0;\nconst SEGMENT_CUBIC = 4;\nconst DEFAULT_HANDLE_MIRRORING = 4;\n\ntype GeometryRef = {\n commandsBlob?: number;\n windingRule?: string;\n styleID?: number;\n};\n\ntype StyleOverride = {\n styleID?: number;\n fillPaints?: FigPaint[];\n};\n\nexport interface ResolvedGeometryPath {\n blobIndex: number;\n commandsBlob: Uint8Array;\n svgPath: string;\n windingRule?: string;\n styleID: number;\n paints?: FigPaint[];\n}\n\nexport interface ResolvedVectorNodePaths {\n fill: ResolvedGeometryPath[];\n stroke: ResolvedGeometryPath[];\n}\n\nexport type VectorPathCommand =\n | { type: \"M\"; x: number; y: number }\n | { type: \"L\"; x: number; y: number }\n | { type: \"C\"; c1x: number; c1y: number; c2x: number; c2y: number; x: number; y: number }\n | { type: \"Z\" };\n\nfunction quadraticToCubic(\n x0: number,\n y0: number,\n qx: number,\n qy: number,\n x: number,\n y: number,\n): Extract<VectorPathCommand, { type: \"C\" }> {\n return {\n type: \"C\",\n c1x: x0 + (2 / 3) * (qx - x0),\n c1y: y0 + (2 / 3) * (qy - y0),\n c2x: x + (2 / 3) * (qx - x),\n c2y: y + (2 / 3) * (qy - y),\n x,\n y,\n };\n}\n\nexport interface VectorGeometryInput {\n svgPath?: string;\n commands?: readonly VectorPathCommand[];\n windingRule?: string;\n styleID?: number;\n}\n\nexport interface VectorStyleOverride {\n styleID: number;\n fillPaints?: FigPaint[];\n [key: string]: any;\n}\n\nexport interface AppendVectorPayloadInput {\n width: number;\n height: number;\n normalizedWidth?: number;\n normalizedHeight?: number;\n fillPaths?: readonly VectorGeometryInput[];\n /**\n * Stroke geometry is expected to already be expanded into outline paths.\n * This helper does not expand SVG strokes into strokeGeometry.\n */\n strokePaths?: readonly VectorGeometryInput[];\n styleOverrideTable?: readonly VectorStyleOverride[];\n}\n\nexport interface AuthoredVectorPayload {\n fillGeometry: GeometryRef[];\n strokeGeometry: GeometryRef[];\n vectorData: {\n vectorNetworkBlob: number;\n normalizedSize: { x: number; y: number };\n styleOverrideTable?: VectorStyleOverride[];\n };\n}\n\nexport function roundPathNumber(n: number, decimals = 2): number {\n const factor = 10 ** decimals;\n return Math.round(n * factor) / factor;\n}\n\nexport function getBlobBytes(doc: FigDocument, blobIndex: number | null | undefined): Uint8Array | null {\n if (blobIndex == null || blobIndex < 0) return null;\n\n const blob = doc.message?.blobs?.[blobIndex];\n if (!blob) return null;\n\n if (blob instanceof Uint8Array) return blob;\n if (blob.bytes instanceof Uint8Array) return blob.bytes;\n if (Array.isArray(blob.bytes)) return Uint8Array.from(blob.bytes);\n\n if (blob.bytes && typeof blob.bytes === \"object\") {\n const values = Object.values(blob.bytes);\n if (values.every((value) => typeof value === \"number\")) {\n return Uint8Array.from(values as number[]);\n }\n }\n\n return null;\n}\n\nexport function geometryBlobToSVGPath(blob: Uint8Array): string {\n if (!blob.length) return \"\";\n\n const view = new DataView(blob.buffer, blob.byteOffset, blob.byteLength);\n let offset = 0;\n const parts: string[] = [];\n\n const canRead = (byteLength: number) => offset + byteLength <= blob.length;\n\n while (offset < blob.length) {\n const cmd = blob[offset++];\n\n switch (cmd) {\n case CMD_CLOSE:\n parts.push(\"Z\");\n break;\n\n case CMD_MOVE_TO: {\n if (!canRead(8)) return parts.join(\"\");\n const x = roundPathNumber(view.getFloat32(offset, true));\n const y = roundPathNumber(view.getFloat32(offset + 4, true));\n offset += 8;\n parts.push(`M${x} ${y}`);\n break;\n }\n\n case CMD_LINE_TO: {\n if (!canRead(8)) return parts.join(\"\");\n const x = roundPathNumber(view.getFloat32(offset, true));\n const y = roundPathNumber(view.getFloat32(offset + 4, true));\n offset += 8;\n parts.push(`L${x} ${y}`);\n break;\n }\n\n case CMD_CUBIC_TO: {\n if (!canRead(24)) return parts.join(\"\");\n const x1 = roundPathNumber(view.getFloat32(offset, true));\n const y1 = roundPathNumber(view.getFloat32(offset + 4, true));\n const x2 = roundPathNumber(view.getFloat32(offset + 8, true));\n const y2 = roundPathNumber(view.getFloat32(offset + 12, true));\n const x = roundPathNumber(view.getFloat32(offset + 16, true));\n const y = roundPathNumber(view.getFloat32(offset + 20, true));\n offset += 24;\n parts.push(`C${x1} ${y1} ${x2} ${y2} ${x} ${y}`);\n break;\n }\n\n default:\n return parts.join(\"\");\n }\n }\n\n return parts.join(\"\");\n}\n\nexport function parseSVGPathData(svgPath: string): VectorPathCommand[] {\n const tokens: Array<string | number> = [];\n const re = /([MmLlCcSsQqTtHhVvZz])|([+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(svgPath)) !== null) {\n if (match[1]) tokens.push(match[1]);\n else tokens.push(Number.parseFloat(match[2]));\n }\n\n const commands: VectorPathCommand[] = [];\n let i = 0;\n let cx = 0;\n let cy = 0;\n let startX = 0;\n let startY = 0;\n let prevC2x = 0;\n let prevC2y = 0;\n let prevQuadraticX = 0;\n let prevQuadraticY = 0;\n let cmd = \"\";\n const num = () => {\n const value = tokens[i++];\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n throw new Error(`Invalid SVG path data near token index ${i - 1}`);\n }\n return value;\n };\n\n while (i < tokens.length) {\n if (typeof tokens[i] === \"string\") cmd = tokens[i++] as string;\n switch (cmd) {\n case \"M\":\n cx = num(); cy = num(); startX = cx; startY = cy;\n commands.push({ type: \"M\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n cmd = \"L\";\n break;\n case \"m\":\n cx += num(); cy += num(); startX = cx; startY = cy;\n commands.push({ type: \"M\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n cmd = \"l\";\n break;\n case \"L\":\n cx = num(); cy = num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"l\":\n cx += num(); cy += num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"H\":\n cx = num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"h\":\n cx += num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"V\":\n cy = num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"v\":\n cy += num();\n commands.push({ type: \"L\", x: cx, y: cy });\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"C\": {\n const c1x = num();\n const c1y = num();\n const c2x = num();\n const c2y = num();\n cx = num();\n cy = num();\n prevC2x = c2x;\n prevC2y = c2y;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n commands.push({ type: \"C\", c1x, c1y, c2x, c2y, x: cx, y: cy });\n break;\n }\n case \"c\": {\n const c1x = cx + num();\n const c1y = cy + num();\n const c2x = cx + num();\n const c2y = cy + num();\n cx += num();\n cy += num();\n prevC2x = c2x;\n prevC2y = c2y;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n commands.push({ type: \"C\", c1x, c1y, c2x, c2y, x: cx, y: cy });\n break;\n }\n case \"S\": {\n const c1x = 2 * cx - prevC2x;\n const c1y = 2 * cy - prevC2y;\n const c2x = num();\n const c2y = num();\n cx = num();\n cy = num();\n prevC2x = c2x;\n prevC2y = c2y;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n commands.push({ type: \"C\", c1x, c1y, c2x, c2y, x: cx, y: cy });\n break;\n }\n case \"s\": {\n const c1x = 2 * cx - prevC2x;\n const c1y = 2 * cy - prevC2y;\n const c2x = cx + num();\n const c2y = cy + num();\n cx += num();\n cy += num();\n prevC2x = c2x;\n prevC2y = c2y;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n commands.push({ type: \"C\", c1x, c1y, c2x, c2y, x: cx, y: cy });\n break;\n }\n case \"Q\": {\n const qx = num();\n const qy = num();\n const x = num();\n const y = num();\n const cubic = quadraticToCubic(cx, cy, qx, qy, x, y);\n commands.push(cubic);\n prevQuadraticX = qx;\n prevQuadraticY = qy;\n prevC2x = cubic.c2x;\n prevC2y = cubic.c2y;\n cx = x;\n cy = y;\n break;\n }\n case \"q\": {\n const qx = cx + num();\n const qy = cy + num();\n const x = cx + num();\n const y = cy + num();\n const cubic = quadraticToCubic(cx, cy, qx, qy, x, y);\n commands.push(cubic);\n prevQuadraticX = qx;\n prevQuadraticY = qy;\n prevC2x = cubic.c2x;\n prevC2y = cubic.c2y;\n cx = x;\n cy = y;\n break;\n }\n case \"T\": {\n const qx = 2 * cx - prevQuadraticX;\n const qy = 2 * cy - prevQuadraticY;\n const x = num();\n const y = num();\n const cubic = quadraticToCubic(cx, cy, qx, qy, x, y);\n commands.push(cubic);\n prevQuadraticX = qx;\n prevQuadraticY = qy;\n prevC2x = cubic.c2x;\n prevC2y = cubic.c2y;\n cx = x;\n cy = y;\n break;\n }\n case \"t\": {\n const qx = 2 * cx - prevQuadraticX;\n const qy = 2 * cy - prevQuadraticY;\n const x = cx + num();\n const y = cy + num();\n const cubic = quadraticToCubic(cx, cy, qx, qy, x, y);\n commands.push(cubic);\n prevQuadraticX = qx;\n prevQuadraticY = qy;\n prevC2x = cubic.c2x;\n prevC2y = cubic.c2y;\n cx = x;\n cy = y;\n break;\n }\n case \"Z\":\n case \"z\":\n commands.push({ type: \"Z\" });\n cx = startX;\n cy = startY;\n prevC2x = cx;\n prevC2y = cy;\n prevQuadraticX = cx;\n prevQuadraticY = cy;\n break;\n case \"\":\n i++;\n break;\n default:\n throw new Error(`Unsupported SVG path command: ${cmd}`);\n }\n }\n\n return commands;\n}\n\nexport function encodeCommandsBlob(\n commands: readonly VectorPathCommand[],\n scaleX = 1,\n scaleY = 1,\n): Uint8Array {\n let byteLength = 0;\n for (const command of commands) {\n byteLength += 1;\n if (command.type === \"M\" || command.type === \"L\") byteLength += 8;\n else if (command.type === \"C\") byteLength += 24;\n }\n\n const buffer = new ArrayBuffer(byteLength);\n const view = new DataView(buffer);\n let offset = 0;\n\n for (const command of commands) {\n switch (command.type) {\n case \"M\":\n view.setUint8(offset++, CMD_MOVE_TO);\n view.setFloat32(offset, command.x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.y * scaleY, true); offset += 4;\n break;\n case \"L\":\n view.setUint8(offset++, CMD_LINE_TO);\n view.setFloat32(offset, command.x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.y * scaleY, true); offset += 4;\n break;\n case \"C\":\n view.setUint8(offset++, CMD_CUBIC_TO);\n view.setFloat32(offset, command.c1x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.c1y * scaleY, true); offset += 4;\n view.setFloat32(offset, command.c2x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.c2y * scaleY, true); offset += 4;\n view.setFloat32(offset, command.x * scaleX, true); offset += 4;\n view.setFloat32(offset, command.y * scaleY, true); offset += 4;\n break;\n case \"Z\":\n view.setUint8(offset++, CMD_CLOSE);\n break;\n }\n }\n\n return new Uint8Array(buffer, 0, offset);\n}\n\nexport function encodeVectorNetworkBlob(pathCommandsList: readonly (readonly VectorPathCommand[])[]): Uint8Array {\n const vertices: Array<{ x: number; y: number }> = [];\n const segments: Array<{ s: number; tsx: number; tsy: number; e: number; tex: number; tey: number; t: number }> = [];\n const regions: number[][] = [];\n\n for (const pathCommands of pathCommandsList) {\n let regionSegments: number[] = [];\n let firstVertex = -1;\n let prevVertex = -1;\n let prevX = 0;\n let prevY = 0;\n\n for (const command of pathCommands) {\n if (command.type === \"M\") {\n // Each sub-path (M...Z sequence) becomes its own region so Figma\n // strokes compound paths correctly (e.g. counter holes in letters).\n if (regionSegments.length > 0) {\n regions.push(regionSegments);\n regionSegments = [];\n }\n const vertexIndex = vertices.length;\n vertices.push({ x: command.x, y: command.y });\n firstVertex = vertexIndex;\n prevVertex = vertexIndex;\n prevX = command.x;\n prevY = command.y;\n } else if (command.type === \"L\") {\n const vertexIndex = vertices.length;\n vertices.push({ x: command.x, y: command.y });\n if (prevVertex >= 0) {\n regionSegments.push(segments.length);\n segments.push({ s: prevVertex, tsx: 0, tsy: 0, e: vertexIndex, tex: 0, tey: 0, t: SEGMENT_LINE });\n }\n prevVertex = vertexIndex;\n prevX = command.x;\n prevY = command.y;\n } else if (command.type === \"C\") {\n const vertexIndex = vertices.length;\n vertices.push({ x: command.x, y: command.y });\n if (prevVertex >= 0) {\n regionSegments.push(segments.length);\n segments.push({\n s: prevVertex,\n tsx: command.c1x - prevX,\n tsy: command.c1y - prevY,\n e: vertexIndex,\n tex: command.c2x - command.x,\n tey: command.c2y - command.y,\n t: SEGMENT_CUBIC,\n });\n }\n prevVertex = vertexIndex;\n prevX = command.x;\n prevY = command.y;\n } else if (command.type === \"Z\") {\n if (prevVertex >= 0 && prevVertex !== firstVertex) {\n const lastPos = vertices[prevVertex];\n const firstPos = vertices[firstVertex];\n const dx = lastPos.x - firstPos.x;\n const dy = lastPos.y - firstPos.y;\n if (dx * dx + dy * dy < 1e-4) {\n // Path already returned to start — merge the duplicate end vertex\n // into firstVertex so Figma sees one vertex with correct incoming\n // and outgoing bezier tangent handles for miter join computation.\n // Without this, a zero-length closing LINE segment would give Figma\n // a degenerate tangent, producing wrong miter angles (visible as\n // notches at sharp corners like the \"g\" terminal).\n const lastSeg = segments[segments.length - 1];\n if (lastSeg && lastSeg.e === prevVertex) {\n lastSeg.e = firstVertex;\n vertices.pop();\n }\n } else {\n regionSegments.push(segments.length);\n segments.push({ s: prevVertex, tsx: 0, tsy: 0, e: firstVertex, tex: 0, tey: 0, t: SEGMENT_LINE });\n }\n }\n if (firstVertex >= 0) {\n prevVertex = firstVertex;\n prevX = vertices[firstVertex].x;\n prevY = vertices[firstVertex].y;\n }\n }\n }\n\n regions.push(regionSegments);\n }\n\n let regionsByteLength = 0;\n for (const region of regions) regionsByteLength += 4 + 4 + (region.length * 4) + 4;\n const totalByteLength = 16 + (vertices.length * 12) + (segments.length * 28) + regionsByteLength;\n\n const buffer = new ArrayBuffer(totalByteLength);\n const view = new DataView(buffer);\n let offset = 0;\n\n view.setUint32(offset, vertices.length, true); offset += 4;\n view.setUint32(offset, segments.length, true); offset += 4;\n view.setUint32(offset, regions.length, true); offset += 4;\n view.setUint32(offset, 1, true); offset += 4;\n\n for (const vertex of vertices) {\n view.setFloat32(offset, vertex.x, true); offset += 4;\n view.setFloat32(offset, vertex.y, true); offset += 4;\n view.setUint32(offset, DEFAULT_HANDLE_MIRRORING, true); offset += 4;\n }\n\n for (const segment of segments) {\n view.setUint32(offset, segment.s, true); offset += 4;\n view.setFloat32(offset, segment.tsx, true); offset += 4;\n view.setFloat32(offset, segment.tsy, true); offset += 4;\n view.setUint32(offset, segment.e, true); offset += 4;\n view.setFloat32(offset, segment.tex, true); offset += 4;\n view.setFloat32(offset, segment.tey, true); offset += 4;\n view.setUint32(offset, segment.t, true); offset += 4;\n }\n\n for (const region of regions) {\n view.setUint32(offset, 1, true); offset += 4;\n view.setUint32(offset, region.length, true); offset += 4;\n for (const segmentIndex of region) {\n view.setUint32(offset, segmentIndex, true); offset += 4;\n }\n view.setUint32(offset, 1, true); offset += 4;\n }\n\n return new Uint8Array(buffer, 0, offset);\n}\n\nfunction cloneStyleOverrides(styleOverrideTable: readonly VectorStyleOverride[] | undefined): VectorStyleOverride[] | undefined {\n if (!styleOverrideTable?.length) return undefined;\n return JSON.parse(JSON.stringify(styleOverrideTable));\n}\n\nfunction toCommands(input: VectorGeometryInput): VectorPathCommand[] {\n if (Array.isArray(input.commands) && input.commands.length > 0) {\n return input.commands.map((command) => ({ ...command }));\n }\n if (input.svgPath) return parseSVGPathData(input.svgPath);\n throw new Error(\"Vector geometry input requires either svgPath or commands\");\n}\n\nexport function appendVectorPayloadToDocument(\n doc: FigDocument,\n input: AppendVectorPayloadInput,\n): AuthoredVectorPayload {\n const blobs: any[] = doc.message?.blobs ?? (doc.message.blobs = []);\n const normalizedWidth = input.normalizedWidth ?? input.width;\n const normalizedHeight = input.normalizedHeight ?? input.height;\n const scaleX = normalizedWidth === 0 ? 1 : input.width / normalizedWidth;\n const scaleY = normalizedHeight === 0 ? 1 : input.height / normalizedHeight;\n\n const fillPaths = (input.fillPaths ?? []).map(toCommands);\n const strokePaths = (input.strokePaths ?? []).map(toCommands);\n if (fillPaths.length === 0 && strokePaths.length === 0) {\n throw new Error(\"Vector payload requires at least one fill or stroke path\");\n }\n\n const fillGeometry: GeometryRef[] = [];\n for (let i = 0; i < fillPaths.length; i++) {\n const bytes = encodeCommandsBlob(fillPaths[i], scaleX, scaleY);\n blobs.push({ bytes });\n const path = input.fillPaths?.[i];\n fillGeometry.push({\n windingRule: path?.windingRule ?? \"NONZERO\",\n commandsBlob: blobs.length - 1,\n styleID: path?.styleID ?? 0,\n });\n }\n\n const strokeGeometry: GeometryRef[] = [];\n for (let i = 0; i < strokePaths.length; i++) {\n const bytes = encodeCommandsBlob(strokePaths[i], scaleX, scaleY);\n blobs.push({ bytes });\n const path = input.strokePaths?.[i];\n strokeGeometry.push({\n windingRule: path?.windingRule ?? \"NONZERO\",\n commandsBlob: blobs.length - 1,\n styleID: path?.styleID ?? 0,\n });\n }\n\n const vectorNetworkBlob = encodeVectorNetworkBlob([...fillPaths, ...strokePaths]);\n blobs.push({ bytes: vectorNetworkBlob });\n\n return {\n fillGeometry,\n strokeGeometry,\n vectorData: {\n vectorNetworkBlob: blobs.length - 1,\n normalizedSize: { x: normalizedWidth, y: normalizedHeight },\n ...(cloneStyleOverrides(input.styleOverrideTable)?.length\n ? { styleOverrideTable: cloneStyleOverrides(input.styleOverrideTable) }\n : {}),\n },\n };\n}\n\nfunction getStyleOverrideTable(node: FigNode): StyleOverride[] {\n const table = node.vectorData?.styleOverrideTable;\n return Array.isArray(table) ? table : [];\n}\n\nfunction resolveFillPaints(node: FigNode, styleID: number): FigPaint[] | undefined {\n if (!styleID) return node.fillPaints;\n const override = getStyleOverrideTable(node).find((entry) => entry?.styleID === styleID);\n if (!override || !(\"fillPaints\" in override)) return node.fillPaints;\n return override.fillPaints;\n}\n\nfunction resolveGeometry(\n doc: FigDocument,\n node: FigNode,\n geometry: GeometryRef[] | undefined,\n kind: \"fill\" | \"stroke\",\n): ResolvedGeometryPath[] {\n if (!Array.isArray(geometry) || geometry.length === 0) return [];\n\n const resolved: Array<ResolvedGeometryPath | null> = geometry.map((entry) => {\n if (typeof entry?.commandsBlob !== \"number\") return null;\n const bytes = getBlobBytes(doc, entry.commandsBlob);\n if (!bytes) return null;\n const svgPath = geometryBlobToSVGPath(bytes);\n if (!svgPath) return null;\n\n const path: ResolvedGeometryPath = {\n blobIndex: entry.commandsBlob,\n commandsBlob: bytes,\n svgPath,\n windingRule: entry.windingRule,\n styleID: entry.styleID || 0,\n paints: kind === \"fill\" ? resolveFillPaints(node, entry.styleID || 0) : node.strokePaints,\n };\n\n return path;\n });\n\n return resolved.filter((entry): entry is ResolvedGeometryPath => entry !== null);\n}\n\nexport function resolveVectorNodePaths(doc: FigDocument, node: FigNode): ResolvedVectorNodePaths {\n return {\n fill: resolveGeometry(doc, node, node.fillGeometry as GeometryRef[] | undefined, \"fill\"),\n stroke: resolveGeometry(doc, node, node.strokeGeometry as GeometryRef[] | undefined, \"stroke\"),\n };\n}\n","/**\n * CSS / hex color ↔ Figma normalized RGBA color helpers.\n *\n * All functions are isomorphic (no DOM required).\n * For named CSS colors (e.g. \"coral\"), pass an optional `resolveNamed`\n * callback that uses the browser's computed-style machinery.\n */\n\nimport type { FigColor, FigPaint } from \"./types.js\";\n\nexport function hexToFigColor(hex: string): FigColor {\n if (!hex || hex === \"transparent\") return { r: 0, g: 0, b: 0, a: 0 };\n const h = hex.replace(\"#\", \"\");\n const r = parseInt(h.substring(0, 2), 16) / 255;\n const g = parseInt(h.substring(2, 4), 16) / 255;\n const b = parseInt(h.substring(4, 6), 16) / 255;\n const a = h.length >= 8 ? parseInt(h.substring(6, 8), 16) / 255 : 1;\n return { r, g, b, a };\n}\n\nexport function parseCssRgbColor(value: string): FigColor | null {\n const match = value.trim().match(/^rgba?\\((.+)\\)$/i);\n if (!match) return null;\n const parts = match[1].split(\",\").map((part) => part.trim());\n if (parts.length < 3) return null;\n const r = Number.parseFloat(parts[0]);\n const g = Number.parseFloat(parts[1]);\n const b = Number.parseFloat(parts[2]);\n const a = parts.length >= 4 ? Number.parseFloat(parts[3]) : 1;\n if ([r, g, b, a].some((n) => Number.isNaN(n))) return null;\n return { r: r / 255, g: g / 255, b: b / 255, a };\n}\n\nexport function cssColorToFigColor(\n value: string,\n resolveNamed?: (name: string) => FigColor | null,\n): FigColor {\n const trimmed = value.trim();\n if (trimmed === \"transparent\" || trimmed === \"none\") return { r: 0, g: 0, b: 0, a: 0 };\n if (trimmed.startsWith(\"#\")) return hexToFigColor(trimmed);\n const rgba = parseCssRgbColor(trimmed);\n if (rgba) return rgba;\n\n if (resolveNamed) {\n const resolved = resolveNamed(trimmed);\n if (resolved) return resolved;\n }\n\n throw new Error(`Unsupported CSS color: ${value}`);\n}\n\nexport function makeSolidPaint(\n fill: string,\n resolveNamed?: (name: string) => FigColor | null,\n): FigPaint {\n const color = cssColorToFigColor(fill, resolveNamed);\n return {\n type: \"SOLID\",\n color: { r: color.r, g: color.g, b: color.b, a: 1 },\n opacity: color.a,\n visible: true,\n blendMode: \"NORMAL\",\n };\n}\n","/**\n * SVG path serialization, transformation, and stroke/cap enum mapping.\n */\n\nimport { parseSVGPathData } from \"./vector.js\";\nimport type { VectorPathCommand } from \"./vector.js\";\n\nexport function serializeSvgPathData(commands: readonly VectorPathCommand[]): string {\n return commands\n .map((command) => {\n switch (command.type) {\n case \"M\":\n return `M${command.x} ${command.y}`;\n case \"L\":\n return `L${command.x} ${command.y}`;\n case \"C\":\n return `C${command.c1x} ${command.c1y} ${command.c2x} ${command.c2y} ${command.x} ${command.y}`;\n case \"Z\":\n return \"Z\";\n }\n })\n .join(\" \");\n}\n\nexport function transformSvgPathData(\n svgPath: string,\n {\n scaleX = 1,\n scaleY = 1,\n translateX = 0,\n translateY = 0,\n }: { scaleX?: number; scaleY?: number; translateX?: number; translateY?: number },\n): string {\n const commands = parseSVGPathData(svgPath).map((command) => {\n switch (command.type) {\n case \"M\":\n case \"L\":\n return {\n ...command,\n x: command.x * scaleX + translateX,\n y: command.y * scaleY + translateY,\n };\n case \"C\":\n return {\n ...command,\n c1x: command.c1x * scaleX + translateX,\n c1y: command.c1y * scaleY + translateY,\n c2x: command.c2x * scaleX + translateX,\n c2y: command.c2y * scaleY + translateY,\n x: command.x * scaleX + translateX,\n y: command.y * scaleY + translateY,\n };\n case \"Z\":\n return command;\n }\n });\n\n return serializeSvgPathData(commands);\n}\n\nexport function mapStrokeJoin(value: string | undefined): string {\n switch ((value || \"\").toLowerCase()) {\n case \"round\":\n return \"ROUND\";\n case \"bevel\":\n return \"BEVEL\";\n default:\n return \"MITER\";\n }\n}\n\nexport function mapStrokeCap(value: string | undefined): string {\n switch ((value || \"\").toLowerCase()) {\n case \"round\":\n return \"ROUND\";\n case \"square\":\n return \"SQUARE\";\n default:\n return \"NONE\";\n }\n}\n"],"mappings":"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","names":["collectSubtree","collectSiblingSubtree"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openfig-core",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Isomorphic .fig file parser — reads Figma binary format in Node.js and browsers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",