@effing/canvas 0.19.2 → 0.19.3
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 +55 -229
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/lottie.ts","../src/jsx/draw/index.ts","../src/jsx/language.ts","../src/jsx/text/linebreak.ts","../src/jsx/text/measure.ts","../src/jsx/text/index.ts","../src/jsx/draw/clip.ts","../src/jsx/draw/gradient.ts","../src/jsx/draw/image.ts","../src/jsx/draw/object-fit.ts","../src/jsx/draw/rect.ts","../src/jsx/draw/svg.ts","../src/jsx/draw/text.ts","../src/jsx/emoji.ts","../src/jsx/text/emoji-split.ts","../src/jsx/font.ts","../src/jsx/layout.ts","../src/jsx/style/expand.ts","../src/jsx/style/compute.ts","../src/jsx/yoga.ts","../src/jsx/style/properties.ts","../src/jsx/index.ts"],"sourcesContent":["// Re-export canvas primitives from @napi-rs/canvas\nimport { createCanvas as _createCanvas } from \"@napi-rs/canvas\";\nexport {\n Canvas,\n type SKRSContext2D,\n GlobalFonts,\n loadImage,\n Image,\n} from \"@napi-rs/canvas\";\n\nexport function createCanvas(width: number, height: number) {\n const canvas = _createCanvas(width, height);\n const origEncode = canvas.encode.bind(canvas);\n type Encode = typeof canvas.encode;\n\n // The native @napi-rs/canvas encode() returns Buffers backed by Rust/Skia\n // memory that can be freed before downstream consumers finish reading (e.g.\n // when streaming frames concurrently). We patch encode to copy the result\n // to the JS heap so the data remains valid regardless of native GC timing.\n canvas.encode = (async (...args: unknown[]) =>\n Buffer.from(await origEncode(...(args as Parameters<Encode>)))) as Encode;\n\n return canvas;\n}\n\n// Lottie API\nexport { LottieAnimation, loadLottie, renderLottieFrame } from \"./lottie.ts\";\n\n// JSX API\nexport { renderReactElement } from \"./jsx/index.ts\";\n\n// Font management\nexport {\n registerFont,\n registerFontFromPath,\n registeredFamilies,\n} from \"./jsx/font.ts\";\n\n// Types\nexport type {\n FontData,\n RenderReactElementOptions,\n EmojiStyle,\n} from \"./types.ts\";\n","import { LottieAnimation } from \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\n\nexport { LottieAnimation };\n\n/**\n * Load a Lottie animation from a JSON string or Buffer.\n *\n * @param data - Lottie JSON string or Buffer\n * @param options - Optional resource path for external assets\n * @returns A `LottieAnimation` handle ready for rendering\n *\n * @example\n * ```ts\n * const anim = loadLottie(fs.readFileSync(\"animation.json\", \"utf-8\"));\n * ```\n */\nexport function loadLottie(\n data: string | Buffer,\n options?: { resourcePath?: string },\n): LottieAnimation {\n const jsonString = typeof data === \"string\" ? data : data.toString(\"utf-8\");\n return LottieAnimation.loadFromData(jsonString, {\n resourcePath: options?.resourcePath,\n });\n}\n\n/**\n * Render a specific frame of a Lottie animation to a canvas context.\n *\n * Seeks the animation to the given frame, then renders it onto the\n * provided context. The canvas dimensions determine the render size.\n *\n * @param ctx - Canvas 2D rendering context to draw into\n * @param animation - Lottie animation handle (from {@link loadLottie})\n * @param frame - Zero-based frame number to render\n *\n * @example\n * ```ts\n * import { createCanvas, loadLottie, renderLottieFrame } from \"@effing/canvas\";\n *\n * const canvas = createCanvas(1080, 1080);\n * const ctx = canvas.getContext(\"2d\");\n * const anim = loadLottie(jsonString);\n *\n * renderLottieFrame(ctx, anim, 0);\n * const png = canvas.encodeSync(\"png\");\n * ```\n */\nexport function renderLottieFrame(\n ctx: SKRSContext2D,\n animation: LottieAnimation,\n frame: number,\n): void {\n animation.seekFrame(frame);\n animation.render(ctx);\n}\n","import type { Canvas, Image, SKRSContext2D } from \"@napi-rs/canvas\";\n\nimport { createCanvas, loadImage } from \"@napi-rs/canvas\";\n\nconst canvasPool = new Map<string, WeakRef<Canvas>[]>();\n\nfunction acquireOffscreen(w: number, h: number): [Canvas, SKRSContext2D] {\n const key = `${w}x${h}`;\n const stack = canvasPool.get(key);\n if (stack) {\n while (stack.length > 0) {\n const ref = stack.pop()!;\n const canvas = ref.deref();\n if (canvas) {\n const ctx = canvas.getContext(\"2d\");\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, w, h);\n return [canvas, ctx];\n }\n }\n }\n const canvas = createCanvas(w, h);\n return [canvas, canvas.getContext(\"2d\")];\n}\n\nfunction releaseOffscreen(canvas: Canvas): void {\n const key = `${canvas.width}x${canvas.height}`;\n let stack = canvasPool.get(key);\n if (!stack) {\n stack = [];\n canvasPool.set(key, stack);\n }\n stack.push(new WeakRef(canvas));\n}\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport type { LayoutNode } from \"../layout.ts\";\nimport { layoutText } from \"../text/index.ts\";\nimport { applyClip, roundedRect } from \"./clip.ts\";\nimport { createGradientFromCSS, splitGradientArgs } from \"./gradient.ts\";\nimport { drawImage } from \"./image.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\nimport { drawRect, getBorderRadiusFromStyle } from \"./rect.ts\";\nimport { drawSvgContainer } from \"./svg.ts\";\nimport { drawText } from \"./text.ts\";\n\n/**\n * Main draw dispatcher: recursively draws the layout tree onto the canvas.\n */\nexport async function drawNode(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n debug: boolean,\n emojiStyle?: EmojiStyle,\n): Promise<void> {\n const x = parentX + node.x;\n const y = parentY + node.y;\n const { width, height, style } = node;\n\n if (style.display === \"none\") return;\n\n const opacity = style.opacity ?? 1;\n if (opacity <= 0) return;\n\n // Detect scale in transform — if present, render to offscreen buffer at 1x\n // then composite scaled. This avoids Skia re-rasterizing glyphs per-frame.\n const scaleInfo = style.transform ? extractScale(style.transform) : null;\n if (scaleInfo && (scaleInfo.sx !== 1 || scaleInfo.sy !== 1)) {\n const sx = scaleInfo.sx;\n const sy = scaleInfo.sy;\n const transformWithoutScale = scaleInfo.remaining;\n\n // Quantize to ceil(|scale|) — buffer resolution only changes at\n // integer boundaries (no jitter), and composite is always ≤1x (sharp).\n const qx = Math.max(1, Math.ceil(Math.abs(sx)));\n const qy = Math.max(1, Math.ceil(Math.abs(sy)));\n\n const bufW = Math.ceil((width + 2) * qx);\n const bufH = Math.ceil((height + 2) * qy);\n if (bufW > 0 && bufH > 0) {\n const [offscreen, offCtx] = acquireOffscreen(bufW, bufH);\n\n // Render at qx×qy resolution — logical coords produce more pixels\n offCtx.save();\n offCtx.scale(qx, qy);\n await drawNodeInner(\n offCtx,\n node,\n parentX,\n parentY,\n 1 - x,\n 1 - y,\n debug,\n emojiStyle,\n transformWithoutScale,\n );\n offCtx.restore();\n\n ctx.save();\n if (opacity < 1) {\n ctx.globalAlpha *= opacity;\n }\n\n let ox = x + width / 2;\n let oy = y + height / 2;\n if (style.transformOrigin) {\n const parts = style.transformOrigin.split(/\\s+/);\n ox = resolveOrigin(parts[0], x, width);\n oy = resolveOrigin(parts[1], y, height);\n }\n\n // Apply the original scale — drawImage maps the high-res buffer\n // back to logical size, so the transform needs the full scale value.\n ctx.translate(ox, oy);\n ctx.scale(sx, sy);\n ctx.translate(-ox, -oy);\n\n // Draw high-res buffer back at logical size (qx→1x downscale happens here)\n ctx.drawImage(\n offscreen,\n 0,\n 0,\n bufW,\n bufH,\n x - 1,\n y - 1,\n width + 2,\n height + 2,\n );\n releaseOffscreen(offscreen);\n ctx.restore();\n return;\n }\n }\n\n ctx.save();\n\n // Apply opacity\n if (opacity < 1) {\n ctx.globalAlpha *= opacity;\n }\n\n // Apply CSS filter\n if (style.filter) {\n ctx.filter = style.filter;\n }\n\n // Apply transform\n if (style.transform) {\n applyTransform(\n ctx,\n style.transform,\n x,\n y,\n width,\n height,\n style.transformOrigin,\n );\n }\n\n // Apply clipping for overflow: hidden\n const isClipped =\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\";\n\n if (isClipped) {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n\n // Draw background and borders\n if (\n style.backgroundColor ||\n style.borderTopWidth ||\n style.borderRightWidth ||\n style.borderBottomWidth ||\n style.borderLeftWidth ||\n style.boxShadow\n ) {\n drawRect(ctx, x, y, width, height, style);\n }\n\n // Draw background-image (gradient or url) — supports multiple comma-separated layers\n if (style.backgroundImage) {\n const layers = splitGradientArgs(style.backgroundImage);\n // CSS paints last layer first (bottommost)\n for (let i = layers.length - 1; i >= 0; i--) {\n const layer = layers[i]!.trim();\n const gradient = createGradientFromCSS(ctx, layer, x, y, width, height);\n if (gradient) {\n ctx.fillStyle = gradient;\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n if (\n borderRadius.topLeft > 0 ||\n borderRadius.topRight > 0 ||\n borderRadius.bottomRight > 0 ||\n borderRadius.bottomLeft > 0\n ) {\n ctx.beginPath();\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n );\n ctx.fill();\n } else {\n ctx.fillRect(x, y, width, height);\n }\n } else {\n // Try url(...) background image\n const urlMatch = layer.match(/url\\([\"']?(.*?)[\"']?\\)/);\n if (urlMatch) {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n const hasRadius =\n borderRadius.topLeft > 0 ||\n borderRadius.topRight > 0 ||\n borderRadius.bottomRight > 0 ||\n borderRadius.bottomLeft > 0;\n\n if (hasRadius) {\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n\n const image = await loadImage(urlMatch[1]!);\n const bgSize = style.backgroundSize;\n\n if (bgSize === \"cover\") {\n // Cover fills the box completely — no tiling needed\n const r = computeCover(\n image.width,\n image.height,\n x,\n y,\n width,\n height,\n );\n ctx.drawImage(\n image,\n r.sx,\n r.sy,\n r.sw,\n r.sh,\n r.dx,\n r.dy,\n r.dw,\n r.dh,\n );\n } else {\n // Compute tile dimensions based on backgroundSize\n let tileW: number, tileH: number;\n if (bgSize === \"contain\") {\n const r = computeContain(\n image.width,\n image.height,\n 0,\n 0,\n width,\n height,\n );\n tileW = r.dw;\n tileH = r.dh;\n } else if (bgSize === \"100% 100%\") {\n tileW = width;\n tileH = height;\n } else {\n // CSS default (auto): natural image size\n tileW = image.width;\n tileH = image.height;\n }\n // Tile the image to fill the box (CSS background-repeat: repeat)\n for (let ty = y; ty < y + height; ty += tileH) {\n for (let tx = x; tx < x + width; tx += tileW) {\n ctx.drawImage(image, tx, ty, tileW, tileH);\n }\n }\n }\n }\n }\n }\n }\n\n // Debug: draw bounding boxes\n if (debug) {\n ctx.strokeStyle = \"rgba(255, 0, 0, 0.5)\";\n ctx.lineWidth = 1;\n ctx.strokeRect(x, y, width, height);\n }\n\n // Draw text content\n if (node.textContent !== undefined && node.textContent !== \"\") {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n\n const borderTopW = resolveBoxValue(style.borderTopWidth, width);\n const borderLeftW = resolveBoxValue(style.borderLeftWidth, width);\n const borderRightW = resolveBoxValue(style.borderRightWidth, width);\n\n const contentX = x + paddingLeft + borderLeftW;\n const contentY = y + paddingTop + borderTopW;\n const contentWidth =\n width - paddingLeft - paddingRight - borderLeftW - borderRightW;\n\n const textLayout = layoutText(\n node.textContent,\n style,\n contentWidth,\n ctx,\n !!emojiStyle,\n );\n await drawText(\n ctx,\n textLayout.segments,\n contentX,\n contentY,\n style.textShadow,\n emojiStyle,\n );\n }\n\n // Draw <img> elements\n if (node.type === \"img\" && node.props.src) {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n const paddingBottom = resolveBoxValue(style.paddingBottom, width);\n\n const imgX = x + paddingLeft;\n const imgY = y + paddingTop;\n const imgW = width - paddingLeft - paddingRight;\n const imgH = height - paddingTop - paddingBottom;\n\n // Images are replaced content — borderRadius clips them directly\n // (unlike child content which requires overflow:hidden)\n if (!isClipped) {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n if (\n borderRadius.topLeft > 0 ||\n borderRadius.topRight > 0 ||\n borderRadius.bottomRight > 0 ||\n borderRadius.bottomLeft > 0\n ) {\n applyClip(ctx, imgX, imgY, imgW, imgH, borderRadius);\n }\n }\n\n await drawImage(\n ctx,\n node.props.src as string | Buffer,\n imgX,\n imgY,\n imgW,\n imgH,\n style,\n node.props.__loadedImage as Image | undefined,\n );\n }\n\n // Draw <svg> containers (handle their own child traversal in SVG coordinate space)\n if (node.type === \"svg\") {\n drawSvgContainer(ctx, node, x, y, width, height);\n } else {\n // Recursively draw children\n for (const child of node.children) {\n await drawNode(ctx, child, x, y, debug, emojiStyle);\n }\n }\n\n ctx.restore();\n}\n\n/**\n * Extract scale(sx, sy) from a transform string, returning the scale values\n * and the remaining transform with scale removed.\n */\nfunction extractScale(\n transform: string,\n): { sx: number; sy: number; remaining: string } | null {\n const scaleMatch = transform.match(/\\b(scale|scaleX|scaleY)\\(([^)]+)\\)/);\n if (!scaleMatch) return null;\n\n const [fullMatch, name, args] = scaleMatch;\n const values = args!.split(\",\").map((s) => s.trim());\n\n const sx = name === \"scaleY\" ? 1 : parseFloat(values[0]!);\n const sy =\n name === \"scaleX\"\n ? 1\n : parseFloat(values[name === \"scale\" ? 1 : 0] ?? String(sx));\n\n const remaining = transform.replace(fullMatch!, \"\").trim();\n return { sx, sy, remaining };\n}\n\n/**\n * Inner draw that renders a node with an optional override transform\n * (used by the offscreen-buffer path to strip scale from the transform).\n * offsetX/offsetY shift all coordinates so the node renders at a buffer-local position.\n */\nasync function drawNodeInner(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n offsetX: number,\n offsetY: number,\n debug: boolean,\n emojiStyle: EmojiStyle | undefined,\n overrideTransform: string | undefined,\n): Promise<void> {\n const x = parentX + node.x + offsetX;\n const y = parentY + node.y + offsetY;\n const { width, height, style } = node;\n\n if (style.display === \"none\") return;\n\n const opacity = style.opacity ?? 1;\n if (opacity <= 0) return;\n\n ctx.save();\n\n if (opacity < 1) {\n ctx.globalAlpha *= opacity;\n }\n\n if (style.filter) {\n ctx.filter = style.filter;\n }\n\n // Apply the override transform (scale stripped) or original\n const transformToApply =\n overrideTransform !== undefined ? overrideTransform : style.transform;\n if (transformToApply) {\n applyTransform(\n ctx,\n transformToApply,\n x,\n y,\n width,\n height,\n style.transformOrigin,\n );\n }\n\n const isClipped =\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\";\n\n if (isClipped) {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n\n if (\n style.backgroundColor ||\n style.borderTopWidth ||\n style.borderRightWidth ||\n style.borderBottomWidth ||\n style.borderLeftWidth ||\n style.boxShadow\n ) {\n drawRect(ctx, x, y, width, height, style);\n }\n\n if (style.backgroundImage) {\n const layers = splitGradientArgs(style.backgroundImage);\n // CSS paints last layer first (bottommost)\n for (let i = layers.length - 1; i >= 0; i--) {\n const layer = layers[i]!.trim();\n const gradient = createGradientFromCSS(ctx, layer, x, y, width, height);\n if (gradient) {\n ctx.fillStyle = gradient;\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n if (\n borderRadius.topLeft > 0 ||\n borderRadius.topRight > 0 ||\n borderRadius.bottomRight > 0 ||\n borderRadius.bottomLeft > 0\n ) {\n ctx.beginPath();\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n );\n ctx.fill();\n } else {\n ctx.fillRect(x, y, width, height);\n }\n } else {\n const urlMatch = layer.match(/url\\([\"']?(.*?)[\"']?\\)/);\n if (urlMatch) {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n const hasRadius =\n borderRadius.topLeft > 0 ||\n borderRadius.topRight > 0 ||\n borderRadius.bottomRight > 0 ||\n borderRadius.bottomLeft > 0;\n if (hasRadius) {\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n const image = await loadImage(urlMatch[1]!);\n const bgSize = style.backgroundSize;\n if (bgSize === \"cover\") {\n const r = computeCover(\n image.width,\n image.height,\n x,\n y,\n width,\n height,\n );\n ctx.drawImage(\n image,\n r.sx,\n r.sy,\n r.sw,\n r.sh,\n r.dx,\n r.dy,\n r.dw,\n r.dh,\n );\n } else {\n let tileW: number, tileH: number;\n if (bgSize === \"contain\") {\n const r = computeContain(\n image.width,\n image.height,\n 0,\n 0,\n width,\n height,\n );\n tileW = r.dw;\n tileH = r.dh;\n } else if (bgSize === \"100% 100%\") {\n tileW = width;\n tileH = height;\n } else {\n tileW = image.width;\n tileH = image.height;\n }\n for (let ty = y; ty < y + height; ty += tileH) {\n for (let tx = x; tx < x + width; tx += tileW) {\n ctx.drawImage(image, tx, ty, tileW, tileH);\n }\n }\n }\n }\n }\n }\n }\n\n if (debug) {\n ctx.strokeStyle = \"rgba(255, 0, 0, 0.5)\";\n ctx.lineWidth = 1;\n ctx.strokeRect(x, y, width, height);\n }\n\n if (node.textContent !== undefined && node.textContent !== \"\") {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n const borderTopW = resolveBoxValue(style.borderTopWidth, width);\n const borderLeftW = resolveBoxValue(style.borderLeftWidth, width);\n const borderRightW = resolveBoxValue(style.borderRightWidth, width);\n const contentX = x + paddingLeft + borderLeftW;\n const contentY = y + paddingTop + borderTopW;\n const contentWidth =\n width - paddingLeft - paddingRight - borderLeftW - borderRightW;\n const textLayout = layoutText(\n node.textContent,\n style,\n contentWidth,\n ctx,\n !!emojiStyle,\n );\n await drawText(\n ctx,\n textLayout.segments,\n contentX,\n contentY,\n style.textShadow,\n emojiStyle,\n );\n }\n\n if (node.type === \"img\" && node.props.src) {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n const paddingBottom = resolveBoxValue(style.paddingBottom, width);\n const imgX = x + paddingLeft;\n const imgY = y + paddingTop;\n const imgW = width - paddingLeft - paddingRight;\n const imgH = height - paddingTop - paddingBottom;\n if (!isClipped) {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n if (\n borderRadius.topLeft > 0 ||\n borderRadius.topRight > 0 ||\n borderRadius.bottomRight > 0 ||\n borderRadius.bottomLeft > 0\n ) {\n applyClip(ctx, imgX, imgY, imgW, imgH, borderRadius);\n }\n }\n await drawImage(\n ctx,\n node.props.src as string | Buffer,\n imgX,\n imgY,\n imgW,\n imgH,\n style,\n node.props.__loadedImage as Image | undefined,\n );\n }\n\n if (node.type === \"svg\") {\n drawSvgContainer(ctx, node, x, y, width, height);\n } else {\n // Children use offset 0 since x,y already incorporates the offset\n for (const child of node.children) {\n await drawNodeInner(ctx, child, x, y, 0, 0, debug, emojiStyle, undefined);\n }\n }\n\n ctx.restore();\n}\n\nexport function parseCSSLength(value: string, referenceSize: number): number {\n if (value.endsWith(\"%\")) return (parseFloat(value) / 100) * referenceSize;\n return parseFloat(value);\n}\n\nfunction applyTransform(\n ctx: SKRSContext2D,\n transform: string,\n x: number,\n y: number,\n width: number,\n height: number,\n transformOrigin?: string,\n): void {\n // Resolve transform-origin (default: center)\n let ox = x + width / 2;\n let oy = y + height / 2;\n\n if (transformOrigin) {\n const parts = transformOrigin.split(/\\s+/);\n ox = resolveOrigin(parts[0], x, width);\n oy = resolveOrigin(parts[1], y, height);\n }\n\n ctx.translate(ox, oy);\n\n // Parse and apply transform functions\n const funcs = transform.matchAll(/(\\w+)\\(([^)]+)\\)/g);\n\n for (const [, name, args] of funcs) {\n const values = args!.split(\",\").map((s) => s.trim());\n\n switch (name) {\n case \"translate\":\n case \"translateX\":\n case \"translateY\": {\n const tx =\n name === \"translateY\" ? 0 : parseCSSLength(values[0]!, width);\n const ty =\n name === \"translateX\"\n ? 0\n : parseCSSLength(\n values[name === \"translate\" ? 1 : 0] ?? \"0\",\n height,\n );\n ctx.translate(tx, ty);\n break;\n }\n case \"scale\":\n case \"scaleX\":\n case \"scaleY\": {\n const sx = name === \"scaleY\" ? 1 : parseFloat(values[0]!);\n const sy =\n name === \"scaleX\"\n ? 1\n : parseFloat(values[name === \"scale\" ? 1 : 0] ?? String(sx));\n ctx.scale(sx, sy);\n break;\n }\n case \"rotate\": {\n const angle = parseAngle(values[0]!);\n ctx.rotate(angle);\n break;\n }\n case \"skewX\": {\n const angle = parseAngle(values[0]!);\n ctx.transform(1, 0, Math.tan(angle), 1, 0, 0);\n break;\n }\n case \"skewY\": {\n const angle = parseAngle(values[0]!);\n ctx.transform(1, Math.tan(angle), 0, 1, 0, 0);\n break;\n }\n }\n }\n\n ctx.translate(-ox, -oy);\n}\n\nfunction resolveOrigin(\n value: string | undefined,\n base: number,\n size: number,\n): number {\n if (!value) return base + size / 2;\n if (value === \"left\" || value === \"top\") return base;\n if (value === \"right\" || value === \"bottom\") return base + size;\n if (value === \"center\") return base + size / 2;\n return base + parseCSSLength(value, size);\n}\n\nfunction parseAngle(value: string): number {\n if (value.endsWith(\"deg\")) return (parseFloat(value) * Math.PI) / 180;\n if (value.endsWith(\"rad\")) return parseFloat(value);\n if (value.endsWith(\"turn\")) return parseFloat(value) * 2 * Math.PI;\n return parseFloat(value);\n}\n\nexport function toNumber(v: unknown): number {\n if (typeof v === \"number\") return v;\n if (v === undefined || v === null) return 0;\n const n = parseFloat(String(v));\n return isNaN(n) ? 0 : n;\n}\n\n/**\n * Resolve a box-model value (padding, border-width) that may be a percentage.\n * Per CSS spec, percentage padding/border resolves against the element's width\n * (even for top/bottom).\n */\nexport function resolveBoxValue(v: unknown, referenceWidth: number): number {\n if (typeof v === \"number\") return v;\n if (v === undefined || v === null) return 0;\n const s = String(v);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * referenceWidth;\n const n = parseFloat(s);\n return isNaN(n) ? 0 : n;\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\n/**\n * Detect the primary script/language of a text string.\n * Used for font selection and line-breaking behavior.\n */\nexport function detectLanguageCode(text: string): string | undefined {\n for (const char of text) {\n const cp = char.codePointAt(0);\n if (cp === undefined) continue;\n\n // CJK Unified Ideographs\n if (cp >= 0x4e00 && cp <= 0x9fff) return \"zh\";\n // CJK Extension A\n if (cp >= 0x3400 && cp <= 0x4dbf) return \"zh\";\n // Hiragana\n if (cp >= 0x3040 && cp <= 0x309f) return \"ja\";\n // Katakana\n if (cp >= 0x30a0 && cp <= 0x30ff) return \"ja\";\n // Hangul Syllables\n if (cp >= 0xac00 && cp <= 0xd7af) return \"ko\";\n // Hangul Jamo\n if (cp >= 0x1100 && cp <= 0x11ff) return \"ko\";\n // Thai\n if (cp >= 0x0e00 && cp <= 0x0e7f) return \"th\";\n // Arabic\n if (cp >= 0x0600 && cp <= 0x06ff) return \"ar\";\n // Hebrew\n if (cp >= 0x0590 && cp <= 0x05ff) return \"he\";\n // Devanagari\n if (cp >= 0x0900 && cp <= 0x097f) return \"hi\";\n // Bengali\n if (cp >= 0x0980 && cp <= 0x09ff) return \"bn\";\n // Tamil\n if (cp >= 0x0b80 && cp <= 0x0bff) return \"ta\";\n // Telugu\n if (cp >= 0x0c00 && cp <= 0x0c7f) return \"te\";\n // Kannada\n if (cp >= 0x0c80 && cp <= 0x0cff) return \"kn\";\n // Malayalam\n if (cp >= 0x0d00 && cp <= 0x0d7f) return \"ml\";\n }\n\n return undefined;\n}\n\n/**\n * Check if a character is an emoji.\n */\nexport function isEmoji(char: string): boolean {\n const cp = char.codePointAt(0);\n if (cp === undefined) return false;\n\n // Common emoji ranges\n if (cp >= 0x1f600 && cp <= 0x1f64f) return true; // Emoticons\n if (cp >= 0x1f300 && cp <= 0x1f5ff) return true; // Misc Symbols & Pictographs\n if (cp >= 0x1f680 && cp <= 0x1f6ff) return true; // Transport & Map\n if (cp >= 0x1f900 && cp <= 0x1f9ff) return true; // Supplemental Symbols\n if (cp >= 0x2600 && cp <= 0x26ff) return true; // Misc Symbols\n if (cp >= 0x2700 && cp <= 0x27bf) return true; // Dingbats\n if (cp >= 0x2b50 && cp <= 0x2b55) return true; // Misc Symbols & Arrows (star, circle)\n if (cp >= 0x200d && cp <= 0x200d) return true; // Zero Width Joiner\n if (cp >= 0xfe00 && cp <= 0xfe0f) return true; // Variation Selectors\n if (cp >= 0x1fa00 && cp <= 0x1fa6f) return true; // Chess Symbols\n if (cp >= 0x1fa70 && cp <= 0x1faff) return true; // Symbols Extended-A\n if (cp >= 0x231a && cp <= 0x23f3) return true; // Misc Technical (watch, hourglass)\n if (cp >= 0x23e9 && cp <= 0x23fa) return true; // Misc Technical (play, pause)\n if (cp >= 0x25aa && cp <= 0x25fe) return true; // Geometric Shapes\n if (cp >= 0x2934 && cp <= 0x2935) return true; // Arrows\n if (cp >= 0x2b05 && cp <= 0x2b07) return true; // Arrows\n if (cp >= 0x3030 && cp <= 0x3030) return true; // Wavy dash\n if (cp >= 0x303d && cp <= 0x303d) return true; // Part alternation mark\n if (cp >= 0x3297 && cp <= 0x3299) return true; // CJK symbols\n\n return false;\n}\n","import LineBreaker from \"linebreak\";\n\nexport type BreakOpportunity = {\n position: number;\n required: boolean;\n};\n\n/**\n * Find line-break opportunities in text using UAX #14 algorithm.\n *\n * @param text - The text to analyze\n * @returns Array of break opportunities with positions and whether they're required (hard breaks)\n */\nexport function findBreakOpportunities(text: string): BreakOpportunity[] {\n const breaker = new LineBreaker(text);\n const opportunities: BreakOpportunity[] = [];\n\n let bk = breaker.nextBreak();\n while (bk) {\n opportunities.push({\n position: bk.position,\n required: bk.required ?? false,\n });\n bk = breaker.nextBreak();\n }\n\n return opportunities;\n}\n","import { createCanvas } from \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\n\nexport type TextMetrics = {\n width: number;\n ascent: number;\n descent: number;\n height: number;\n};\n\n// Scratch canvas for text measurement when no ctx is available\nlet scratchCtx: SKRSContext2D | null = null;\n\nfunction getScratchCtx(): SKRSContext2D {\n if (!scratchCtx) {\n scratchCtx = createCanvas(1, 1).getContext(\"2d\");\n }\n return scratchCtx;\n}\n\nconst GENERIC_FAMILIES = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"math\",\n \"emoji\",\n \"fangsong\",\n]);\n\nfunction quoteFontFamily(family: string): string {\n if (!family || GENERIC_FAMILIES.has(family)) return family;\n return `\"${family}\"`;\n}\n\n/**\n * Set font properties on a canvas context for measurement.\n */\nexport function setFont(\n ctx: SKRSContext2D,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n): void {\n const quoted = fontFamily\n .split(\",\")\n .map((f) => quoteFontFamily(f.trim()))\n .join(\", \");\n ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${quoted}`;\n}\n\n/**\n * Measure text using the canvas ctx.measureText() API.\n * Returns width, ascent, descent, and total height.\n */\nexport function measureText(\n text: string,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n ctx?: SKRSContext2D,\n): TextMetrics {\n const c = ctx ?? getScratchCtx();\n setFont(c, fontSize, fontFamily, fontWeight, fontStyle);\n\n const m = c.measureText(text);\n\n const ascent =\n m.fontBoundingBoxAscent ?? m.actualBoundingBoxAscent ?? fontSize * 0.8;\n const descent =\n m.fontBoundingBoxDescent ?? m.actualBoundingBoxDescent ?? fontSize * 0.2;\n\n return {\n width: m.width,\n ascent,\n descent,\n height: ascent + descent,\n };\n}\n\n/**\n * Measure how many pixels to trim from the top (overTrim) and bottom\n * (underTrim) of a line box based on `text-box-edge` keywords.\n *\n * The trim amount is the difference between the full line-height half-leading\n * and the target metric for each edge.\n */\nexport function measureTrimMetrics(\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n lineHeight: number,\n edge: string,\n ctx?: SKRSContext2D,\n): { overTrim: number; underTrim: number } {\n const c = ctx ?? getScratchCtx();\n setFont(c, fontSize, fontFamily, fontWeight, fontStyle);\n\n const refMetrics = c.measureText(\"M\");\n const fontAscent =\n refMetrics.fontBoundingBoxAscent ??\n refMetrics.actualBoundingBoxAscent ??\n fontSize * 0.8;\n const fontDescent =\n refMetrics.fontBoundingBoxDescent ??\n refMetrics.actualBoundingBoxDescent ??\n fontSize * 0.2;\n\n // Parse edge into over-edge and under-edge keywords\n const parts = edge.trim().split(/\\s+/);\n const overEdge = parts[0] ?? \"text\";\n const underEdge = parts.length > 1 ? parts[1]! : overEdge;\n\n // Resolve over-edge keyword → target ascent\n let targetAscent: number;\n switch (overEdge) {\n case \"cap\": {\n const capMetrics = c.measureText(\"H\");\n targetAscent = capMetrics.actualBoundingBoxAscent ?? fontSize * 0.7;\n break;\n }\n case \"ex\": {\n const exMetrics = c.measureText(\"x\");\n targetAscent = exMetrics.actualBoundingBoxAscent ?? fontSize * 0.5;\n break;\n }\n case \"ideographic\":\n case \"ideographic-ink\":\n case \"text\":\n default:\n targetAscent = fontAscent;\n break;\n }\n\n // Resolve under-edge keyword → target descent\n let targetDescent: number;\n switch (underEdge) {\n case \"alphabetic\":\n targetDescent = 0;\n break;\n case \"ideographic\":\n case \"ideographic-ink\":\n case \"text\":\n default:\n targetDescent = fontDescent;\n break;\n }\n\n const halfLeading = (lineHeight - (fontAscent + fontDescent)) / 2;\n const overTrim = halfLeading + (fontAscent - targetAscent);\n const underTrim = halfLeading + (fontDescent - targetDescent);\n\n return {\n overTrim: Math.max(0, overTrim),\n underTrim: Math.max(0, underTrim),\n };\n}\n\n/**\n * Measure the width of a single word.\n */\nexport function measureWord(\n word: string,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n): number {\n const base = measureText(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n ).width;\n if (letterSpacing === 0 || word.length === 0) return base;\n return base + letterSpacing * word.length;\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { isEmoji } from \"../language.ts\";\nimport { findBreakOpportunities } from \"./linebreak.ts\";\nimport { measureText, measureTrimMetrics, measureWord } from \"./measure.ts\";\nimport type { TextMetrics } from \"./measure.ts\";\n\nexport type TextSegment = {\n text: string;\n x: number;\n y: number;\n width: number;\n height: number;\n fontSize: number;\n fontFamily: string;\n fontWeight: number | string;\n fontStyle: string;\n color: string;\n ascent: number;\n textDecoration?: string;\n letterSpacing: number;\n lineIndex: number;\n};\n\nexport type TextLayoutResult = {\n segments: TextSegment[];\n width: number;\n height: number;\n};\n\n/**\n * Measure the width of a word, accounting for emoji characters when enabled.\n * Emoji characters are treated as square images sized to fontSize.\n */\nfunction emojiAwareMeasureWord(\n word: string,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n): number {\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n let totalWidth = 0;\n let textBuffer = \"\";\n\n for (const { segment } of segmenter.segment(word)) {\n let isEmojiSegment = false;\n for (const char of segment) {\n if (isEmoji(char)) {\n isEmojiSegment = true;\n break;\n }\n }\n\n if (isEmojiSegment) {\n if (textBuffer) {\n totalWidth += measureWord(\n textBuffer,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n textBuffer = \"\";\n }\n totalWidth += fontSize;\n } else {\n textBuffer += segment;\n }\n }\n\n if (textBuffer) {\n totalWidth += measureWord(\n textBuffer,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n }\n\n return totalWidth;\n}\n\n/**\n * Lay out text content into positioned segments with line-breaking.\n *\n * @param text - The text to lay out\n * @param style - Computed style\n * @param maxWidth - Maximum width for wrapping\n * @param ctx - Canvas context for measurement\n * @param emojiEnabled - Whether to use emoji-aware measurement\n * @returns Text segments with positions and total dimensions\n */\nexport function layoutText(\n text: string,\n style: ComputedStyle,\n maxWidth: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n): TextLayoutResult {\n const fontSize = style.fontSize ?? 16;\n const fontFamily = style.fontFamily ?? \"sans-serif\";\n const fontWeight = style.fontWeight ?? 400;\n const fontStyle = style.fontStyle ?? \"normal\";\n const color = style.color ?? \"black\";\n const textAlign = style.textAlign ?? \"left\";\n // Measure reference metrics for \"normal\" lineHeight (font ascent + descent)\n const refMetrics = measureText(\n \"M\",\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n );\n const lineHeightPx = resolveLineHeight(\n style.lineHeight,\n fontSize,\n refMetrics,\n );\n const letterSpacing =\n typeof style.letterSpacing === \"number\" ? style.letterSpacing : 0;\n const whiteSpace = style.whiteSpace ?? \"normal\";\n const wordBreak = style.wordBreak ?? \"normal\";\n const textOverflow = style.textOverflow ?? \"clip\";\n const textDecoration = style.textDecoration;\n\n // Choose measurement function based on emoji mode\n const measure = emojiEnabled\n ? (word: string, ls?: number) =>\n emojiAwareMeasureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n ls ?? letterSpacing,\n )\n : (word: string, ls?: number) =>\n measureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n ls ?? letterSpacing,\n );\n\n // Apply text transform\n let processedText = text;\n if (style.textTransform === \"uppercase\") {\n processedText = text.toUpperCase();\n } else if (style.textTransform === \"lowercase\") {\n processedText = text.toLowerCase();\n } else if (style.textTransform === \"capitalize\") {\n processedText = text.replace(/\\b\\w/g, (c) => c.toUpperCase());\n }\n\n const noWrap = whiteSpace === \"nowrap\" || whiteSpace === \"pre\";\n const preserveWhitespace = whiteSpace === \"pre\" || whiteSpace === \"pre-wrap\";\n\n // Split by explicit newlines\n const paragraphs = preserveWhitespace\n ? processedText.split(\"\\n\")\n : processedText.split(\"\\n\");\n\n const lines: string[] = [];\n\n for (const paragraph of paragraphs) {\n if (noWrap) {\n lines.push(paragraph);\n continue;\n }\n\n // Wrap text\n const wrapped = wrapText(\n paragraph,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n letterSpacing,\n wordBreak,\n ctx,\n measure,\n );\n lines.push(...wrapped);\n }\n\n // Handle text-overflow: ellipsis\n if (textOverflow === \"ellipsis\" && noWrap && lines.length === 1) {\n const line = lines[0]!;\n const lineWidth = measure(line);\n if (lineWidth > maxWidth) {\n lines[0] = truncateWithEllipsis(\n line,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n }\n }\n\n // Create positioned segments\n const segments: TextSegment[] = [];\n let totalHeight = 0;\n let maxLineWidth = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const lineWidth = measure(line);\n\n let x = 0;\n if (textAlign === \"center\") {\n x = (maxWidth - lineWidth) / 2;\n } else if (textAlign === \"right\") {\n x = maxWidth - lineWidth;\n }\n\n const metrics = measureText(\n line || \"M\",\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n );\n\n segments.push({\n text: line,\n x,\n y: totalHeight + (lineHeightPx + metrics.ascent - metrics.descent) / 2,\n width: lineWidth,\n height: lineHeightPx,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n color,\n ascent: metrics.ascent,\n textDecoration,\n letterSpacing,\n lineIndex: i,\n });\n\n totalHeight += lineHeightPx;\n maxLineWidth = Math.max(maxLineWidth, lineWidth);\n }\n\n // Apply text-box-trim\n const textBoxTrim = style.textBoxTrim;\n if (textBoxTrim && textBoxTrim !== \"none\" && segments.length > 0) {\n const textBoxEdge = style.textBoxEdge ?? \"text\";\n const trimMetrics = measureTrimMetrics(\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n lineHeightPx,\n textBoxEdge,\n ctx,\n );\n\n if (textBoxTrim === \"trim-start\" || textBoxTrim === \"trim-both\") {\n for (const seg of segments) {\n seg.y -= trimMetrics.overTrim;\n }\n totalHeight -= trimMetrics.overTrim;\n }\n\n if (textBoxTrim === \"trim-end\" || textBoxTrim === \"trim-both\") {\n totalHeight -= trimMetrics.underTrim;\n }\n }\n\n return {\n segments,\n width: maxLineWidth,\n height: totalHeight,\n };\n}\n\nfunction resolveLineHeight(\n lineHeight: number | string | undefined,\n fontSize: number,\n metrics?: TextMetrics,\n): number {\n if (lineHeight === undefined || lineHeight === \"normal\") {\n // CSS \"normal\": use font ascent + descent (matches satori behaviour)\n return metrics ? metrics.ascent + metrics.descent : fontSize * 1.2;\n }\n if (typeof lineHeight === \"number\") {\n // Already resolved to px in compute.ts if > 5, else multiplier\n return lineHeight > 5 ? lineHeight : lineHeight * fontSize;\n }\n const parsed = parseFloat(String(lineHeight));\n return isNaN(parsed) ? fontSize * 1.2 : parsed;\n}\n\nfunction wrapText(\n text: string,\n maxWidth: number,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n letterSpacing: number,\n wordBreak: string,\n ctx?: SKRSContext2D,\n measureFn?: (word: string, ls?: number) => number,\n): string[] {\n if (!text) return [\"\"];\n\n const mw =\n measureFn ??\n ((word: string) =>\n measureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n ));\n\n const breakOpps = findBreakOpportunities(text);\n const lines: string[] = [];\n let lineStart = 0;\n let lastBreak = 0;\n\n for (const opp of breakOpps) {\n const segment = text.slice(lineStart, opp.position);\n const segWidth = mw(segment);\n\n if (segWidth > maxWidth && lastBreak > lineStart) {\n // Line overflows — break at last opportunity\n const line = text.slice(lineStart, lastBreak).replace(/\\s+$/, \"\");\n lines.push(line);\n lineStart = lastBreak;\n } else if (segWidth > maxWidth && wordBreak === \"break-all\") {\n // Force break within word\n const broken = forceBreakWord(\n text,\n lineStart,\n opp.position,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n measureFn,\n );\n lines.push(...broken.lines);\n lineStart = broken.endPos;\n }\n\n if (opp.required) {\n // Hard break (newline)\n const line = text.slice(lineStart, opp.position).replace(/\\s+$/, \"\");\n lines.push(line);\n lineStart = opp.position;\n }\n\n lastBreak = opp.position;\n }\n\n // Remaining text\n if (lineStart < text.length) {\n const remaining = text.slice(lineStart).replace(/\\s+$/, \"\");\n if (remaining) {\n const remWidth = mw(remaining);\n if (remWidth > maxWidth && wordBreak === \"break-all\") {\n const broken = forceBreakWord(\n text,\n lineStart,\n text.length,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n measureFn,\n );\n lines.push(...broken.lines);\n } else {\n lines.push(remaining);\n }\n }\n }\n\n return lines.length > 0 ? lines : [\"\"];\n}\n\nfunction forceBreakWord(\n text: string,\n start: number,\n end: number,\n maxWidth: number,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n measureFn?: (word: string, ls?: number) => number,\n): { lines: string[]; endPos: number } {\n const mw =\n measureFn ??\n ((word: string) =>\n measureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n ));\n const lines: string[] = [];\n let pos = start;\n\n while (pos < end) {\n let breakPos = pos + 1;\n while (breakPos < end) {\n const chunk = text.slice(pos, breakPos + 1);\n const w = mw(chunk);\n if (w > maxWidth) break;\n breakPos++;\n }\n\n const line = text.slice(pos, breakPos);\n if (line.trim()) lines.push(line);\n pos = breakPos;\n }\n\n return { lines, endPos: end };\n}\n\nfunction truncateWithEllipsis(\n text: string,\n maxWidth: number,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n): string {\n const ellipsis = \"\\u2026\";\n const ellipsisWidth = measureWord(\n ellipsis,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n const availWidth = maxWidth - ellipsisWidth;\n\n for (let i = text.length - 1; i > 0; i--) {\n const truncated = text.slice(0, i);\n const w = measureWord(\n truncated,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n if (w <= availWidth) {\n return truncated + ellipsis;\n }\n }\n\n return ellipsis;\n}\n\n/**\n * Yoga-compatible measure function for text nodes.\n * Returns the dimensions needed for the text content.\n */\nexport function createTextMeasureFunc(\n text: string,\n style: ComputedStyle,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n) {\n // Strip textOverflow during measurement so ellipsis truncation doesn't\n // shrink the reported width below the Yoga constraint. The draw phase\n // still uses the original style (with textOverflow) for rendering.\n const measureStyle = { ...style, textOverflow: \"clip\" as const };\n return (\n width: number,\n _widthMode: number,\n _height: number,\n _heightMode: number,\n ) => {\n const maxWidth = width > 0 ? width : Infinity;\n const result = layoutText(text, measureStyle, maxWidth, ctx, emojiEnabled);\n // When text wraps to multiple lines, return the constraint width (like CSS\n // block layout). This ensures the draw phase re-layout gets the same\n // maxWidth and produces identical line-breaking. Without this, the\n // measured content width (widest trimmed line) can be narrower than what\n // the wrapping algorithm needs (it checks untrimmed segments), causing the\n // draw phase to wrap differently.\n const wrapped = result.segments.length > 1;\n const reportedWidth = wrapped\n ? Math.min(maxWidth, width > 0 ? width : result.width)\n : result.width;\n return { width: Math.min(reportedWidth, maxWidth), height: result.height };\n };\n}\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\n\n/**\n * Apply overflow:hidden clipping to a canvas context.\n * Creates a rectangular clip path with optional border-radius.\n */\nexport function applyClip(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n borderRadius?: {\n topLeft: number;\n topRight: number;\n bottomRight: number;\n bottomLeft: number;\n },\n): void {\n ctx.beginPath();\n\n if (borderRadius && hasRadius(borderRadius)) {\n const { topLeft, topRight, bottomRight, bottomLeft } = borderRadius;\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n topLeft,\n topRight,\n bottomRight,\n bottomLeft,\n );\n } else {\n ctx.rect(x, y, width, height);\n }\n\n ctx.clip();\n}\n\n/**\n * Draw a rounded rectangle path on the context.\n */\nexport function roundedRect(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n tl: number,\n tr: number,\n br: number,\n bl: number,\n): void {\n // Clamp radii to half the smallest dimension\n const maxR = Math.min(w, h) / 2;\n tl = Math.min(tl, maxR);\n tr = Math.min(tr, maxR);\n br = Math.min(br, maxR);\n bl = Math.min(bl, maxR);\n\n ctx.moveTo(x + tl, y);\n ctx.lineTo(x + w - tr, y);\n if (tr > 0) ctx.arcTo(x + w, y, x + w, y + tr, tr);\n ctx.lineTo(x + w, y + h - br);\n if (br > 0) ctx.arcTo(x + w, y + h, x + w - br, y + h, br);\n ctx.lineTo(x + bl, y + h);\n if (bl > 0) ctx.arcTo(x, y + h, x, y + h - bl, bl);\n ctx.lineTo(x, y + tl);\n if (tl > 0) ctx.arcTo(x, y, x + tl, y, tl);\n ctx.closePath();\n}\n\nfunction hasRadius(r: {\n topLeft: number;\n topRight: number;\n bottomRight: number;\n bottomLeft: number;\n}): boolean {\n return (\n r.topLeft > 0 || r.topRight > 0 || r.bottomRight > 0 || r.bottomLeft > 0\n );\n}\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\n\n/**\n * Parse and create a canvas gradient from a CSS gradient string.\n * Supports linear-gradient and radial-gradient.\n *\n * @returns A CanvasGradient or null if parsing fails\n */\nexport function createGradientFromCSS(\n ctx: SKRSContext2D,\n cssGradient: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n const trimmed = cssGradient.trim();\n\n if (trimmed.startsWith(\"linear-gradient\")) {\n return parseLinearGradient(ctx, trimmed, x, y, width, height);\n }\n\n if (trimmed.startsWith(\"radial-gradient\")) {\n return parseRadialGradient(ctx, trimmed, x, y, width, height);\n }\n\n return null;\n}\n\nfunction parseLinearGradient(\n ctx: SKRSContext2D,\n css: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n // Extract content between parentheses\n const match = css.match(/linear-gradient\\((.*)\\)/s);\n if (!match) return null;\n\n const content = match[1]!.trim();\n const parts = splitGradientArgs(content);\n\n let angle = 180; // default: to bottom\n let colorStartIdx = 0;\n\n // Parse direction\n const first = parts[0]?.trim();\n if (first) {\n if (first.startsWith(\"to \")) {\n angle = directionToAngle(first);\n colorStartIdx = 1;\n } else if (first.endsWith(\"deg\")) {\n angle = parseFloat(first);\n colorStartIdx = 1;\n } else if (first.endsWith(\"turn\")) {\n angle = parseFloat(first) * 360;\n colorStartIdx = 1;\n }\n }\n\n // Calculate gradient line endpoints\n const rad = ((angle - 90) * Math.PI) / 180;\n const cx = x + width / 2;\n const cy = y + height / 2;\n const halfDiag =\n Math.abs(width * Math.cos(rad)) / 2 + Math.abs(height * Math.sin(rad)) / 2;\n\n const x0 = cx - halfDiag * Math.cos(rad);\n const y0 = cy - halfDiag * Math.sin(rad);\n const x1 = cx + halfDiag * Math.cos(rad);\n const y1 = cy + halfDiag * Math.sin(rad);\n\n const gradient = ctx.createLinearGradient(x0, y0, x1, y1);\n\n // Parse color stops\n const stops = parts.slice(colorStartIdx);\n addColorStops(gradient, stops);\n\n return gradient;\n}\n\nfunction parseRadialGradient(\n ctx: SKRSContext2D,\n css: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n const match = css.match(/radial-gradient\\((.*)\\)/s);\n if (!match) return null;\n\n const content = match[1]!.trim();\n const parts = splitGradientArgs(content);\n\n const cx = x + width / 2;\n const cy = y + height / 2;\n const radius = Math.max(width, height) / 2;\n\n const gradient = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius);\n\n // Simple parsing: skip shape/size/position, just get color stops\n let colorStartIdx = 0;\n const first = parts[0]?.trim() ?? \"\";\n if (\n first.startsWith(\"circle\") ||\n first.startsWith(\"ellipse\") ||\n first.startsWith(\"closest\") ||\n first.startsWith(\"farthest\")\n ) {\n colorStartIdx = 1;\n }\n\n addColorStops(gradient, parts.slice(colorStartIdx));\n\n return gradient;\n}\n\nfunction addColorStops(gradient: CanvasGradient, stops: string[]): void {\n if (stops.length === 0) return;\n\n for (let i = 0; i < stops.length; i++) {\n const stop = stops[i]!.trim();\n const percentMatch = stop.match(/^(.+?)\\s+(\\d+(?:\\.\\d+)?%?)$/);\n\n if (percentMatch) {\n const color = percentMatch[1]!;\n const pos = percentMatch[2]!;\n const offset = pos.endsWith(\"%\")\n ? parseFloat(pos) / 100\n : parseFloat(pos);\n gradient.addColorStop(Math.max(0, Math.min(1, offset)), color);\n } else {\n // Auto-distribute\n const offset = stops.length === 1 ? 0.5 : i / (stops.length - 1);\n gradient.addColorStop(offset, stop);\n }\n }\n}\n\nfunction directionToAngle(dir: string): number {\n const map: Record<string, number> = {\n \"to top\": 0,\n \"to right\": 90,\n \"to bottom\": 180,\n \"to left\": 270,\n \"to top right\": 45,\n \"to top left\": 315,\n \"to bottom right\": 135,\n \"to bottom left\": 225,\n };\n return map[dir] ?? 180;\n}\n\nexport function splitGradientArgs(content: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let parenDepth = 0;\n\n for (const char of content) {\n if (char === \"(\") parenDepth++;\n if (char === \")\") parenDepth--;\n if (char === \",\" && parenDepth === 0) {\n parts.push(current);\n current = \"\";\n } else {\n current += char;\n }\n }\n if (current.trim()) parts.push(current);\n\n return parts;\n}\n","import { loadImage } from \"@napi-rs/canvas\";\nimport type { Image, SKRSContext2D } from \"@napi-rs/canvas\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\n\n/**\n * Draw an image element onto the canvas.\n *\n * @param ctx - Canvas rendering context\n * @param src - Image source (URL, file path, or Buffer)\n * @param x - X position\n * @param y - Y position\n * @param width - Target width\n * @param height - Target height\n * @param style - Computed style (for objectFit)\n */\nexport async function drawImage(\n ctx: SKRSContext2D,\n src: string | Buffer,\n x: number,\n y: number,\n width: number,\n height: number,\n style?: ComputedStyle,\n preloadedImage?: Image,\n): Promise<void> {\n const image = preloadedImage ?? (await loadImage(src));\n const objectFit = style?.objectFit ?? \"fill\";\n\n if (objectFit === \"fill\") {\n ctx.drawImage(image, x, y, width, height);\n return;\n }\n\n const imgW = image.width;\n const imgH = image.height;\n\n if (objectFit === \"contain\") {\n const r = computeContain(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.dx, r.dy, r.dw, r.dh);\n } else if (objectFit === \"cover\") {\n const r = computeCover(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.sx, r.sy, r.sw, r.sh, r.dx, r.dy, r.dw, r.dh);\n } else if (objectFit === \"none\") {\n const dx = x + (width - imgW) / 2;\n const dy = y + (height - imgH) / 2;\n ctx.drawImage(image, dx, dy);\n } else if (objectFit === \"scale-down\") {\n if (imgW <= width && imgH <= height) {\n const dx = x + (width - imgW) / 2;\n const dy = y + (height - imgH) / 2;\n ctx.drawImage(image, dx, dy);\n } else {\n const r = computeContain(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.dx, r.dy, r.dw, r.dh);\n }\n }\n}\n","/**\n * Shared cover/contain sizing logic used by both `<img>` objectFit\n * and `backgroundImage` + `backgroundSize`.\n */\n\nexport interface FitRect {\n sx: number;\n sy: number;\n sw: number;\n sh: number;\n dx: number;\n dy: number;\n dw: number;\n dh: number;\n}\n\n/**\n * Compute source and destination rectangles for \"cover\" sizing.\n * The image fills the box completely, cropping the excess.\n */\nexport function computeCover(\n imgW: number,\n imgH: number,\n boxX: number,\n boxY: number,\n boxW: number,\n boxH: number,\n): FitRect {\n const imgRatio = imgW / imgH;\n const boxRatio = boxW / boxH;\n\n let sx: number, sy: number, sw: number, sh: number;\n\n if (imgRatio > boxRatio) {\n sh = imgH;\n sw = imgH * boxRatio;\n sx = (imgW - sw) / 2;\n sy = 0;\n } else {\n sw = imgW;\n sh = imgW / boxRatio;\n sx = 0;\n sy = (imgH - sh) / 2;\n }\n\n return { sx, sy, sw, sh, dx: boxX, dy: boxY, dw: boxW, dh: boxH };\n}\n\n/**\n * Compute destination rectangle for \"contain\" sizing.\n * The image fits entirely within the box, centered, with no cropping.\n */\nexport function computeContain(\n imgW: number,\n imgH: number,\n boxX: number,\n boxY: number,\n boxW: number,\n boxH: number,\n): FitRect {\n const imgRatio = imgW / imgH;\n const boxRatio = boxW / boxH;\n\n let dw: number, dh: number;\n\n if (imgRatio > boxRatio) {\n dw = boxW;\n dh = boxW / imgRatio;\n } else {\n dh = boxH;\n dw = boxH * imgRatio;\n }\n\n const dx = boxX + (boxW - dw) / 2;\n const dy = boxY + (boxH - dh) / 2;\n\n return { sx: 0, sy: 0, sw: imgW, sh: imgH, dx, dy, dw, dh };\n}\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { roundedRect } from \"./clip.ts\";\nimport { parseCSSLength, toNumber, resolveBoxValue } from \"./index.ts\";\n\n/**\n * Draw the background, borders, and box-shadow for a rectangular element.\n */\nexport function drawRect(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n style: ComputedStyle,\n): void {\n const borderRadius = getBorderRadius(style, width, height);\n const hasRoundedCorners =\n borderRadius.topLeft > 0 ||\n borderRadius.topRight > 0 ||\n borderRadius.bottomRight > 0 ||\n borderRadius.bottomLeft > 0;\n\n // Box shadow (drawn before background)\n if (style.boxShadow) {\n drawBoxShadow(ctx, x, y, width, height, style.boxShadow, borderRadius);\n }\n\n // Background\n if (style.backgroundColor) {\n ctx.fillStyle = style.backgroundColor;\n\n if (hasRoundedCorners) {\n ctx.beginPath();\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n );\n ctx.fill();\n } else {\n ctx.fillRect(x, y, width, height);\n }\n }\n\n // Borders\n drawBorders(ctx, x, y, width, height, style, borderRadius);\n}\n\nfunction resolveRadius(v: unknown, width: number, height: number): number {\n if (typeof v === \"string\") return parseCSSLength(v, Math.min(width, height));\n return toNumber(v);\n}\n\nfunction getBorderRadius(style: ComputedStyle, width: number, height: number) {\n return {\n topLeft: resolveRadius(style.borderTopLeftRadius, width, height),\n topRight: resolveRadius(style.borderTopRightRadius, width, height),\n bottomRight: resolveRadius(style.borderBottomRightRadius, width, height),\n bottomLeft: resolveRadius(style.borderBottomLeftRadius, width, height),\n };\n}\n\nexport function getBorderRadiusFromStyle(\n style: ComputedStyle,\n width: number,\n height: number,\n) {\n return getBorderRadius(style, width, height);\n}\n\nfunction drawBorders(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n style: ComputedStyle,\n borderRadius: ReturnType<typeof getBorderRadius>,\n): void {\n const hasRoundedCorners =\n borderRadius.topLeft > 0 ||\n borderRadius.topRight > 0 ||\n borderRadius.bottomRight > 0 ||\n borderRadius.bottomLeft > 0;\n\n // If all borders are the same, draw as a single stroke\n const tw = resolveBoxValue(style.borderTopWidth, width);\n const rw = resolveBoxValue(style.borderRightWidth, width);\n const bw = resolveBoxValue(style.borderBottomWidth, width);\n const lw = resolveBoxValue(style.borderLeftWidth, width);\n\n if (tw === 0 && rw === 0 && bw === 0 && lw === 0) return;\n\n const allSameWidth = tw === rw && rw === bw && bw === lw && tw > 0;\n const tc = style.borderTopColor ?? \"black\";\n const rc = style.borderRightColor ?? \"black\";\n const bc = style.borderBottomColor ?? \"black\";\n const lc = style.borderLeftColor ?? \"black\";\n const allSameColor = tc === rc && rc === bc && bc === lc;\n\n if (allSameWidth && allSameColor) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n\n if (hasRoundedCorners) {\n ctx.beginPath();\n const half = tw / 2;\n roundedRect(\n ctx,\n x + half,\n y + half,\n width - tw,\n height - tw,\n Math.max(0, borderRadius.topLeft - half),\n Math.max(0, borderRadius.topRight - half),\n Math.max(0, borderRadius.bottomRight - half),\n Math.max(0, borderRadius.bottomLeft - half),\n );\n ctx.stroke();\n } else {\n ctx.strokeRect(x + tw / 2, y + tw / 2, width - tw, height - tw);\n }\n return;\n }\n\n // Draw individual borders\n if (tw > 0) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n ctx.beginPath();\n ctx.moveTo(x, y + tw / 2);\n ctx.lineTo(x + width, y + tw / 2);\n ctx.stroke();\n }\n if (rw > 0) {\n ctx.strokeStyle = rc;\n ctx.lineWidth = rw;\n ctx.beginPath();\n ctx.moveTo(x + width - rw / 2, y);\n ctx.lineTo(x + width - rw / 2, y + height);\n ctx.stroke();\n }\n if (bw > 0) {\n ctx.strokeStyle = bc;\n ctx.lineWidth = bw;\n ctx.beginPath();\n ctx.moveTo(x, y + height - bw / 2);\n ctx.lineTo(x + width, y + height - bw / 2);\n ctx.stroke();\n }\n if (lw > 0) {\n ctx.strokeStyle = lc;\n ctx.lineWidth = lw;\n ctx.beginPath();\n ctx.moveTo(x + lw / 2, y);\n ctx.lineTo(x + lw / 2, y + height);\n ctx.stroke();\n }\n}\n\nfunction drawBoxShadow(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n boxShadow: string,\n borderRadius: ReturnType<typeof getBorderRadius>,\n): void {\n // Parse simple box-shadow: offsetX offsetY blur spread? color\n const parts = boxShadow.match(\n /(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?(?:\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?)?\\s+(.*)/,\n );\n if (!parts) return;\n\n const offsetX = parseFloat(parts[1]!);\n const offsetY = parseFloat(parts[2]!);\n const blur = parseFloat(parts[3]!);\n const color = parts[5]!.trim();\n\n const radii = [\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n ];\n\n // Clip to area OUTSIDE the element so shadow renders but inner fill is hidden\n const margin = blur * 2 + Math.abs(offsetX) + Math.abs(offsetY);\n ctx.save();\n ctx.beginPath();\n ctx.rect(x - margin, y - margin, width + margin * 2, height + margin * 2);\n ctx.roundRect(x, y, width, height, radii);\n ctx.clip(\"evenodd\");\n\n // Use CSS filter blur (sigma = blur/2) instead of the canvas shadow API\n // because it matches SVG feGaussianBlur (used by satori) much more closely.\n ctx.filter = `blur(${blur / 2}px)`;\n ctx.translate(offsetX, offsetY);\n ctx.fillStyle = color;\n ctx.beginPath();\n ctx.roundRect(x, y, width, height, radii);\n ctx.fill();\n ctx.restore();\n}\n","import { Path2D } from \"@napi-rs/canvas\";\nimport type {\n CanvasGradient,\n DOMMatrix2DInit,\n SKRSContext2D,\n} from \"@napi-rs/canvas\";\n\nimport type { LayoutNode } from \"../layout.ts\";\n\ntype SvgChild = {\n type: string;\n props: Record<string, unknown>;\n children?: SvgChild | SvgChild[];\n};\n\ntype BBox = { x: number; y: number; width: number; height: number };\n\n/** Collected `<defs>` definitions: clip paths and gradients. */\ntype SvgDefs = {\n clips: Map<string, SvgChild[]>;\n gradients: Map<string, SvgChild>;\n};\n\n/** Replace `\"currentColor\"` with the inherited CSS `color` value. */\nfunction resolveCurrentColor(\n value: string | undefined,\n color: string,\n): string | undefined {\n if (value?.toLowerCase() === \"currentcolor\") return color;\n return value;\n}\n\n/**\n * Merge SVG presentation properties from `props.style` into the props object.\n * Style values win over direct props, matching browser CSS specificity rules.\n */\nfunction mergeStyleIntoProps(\n props: Record<string, unknown>,\n): Record<string, unknown> {\n const style = props.style as Record<string, unknown> | undefined;\n if (!style) return props;\n return { ...props, ...style };\n}\n\n/**\n * Collect `<clipPath>` and gradient definitions from `<defs>` elements.\n */\nfunction collectDefs(children: SvgChild[]): SvgDefs {\n const clips = new Map<string, SvgChild[]>();\n const gradients = new Map<string, SvgChild>();\n for (const child of children) {\n if (child.type !== \"defs\") continue;\n for (const def of normalizeChildren(child)) {\n const id = def.props.id as string | undefined;\n if (!id) continue;\n if (def.type === \"clipPath\") clips.set(id, normalizeChildren(def));\n else if (def.type === \"radialGradient\" || def.type === \"linearGradient\")\n gradients.set(id, def);\n }\n }\n return { clips, gradients };\n}\n\n/** Parse `url(#id)` references and return the id, or undefined. */\nfunction parseUrlRef(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const m = value.match(/^url\\(#(.+)\\)$/);\n return m?.[1];\n}\n\n/** Normalize children from either `.children` or `.props.children` into an array. */\nfunction normalizeChildren(node: SvgChild): SvgChild[] {\n const raw =\n node.children ?? (node.props.children as SvgChild | SvgChild[] | undefined);\n if (raw == null) return [];\n return Array.isArray(raw) ? raw : [raw];\n}\n\n// ---------------------------------------------------------------------------\n// Gradient helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Parse an SVG length value, resolving percentages against a reference dimension.\n * Unlike `parseFrac`, this returns absolute coordinates (not 0–1 fractions).\n */\nfunction svgLength(value: unknown, reference: number, fallback = 0): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * reference;\n const n = Number(s);\n return isNaN(n) ? fallback : n;\n}\n\n/** Parse a gradient coordinate percentage/fraction to a 0–1 value. */\nfunction parseFrac(value: unknown, fallback: number): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return parseFloat(s) / 100;\n return Number(s);\n}\n\n/** Apply opacity to a CSS color string. */\nfunction applyOpacity(color: string, opacity: number): string {\n if (opacity >= 1) return color;\n const m = color.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);\n if (m)\n return `rgba(${parseInt(m[1]!, 16)}, ${parseInt(m[2]!, 16)}, ${parseInt(m[3]!, 16)}, ${opacity})`;\n return color;\n}\n\n/** Add color stops from SVG `<stop>` children to a canvas gradient. */\nfunction addGradientStops(gradient: CanvasGradient, def: SvgChild): void {\n for (const stop of normalizeChildren(def)) {\n if (stop.type !== \"stop\") continue;\n const sp = stop.props;\n const offsetRaw = (sp.offset as string | number) ?? 0;\n const offset =\n typeof offsetRaw === \"string\" && offsetRaw.endsWith(\"%\")\n ? parseFloat(offsetRaw) / 100\n : Number(offsetRaw);\n const stopColor =\n ((sp.stopColor ?? sp[\"stop-color\"]) as string | undefined) ?? \"black\";\n const stopOpacity = Number(sp.stopOpacity ?? sp[\"stop-opacity\"] ?? 1);\n gradient.addColorStop(offset, applyOpacity(stopColor, stopOpacity));\n }\n}\n\n/**\n * Fill `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n *\n * For `<linearGradient>` the bbox-to-canvas mapping is straightforward.\n * For `<radialGradient>` the SVG default `objectBoundingBox` produces an\n * *elliptical* gradient when the bbox is non-square. Canvas only supports\n * circular radial gradients, so we apply a non-uniform scale transform to\n * the context and fill an inverse-transformed copy of the path.\n */\nfunction fillWithSvgGradient(\n ctx: SKRSContext2D,\n def: SvgChild,\n bbox: BBox,\n path: Path2D,\n fillRule: CanvasFillRule,\n): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n const x1 = bbox.x + parseFrac(props.x1, 0) * bbox.width;\n const y1 = bbox.y + parseFrac(props.y1, 0) * bbox.height;\n const x2 = bbox.x + parseFrac(props.x2, 1) * bbox.width;\n const y2 = bbox.y + parseFrac(props.y2, 0) * bbox.height;\n const gradient = ctx.createLinearGradient(x1, y1, x2, y2);\n addGradientStops(gradient, def);\n ctx.fillStyle = gradient;\n ctx.fill(path, fillRule);\n return true;\n }\n\n if (def.type === \"radialGradient\") {\n const cxF = parseFrac(props.cx, 0.5);\n const cyF = parseFrac(props.cy, 0.5);\n const rF = parseFrac(props.r, 0.5);\n const fxF = parseFrac(props.fx, cxF);\n const fyF = parseFrac(props.fy, cyF);\n\n // Render in a transformed space where the bbox maps to a unit square.\n // This turns canvas's circular radial gradient into the correct ellipse.\n ctx.save();\n ctx.translate(bbox.x, bbox.y);\n ctx.scale(bbox.width, bbox.height);\n\n const gradient = ctx.createRadialGradient(fxF, fyF, 0, cxF, cyF, rF);\n addGradientStops(gradient, def);\n ctx.fillStyle = gradient;\n\n // The path is in original (absolute) coordinates. Inverse-transform it\n // into the unit-square space so the fill aligns with the shape.\n // inverse of translate(bx,by) · scale(bw,bh) = scale(1/bw,1/bh) · translate(-bx,-by)\n const unitPath = new Path2D();\n const invTransform: DOMMatrix2DInit = {\n a: 1 / bbox.width,\n b: 0,\n c: 0,\n d: 1 / bbox.height,\n e: -bbox.x / bbox.width,\n f: -bbox.y / bbox.height,\n };\n unitPath.addPath(path, invTransform);\n\n ctx.fill(unitPath, fillRule);\n ctx.restore();\n return true;\n }\n\n return false;\n}\n\n/**\n * Stroke `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n */\nfunction strokeWithSvgGradient(\n ctx: SKRSContext2D,\n def: SvgChild,\n bbox: BBox,\n path: Path2D,\n): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n const x1 = bbox.x + parseFrac(props.x1, 0) * bbox.width;\n const y1 = bbox.y + parseFrac(props.y1, 0) * bbox.height;\n const x2 = bbox.x + parseFrac(props.x2, 1) * bbox.width;\n const y2 = bbox.y + parseFrac(props.y2, 0) * bbox.height;\n const gradient = ctx.createLinearGradient(x1, y1, x2, y2);\n addGradientStops(gradient, def);\n ctx.strokeStyle = gradient;\n ctx.stroke(path);\n return true;\n }\n\n if (def.type === \"radialGradient\") {\n // For stroke, use a simple circular approximation (geometric mean radius)\n const cxAbs = bbox.x + parseFrac(props.cx, 0.5) * bbox.width;\n const cyAbs = bbox.y + parseFrac(props.cy, 0.5) * bbox.height;\n const rAbs = parseFrac(props.r, 0.5) * Math.sqrt(bbox.width * bbox.height);\n const fxAbs = bbox.x + parseFrac(props.fx, 0.5) * bbox.width;\n const fyAbs = bbox.y + parseFrac(props.fy, 0.5) * bbox.height;\n const gradient = ctx.createRadialGradient(\n fxAbs,\n fyAbs,\n 0,\n cxAbs,\n cyAbs,\n rAbs,\n );\n addGradientStops(gradient, def);\n ctx.strokeStyle = gradient;\n ctx.stroke(path);\n return true;\n }\n\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Bounding-box helpers\n// ---------------------------------------------------------------------------\n\n/** Compute a conservative bounding box from SVG path data. */\nfunction pathBBox(d: string): BBox {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let cx = 0;\n let cy = 0;\n\n const update = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n };\n\n // Tokenize: commands and numbers (including negative)\n const tokens = d.match(/[a-zA-Z]|[-+]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?/g);\n if (!tokens) return { x: 0, y: 0, width: 0, height: 0 };\n\n let cmd = \"\";\n let i = 0;\n const num = () => Number(tokens[i++]);\n\n while (i < tokens.length) {\n const t = tokens[i]!;\n if (/[a-zA-Z]/.test(t)) {\n cmd = t;\n i++;\n }\n\n switch (cmd) {\n case \"M\":\n cx = num();\n cy = num();\n update(cx, cy);\n cmd = \"L\"; // implicit lineTo after moveTo\n break;\n case \"m\":\n cx += num();\n cy += num();\n update(cx, cy);\n cmd = \"l\";\n break;\n case \"L\":\n cx = num();\n cy = num();\n update(cx, cy);\n break;\n case \"l\":\n cx += num();\n cy += num();\n update(cx, cy);\n break;\n case \"H\":\n cx = num();\n update(cx, cy);\n break;\n case \"h\":\n cx += num();\n update(cx, cy);\n break;\n case \"V\":\n cy = num();\n update(cx, cy);\n break;\n case \"v\":\n cy += num();\n update(cx, cy);\n break;\n case \"C\": {\n // Cubic bezier: use control points as conservative bounds\n for (let j = 0; j < 3; j++) {\n const px = num();\n const py = num();\n update(px, py);\n }\n cx = Number(tokens[i - 2]);\n cy = Number(tokens[i - 1]);\n break;\n }\n case \"c\": {\n for (let j = 0; j < 3; j++) {\n const dx = num();\n const dy = num();\n update(cx + dx, cy + dy);\n if (j === 2) {\n cx += dx;\n cy += dy;\n }\n }\n break;\n }\n case \"Q\": {\n for (let j = 0; j < 2; j++) {\n const px = num();\n const py = num();\n update(px, py);\n }\n cx = Number(tokens[i - 2]);\n cy = Number(tokens[i - 1]);\n break;\n }\n case \"q\": {\n for (let j = 0; j < 2; j++) {\n const dx = num();\n const dy = num();\n update(cx + dx, cy + dy);\n if (j === 1) {\n cx += dx;\n cy += dy;\n }\n }\n break;\n }\n case \"A\": {\n // Arc: skip rx, ry, rotation, flags; endpoint is the bound\n num();\n num();\n num();\n num();\n num(); // rx ry rot largeArc sweep\n cx = num();\n cy = num();\n update(cx, cy);\n break;\n }\n case \"a\": {\n num();\n num();\n num();\n num();\n num();\n cx += num();\n cy += num();\n update(cx, cy);\n break;\n }\n case \"Z\":\n case \"z\":\n break;\n default:\n // Unknown command — skip token to avoid infinite loop\n i++;\n break;\n }\n }\n\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/** Compute bounding box from a points attribute (polygon/polyline). */\nfunction pointsBBox(points: [number, number][]): BBox {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of points) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Build a `Path2D` from an SVG shape element (without drawing it).\n * Returns `undefined` for unsupported element types.\n */\nfunction buildPath(\n child: SvgChild,\n vbW: number,\n vbH: number,\n): Path2D | undefined {\n const props = mergeStyleIntoProps(child.props);\n switch (child.type) {\n case \"path\": {\n const d = props.d as string | undefined;\n if (!d) return undefined;\n return new Path2D(d);\n }\n case \"circle\": {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const r = svgLength(props.r, Math.min(vbW, vbH));\n if (r <= 0) return undefined;\n const p = new Path2D();\n p.arc(cx, cy, r, 0, Math.PI * 2);\n return p;\n }\n case \"rect\": {\n const rx = svgLength(props.x, vbW);\n const ry = svgLength(props.y, vbH);\n const w = svgLength(props.width, vbW);\n const h = svgLength(props.height, vbH);\n if (w <= 0 || h <= 0) return undefined;\n const p = new Path2D();\n p.rect(rx, ry, w, h);\n return p;\n }\n case \"ellipse\": {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const rx = svgLength(props.rx, vbW);\n const ry = svgLength(props.ry, vbH);\n if (rx <= 0 || ry <= 0) return undefined;\n const p = new Path2D();\n p.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n return p;\n }\n case \"polygon\": {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return undefined;\n const p = new Path2D();\n p.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n p.lineTo(points[i]![0], points[i]![1]);\n }\n p.closePath();\n return p;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Build a combined `Path2D` from all children of a `<clipPath>` definition.\n */\nfunction buildClipPath(\n shapes: SvgChild[],\n vbW: number,\n vbH: number,\n): Path2D | undefined {\n let combined: Path2D | undefined;\n for (const shape of shapes) {\n const p = buildPath(shape, vbW, vbH);\n if (!p) continue;\n if (!combined) {\n combined = p;\n } else {\n combined.addPath(p);\n }\n }\n return combined;\n}\n\n/**\n * Draw an `<svg>` container and its SVG children (path, circle, rect, etc.).\n *\n * Parses the `viewBox` prop to compute scale factors, then recurses into\n * the React children stored in `node.props.children`.\n */\nexport function drawSvgContainer(\n ctx: SKRSContext2D,\n node: LayoutNode,\n x: number,\n y: number,\n width: number,\n height: number,\n): void {\n ctx.save();\n ctx.translate(x, y);\n\n // Parse viewBox for coordinate mapping; default to rendered size when absent\n const viewBox = node.props.viewBox as string | undefined;\n let vbW = width;\n let vbH = height;\n if (viewBox) {\n const parts = viewBox.split(/[\\s,]+/).map(Number);\n if (parts.length === 4) {\n const [vbX, vbY, parsedW, parsedH] = parts as [\n number,\n number,\n number,\n number,\n ];\n vbW = parsedW;\n vbH = parsedH;\n const scaleX = width / vbW;\n const scaleY = height / vbH;\n ctx.scale(scaleX, scaleY);\n ctx.translate(-vbX, -vbY);\n }\n }\n\n // Resolve the CSS `color` property for `currentColor` references\n const color = (node.style.color as string | undefined) ?? \"black\";\n\n // Inherited fill from the <svg> element (SVG fill is inheritable)\n const merged = mergeStyleIntoProps(node.props);\n const inheritedFill =\n resolveCurrentColor(merged.fill as string | undefined, color) ?? \"black\";\n\n // Traverse React children\n const children = node.props.children;\n if (children != null) {\n const childArray = Array.isArray(children) ? children : [children];\n const svgChildren = childArray.filter(\n (c): c is SvgChild => c != null && typeof c === \"object\",\n );\n\n // First pass: collect definitions from <defs>\n const defs = collectDefs(svgChildren);\n\n // Second pass: draw children\n for (const child of svgChildren) {\n drawSvgChild(ctx, child, inheritedFill, color, defs, vbW, vbH);\n }\n }\n\n ctx.restore();\n}\n\nconst EMPTY_DEFS: SvgDefs = {\n clips: new Map(),\n gradients: new Map(),\n};\n\nfunction drawSvgChild(\n ctx: SKRSContext2D,\n child: SvgChild,\n inheritedFill: string,\n color: string,\n defs: SvgDefs = EMPTY_DEFS,\n vbW = 0,\n vbH = 0,\n): void {\n const { type } = child;\n const props = mergeStyleIntoProps(child.props);\n\n // Skip non-drawable definition elements\n if (type === \"defs\" || type === \"clipPath\") return;\n\n // Check for clip-path=\"url(#id)\" reference\n const clipRef = parseUrlRef(props.clipPath ?? props[\"clip-path\"]);\n const clipShapes = clipRef ? defs.clips.get(clipRef) : undefined;\n const clipPath = clipShapes ? buildClipPath(clipShapes, vbW, vbH) : undefined;\n\n if (clipPath) ctx.save();\n if (clipPath) ctx.clip(clipPath);\n\n switch (type) {\n case \"path\":\n drawPath(ctx, props, inheritedFill, color, defs);\n break;\n case \"circle\":\n drawCircle(ctx, props, inheritedFill, color, defs, vbW, vbH);\n break;\n case \"rect\":\n drawSvgRect(ctx, props, inheritedFill, color, defs, vbW, vbH);\n break;\n case \"line\":\n drawLine(ctx, props, color, defs, vbW, vbH);\n break;\n case \"ellipse\":\n drawEllipse(ctx, props, inheritedFill, color, defs, vbW, vbH);\n break;\n case \"polygon\":\n drawPolygon(ctx, props, inheritedFill, color, defs);\n break;\n case \"polyline\":\n drawPolyline(ctx, props, inheritedFill, color, defs);\n break;\n case \"g\":\n drawGroup(ctx, child, inheritedFill, color, defs, vbW, vbH);\n break;\n }\n\n if (clipPath) ctx.restore();\n}\n\nfunction drawPath(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n): void {\n const d = props.d as string | undefined;\n if (!d) return;\n\n const path = new Path2D(d);\n const bbox = pathBBox(d);\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawCircle(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const r = svgLength(props.r, Math.min(vbW, vbH));\n if (r <= 0) return;\n\n const path = new Path2D();\n path.arc(cx, cy, r, 0, Math.PI * 2);\n const bbox: BBox = { x: cx - r, y: cy - r, width: 2 * r, height: 2 * r };\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawSvgRect(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const rx = svgLength(props.x, vbW);\n const ry = svgLength(props.y, vbH);\n const w = svgLength(props.width, vbW);\n const h = svgLength(props.height, vbH);\n if (w <= 0 || h <= 0) return;\n\n const path = new Path2D();\n path.rect(rx, ry, w, h);\n const bbox: BBox = { x: rx, y: ry, width: w, height: h };\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawLine(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const x1 = svgLength(props.x1, vbW);\n const y1 = svgLength(props.y1, vbH);\n const x2 = svgLength(props.x2, vbW);\n const y2 = svgLength(props.y2, vbH);\n\n const path = new Path2D();\n path.moveTo(x1, y1);\n path.lineTo(x2, y2);\n // Lines are stroke-only\n const bbox: BBox = {\n x: Math.min(x1, x2),\n y: Math.min(y1, y2),\n width: Math.abs(x2 - x1),\n height: Math.abs(y2 - y1),\n };\n applyStroke(ctx, props, path, color, defs, bbox);\n}\n\nfunction drawEllipse(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const rx = svgLength(props.rx, vbW);\n const ry = svgLength(props.ry, vbH);\n if (rx <= 0 || ry <= 0) return;\n\n const path = new Path2D();\n path.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n const bbox: BBox = {\n x: cx - rx,\n y: cy - ry,\n width: 2 * rx,\n height: 2 * ry,\n };\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawPolygon(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n): void {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return;\n\n const path = new Path2D();\n path.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n path.lineTo(points[i]![0], points[i]![1]);\n }\n path.closePath();\n const bbox = pointsBBox(points);\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawPolyline(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n): void {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return;\n\n const path = new Path2D();\n path.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n path.lineTo(points[i]![0], points[i]![1]);\n }\n const bbox = pointsBBox(points);\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\n/**\n * Parse an SVG `transform` attribute and apply it to the canvas context.\n *\n * Supports: translate, scale, rotate, skewX, skewY, matrix.\n * Multiple transforms are applied left-to-right (same order as SVG spec).\n */\nfunction applySvgTransform(ctx: SKRSContext2D, transform: string): void {\n const re = /\\b(translate|scale|rotate|skewX|skewY|matrix)\\s*\\(([^)]*)\\)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(transform)) !== null) {\n const fn = match[1]!;\n const args = match[2]!\n .split(/[\\s,]+/)\n .filter(Boolean)\n .map(Number);\n\n switch (fn) {\n case \"translate\":\n ctx.translate(args[0] ?? 0, args[1] ?? 0);\n break;\n case \"scale\": {\n const sx = args[0] ?? 1;\n ctx.scale(sx, args[1] ?? sx);\n break;\n }\n case \"rotate\": {\n const angle = ((args[0] ?? 0) * Math.PI) / 180;\n if (args.length >= 3) {\n const cx = args[1]!;\n const cy = args[2]!;\n ctx.translate(cx, cy);\n ctx.rotate(angle);\n ctx.translate(-cx, -cy);\n } else {\n ctx.rotate(angle);\n }\n break;\n }\n case \"skewX\":\n ctx.transform(\n 1,\n 0,\n Math.tan(((args[0] ?? 0) * Math.PI) / 180),\n 1,\n 0,\n 0,\n );\n break;\n case \"skewY\":\n ctx.transform(\n 1,\n Math.tan(((args[0] ?? 0) * Math.PI) / 180),\n 0,\n 1,\n 0,\n 0,\n );\n break;\n case \"matrix\":\n ctx.transform(\n args[0] ?? 1,\n args[1] ?? 0,\n args[2] ?? 0,\n args[3] ?? 1,\n args[4] ?? 0,\n args[5] ?? 0,\n );\n break;\n }\n }\n}\n\nfunction drawGroup(\n ctx: SKRSContext2D,\n node: SvgChild,\n inheritedFill: string,\n color: string,\n defs: SvgDefs = EMPTY_DEFS,\n vbW = 0,\n vbH = 0,\n): void {\n const children = normalizeChildren(node);\n if (children.length === 0) return;\n // Group can override inherited fill\n const merged = mergeStyleIntoProps(node.props);\n const groupFill =\n resolveCurrentColor(merged.fill as string | undefined, color) ??\n inheritedFill;\n\n const transform = merged.transform as string | undefined;\n if (transform) {\n ctx.save();\n applySvgTransform(ctx, transform);\n }\n\n for (const child of children) {\n if (child != null && typeof child === \"object\") {\n drawSvgChild(ctx, child, groupFill, color, defs, vbW, vbH);\n }\n }\n\n if (transform) {\n ctx.restore();\n }\n}\n\nfunction parsePoints(value: string | undefined): [number, number][] {\n if (!value) return [];\n const nums = value\n .trim()\n .split(/[\\s,]+/)\n .map(Number);\n const result: [number, number][] = [];\n for (let i = 0; i + 1 < nums.length; i += 2) {\n result.push([nums[i]!, nums[i + 1]!]);\n }\n return result;\n}\n\nfunction applyFillAndStroke(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n path: Path2D,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n bbox: BBox,\n): void {\n // Use element's own fill if set, otherwise inherit from parent\n const fill =\n resolveCurrentColor(props.fill as string | undefined, color) ??\n inheritedFill;\n const fillRule = (props.fillRule ?? props[\"fill-rule\"]) as\n | CanvasFillRule\n | undefined;\n // Resolve url(#id) gradient reference\n const fillRef = parseUrlRef(fill);\n if (fillRef) {\n const gradientDef = defs.gradients.get(fillRef);\n if (gradientDef) {\n fillWithSvgGradient(ctx, gradientDef, bbox, path, fillRule ?? \"nonzero\");\n }\n } else if (fill !== \"none\") {\n ctx.fillStyle = fill;\n ctx.fill(path, fillRule ?? \"nonzero\");\n }\n\n applyStroke(ctx, props, path, color, defs, bbox);\n}\n\nfunction applyStroke(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n path: Path2D,\n color: string,\n defs: SvgDefs,\n bbox: BBox,\n): void {\n const stroke = resolveCurrentColor(props.stroke as string | undefined, color);\n if (!stroke || stroke === \"none\") return;\n\n ctx.lineWidth = Number(props.strokeWidth ?? props[\"stroke-width\"] ?? 1);\n ctx.lineCap =\n ((props.strokeLinecap ?? props[\"stroke-linecap\"]) as CanvasLineCap) ??\n \"butt\";\n ctx.lineJoin =\n ((props.strokeLinejoin ?? props[\"stroke-linejoin\"]) as CanvasLineJoin) ??\n \"miter\";\n\n // Resolve url(#id) gradient reference for stroke\n const strokeRef = parseUrlRef(stroke);\n if (strokeRef) {\n const gradientDef = defs.gradients.get(strokeRef);\n if (gradientDef) {\n strokeWithSvgGradient(ctx, gradientDef, bbox, path);\n return;\n }\n }\n\n ctx.strokeStyle = stroke;\n ctx.stroke(path);\n}\n","import { loadImage } from \"@napi-rs/canvas\";\nimport type { SKRSContext2D, Image } from \"@napi-rs/canvas\";\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport { getEmojiCode, loadEmoji } from \"../emoji.ts\";\nimport type { TextSegment } from \"../text/index.ts\";\nimport { splitTextIntoRuns } from \"../text/emoji-split.ts\";\nimport { setFont } from \"../text/measure.ts\";\n\nconst emojiImageCache = new Map<string, Promise<Image | null>>();\n\nfunction loadEmojiImage(\n style: EmojiStyle,\n char: string,\n): Promise<Image | null> {\n const code = getEmojiCode(char);\n const key = style + \":\" + code;\n let cached = emojiImageCache.get(key);\n if (!cached) {\n cached = loadEmoji(style, code)\n .then((svgText) => {\n if (!svgText || !svgText.includes(\"<svg\")) return null;\n const dataUri =\n \"data:image/svg+xml;base64,\" +\n Buffer.from(svgText).toString(\"base64\");\n return loadImage(dataUri);\n })\n .catch(() => null);\n emojiImageCache.set(key, cached);\n }\n return cached;\n}\n\n/**\n * Draw text segments onto the canvas context.\n *\n * @param ctx - Canvas 2D rendering context\n * @param segments - Positioned text segments from the text layout engine\n * @param offsetX - X offset for the text block\n * @param offsetY - Y offset for the text block\n * @param textShadow - Optional text-shadow CSS value\n * @param emojiStyle - Optional emoji style for rendering emoji as images\n */\nexport async function drawText(\n ctx: SKRSContext2D,\n segments: TextSegment[],\n offsetX: number,\n offsetY: number,\n textShadow?: string,\n emojiStyle?: EmojiStyle,\n): Promise<void> {\n for (const seg of segments) {\n if (!seg.text) continue;\n\n setFont(ctx, seg.fontSize, seg.fontFamily, seg.fontWeight, seg.fontStyle);\n ctx.fillStyle = seg.color;\n\n const x = offsetX + seg.x;\n const y = offsetY + seg.y;\n\n if (emojiStyle) {\n await drawSegmentWithEmoji(ctx, seg, x, y, textShadow, emojiStyle);\n } else if (seg.letterSpacing && seg.letterSpacing !== 0) {\n drawTextWithLetterSpacing(ctx, seg.text, x, y, seg.letterSpacing);\n } else {\n if (textShadow) {\n drawTextShadow(ctx, seg.text, x, y, textShadow);\n }\n ctx.fillText(seg.text, x, y);\n }\n\n // Text decoration\n if (seg.textDecoration) {\n drawTextDecoration(ctx, seg, offsetX, offsetY);\n }\n }\n}\n\nasync function drawSegmentWithEmoji(\n ctx: SKRSContext2D,\n seg: TextSegment,\n x: number,\n y: number,\n textShadow: string | undefined,\n emojiStyle: EmojiStyle,\n): Promise<void> {\n const letterSpacing = seg.letterSpacing ?? 0;\n const runs = splitTextIntoRuns(\n seg.text,\n (text) => {\n setFont(ctx, seg.fontSize, seg.fontFamily, seg.fontWeight, seg.fontStyle);\n return ctx.measureText(text).width;\n },\n seg.fontSize,\n letterSpacing,\n );\n\n for (const run of runs) {\n if (run.kind === \"text\") {\n if (letterSpacing !== 0) {\n if (textShadow) {\n drawTextShadow(ctx, run.text, x + run.x, y, textShadow);\n }\n drawTextWithLetterSpacing(ctx, run.text, x + run.x, y, letterSpacing);\n } else {\n if (textShadow) {\n drawTextShadow(ctx, run.text, x + run.x, y, textShadow);\n }\n ctx.fillText(run.text, x + run.x, y);\n }\n } else {\n const img = await loadEmojiImage(emojiStyle, run.char);\n if (img) {\n const emojiSize = seg.fontSize;\n // Position emoji so it aligns vertically with text:\n // y is the baseline, ascent goes up from baseline\n const emojiY = y - seg.ascent + (seg.height - seg.fontSize) / 2;\n ctx.drawImage(img, x + run.x, emojiY, emojiSize, emojiSize);\n } else {\n // Emoji image unavailable — fall back to text rendering\n ctx.fillText(run.char, x + run.x, y);\n }\n }\n }\n}\n\nfunction drawTextWithLetterSpacing(\n ctx: SKRSContext2D,\n text: string,\n x: number,\n y: number,\n letterSpacing: number,\n): void {\n let currentX = x;\n for (const char of text) {\n ctx.fillText(char, currentX, y);\n const metrics = ctx.measureText(char);\n currentX += metrics.width + letterSpacing;\n }\n}\n\nfunction drawTextShadow(\n ctx: SKRSContext2D,\n text: string,\n x: number,\n y: number,\n shadow: string,\n): void {\n const parts = shadow.match(\n /(-?\\d+(?:\\.\\d+)?)\\s*px?\\s+(-?\\d+(?:\\.\\d+)?)\\s*px?\\s+(-?\\d+(?:\\.\\d+)?)\\s*px?\\s+(.*)/,\n );\n if (!parts) return;\n\n ctx.save();\n ctx.shadowOffsetX = parseFloat(parts[1]!);\n ctx.shadowOffsetY = parseFloat(parts[2]!);\n ctx.shadowBlur = parseFloat(parts[3]!);\n ctx.shadowColor = parts[4]!.trim();\n ctx.fillText(text, x, y);\n ctx.restore();\n}\n\nfunction drawTextDecoration(\n ctx: SKRSContext2D,\n seg: TextSegment,\n offsetX: number,\n offsetY: number,\n): void {\n const decoration = seg.textDecoration;\n if (!decoration || decoration === \"none\") return;\n\n ctx.strokeStyle = seg.color;\n ctx.lineWidth = Math.max(1, seg.fontSize * 0.1);\n\n const x = offsetX + seg.x;\n const baseY = offsetY + seg.y;\n\n if (decoration.includes(\"underline\")) {\n const y = baseY + seg.ascent * 0.1;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n\n if (decoration.includes(\"line-through\")) {\n const y = baseY - seg.fontSize * 0.3;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n\n if (decoration.includes(\"overline\")) {\n const y = baseY - seg.fontSize * 0.85;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\n/**\n * Emoji style options for rendering\n */\nexport type EmojiStyle =\n | \"twemoji\"\n | \"openmoji\"\n | \"blobmoji\"\n | \"noto\"\n | \"fluent\"\n | \"fluentFlat\";\n\nexport const emojiApis: Record<\n EmojiStyle,\n string | ((code: string) => string)\n> = {\n twemoji: (code: string) =>\n `https://cdnjs.cloudflare.com/ajax/libs/twemoji/16.0.1/svg/${code.toLowerCase()}.svg`,\n openmoji: \"https://cdn.jsdelivr.net/npm/@svgmoji/openmoji@2.0.0/svg/\",\n blobmoji: \"https://cdn.jsdelivr.net/npm/@svgmoji/blob@2.0.0/svg/\",\n noto: \"https://cdn.jsdelivr.net/gh/svgmoji/svgmoji/packages/svgmoji__noto/svg/\",\n fluent: (code: string) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_color.svg`,\n fluentFlat: (code: string) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_flat.svg`,\n};\n\nconst U200D = String.fromCharCode(8205);\nconst UFE0Fg = /\\uFE0F/g;\n\nexport function getEmojiCode(char: string): string {\n return toCodePoint(char.indexOf(U200D) < 0 ? char.replace(UFE0Fg, \"\") : char);\n}\n\nexport function toCodePoint(unicodeSurrogates: string): string {\n const r: string[] = [];\n let c = 0,\n p = 0,\n i = 0;\n\n while (i < unicodeSurrogates.length) {\n c = unicodeSurrogates.charCodeAt(i++);\n if (p) {\n r.push((65536 + ((p - 55296) << 10) + (c - 56320)).toString(16));\n p = 0;\n } else if (55296 <= c && c <= 56319) {\n p = c;\n } else {\n r.push(c.toString(16));\n }\n }\n return r.join(\"-\");\n}\n\nconst emojiCache: Record<string, Promise<string>> = {};\n\nexport async function loadEmoji(\n type: EmojiStyle,\n code: string,\n): Promise<string> {\n const key = type + \":\" + code;\n if (key in emojiCache) return emojiCache[key];\n\n const api = emojiApis[type];\n if (typeof api === \"function\") {\n return (emojiCache[key] = fetch(api(code)).then((r) => r.text()));\n }\n return (emojiCache[key] = fetch(`${api}${code.toUpperCase()}.svg`).then((r) =>\n r.text(),\n ));\n}\n","import { isEmoji } from \"../language.ts\";\n\nexport type TextRun =\n | { kind: \"text\"; text: string; x: number; width: number }\n | { kind: \"emoji\"; char: string; x: number; width: number };\n\n/**\n * Split a text string into runs of plain text and individual emoji characters.\n * Uses Intl.Segmenter for correct grapheme cluster handling (multi-codepoint emoji).\n */\nexport function splitTextIntoRuns(\n text: string,\n measureText: (text: string) => number,\n emojiSize: number,\n letterSpacing: number = 0,\n): TextRun[] {\n const runs: TextRun[] = [];\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n let currentText = \"\";\n let currentX = 0;\n let textStartX = 0;\n\n for (const { segment } of segmenter.segment(text)) {\n if (isEmojiGrapheme(segment)) {\n // Flush accumulated text\n if (currentText) {\n const textWidth = measureText(currentText);\n const graphemeCount = [\n ...new Intl.Segmenter(undefined, { granularity: \"grapheme\" }).segment(\n currentText,\n ),\n ].length;\n runs.push({\n kind: \"text\",\n text: currentText,\n x: textStartX,\n width: textWidth + letterSpacing * graphemeCount,\n });\n currentX = textStartX + textWidth + letterSpacing * graphemeCount;\n currentText = \"\";\n }\n runs.push({\n kind: \"emoji\",\n char: segment,\n x: currentX,\n width: emojiSize,\n });\n currentX += emojiSize + letterSpacing;\n textStartX = currentX;\n } else {\n if (!currentText) textStartX = currentX;\n currentText += segment;\n }\n }\n\n // Flush remaining text\n if (currentText) {\n const textWidth = measureText(currentText);\n const graphemeCount = [\n ...new Intl.Segmenter(undefined, { granularity: \"grapheme\" }).segment(\n currentText,\n ),\n ].length;\n runs.push({\n kind: \"text\",\n text: currentText,\n x: textStartX,\n width: textWidth + letterSpacing * graphemeCount,\n });\n }\n\n return runs;\n}\n\n/**\n * Check if a grapheme cluster is an emoji.\n * Checks the first code point of the grapheme.\n */\nfunction isEmojiGrapheme(grapheme: string): boolean {\n for (const char of grapheme) {\n if (isEmoji(char)) return true;\n }\n return false;\n}\n","import { GlobalFonts } from \"@napi-rs/canvas\";\n\nimport type { FontData } from \"../types.ts\";\n\nconst registeredFonts = new Set<string>();\n\n/**\n * Reset internal font state (test-only).\n */\nexport function _resetForTest(): void {\n registeredFonts.clear();\n}\n\n/**\n * Register a font from a FontData buffer.\n * Registration is idempotent — re-registering the same font name is a no-op.\n *\n * @param font - Font data to register\n */\nexport function registerFont(font: FontData): void {\n const key = `${font.name}:${font.weight}:${font.style}`;\n if (registeredFonts.has(key)) return;\n\n const buffer = Buffer.isBuffer(font.data)\n ? font.data\n : Buffer.from(font.data);\n\n GlobalFonts.register(buffer, font.name);\n\n registeredFonts.add(key);\n}\n\n/**\n * Register a font from a file path.\n *\n * @param path - Path to the font file\n * @param nameAlias - Optional font family name override\n */\nexport function registerFontFromPath(path: string, nameAlias?: string): void {\n GlobalFonts.registerFromPath(path, nameAlias ?? \"\");\n}\n\n/**\n * Get the list of registered font family names.\n *\n * @returns Array of font family names\n */\nexport function registeredFamilies(): string[] {\n return GlobalFonts.families.map((f: { family: string }) => f.family);\n}\n\n/**\n * Ensure all fonts from the given array are registered.\n * Called internally by `renderReactElement()`.\n */\nexport function ensureFontsRegistered(fonts: FontData[]): void {\n for (const font of fonts) {\n registerFont(font);\n }\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\nimport { loadImage } from \"@napi-rs/canvas\";\nimport type { ReactElement, ReactNode } from \"react\";\n\nimport { expandStyle } from \"./style/expand.ts\";\nimport { resolveStyle, resolveUnits, DEFAULT_STYLE } from \"./style/compute.ts\";\nimport type { ComputedStyle } from \"./style/compute.ts\";\nimport { applyStylesToYoga } from \"./style/properties.ts\";\nimport { createTextMeasureFunc } from \"./text/index.ts\";\nimport { createYogaNode, freeYogaNode, FlexDirection } from \"./yoga.ts\";\nimport type { YogaNode } from \"./yoga.ts\";\n\n/**\n * A node in the computed layout tree, ready for drawing.\n */\nexport type LayoutNode = {\n type: string;\n style: ComputedStyle;\n children: LayoutNode[];\n textContent?: string;\n props: Record<string, unknown>;\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\ntype ElementChild = string | number | ReactElement | null | undefined | boolean;\n\n/**\n * Build a layout tree from a React element tree.\n * Creates Yoga nodes, calculates layout, and returns the positioned tree.\n *\n * @param element - React element tree to lay out\n * @param containerWidth - Width of the container (from canvas)\n * @param containerHeight - Height of the container (from canvas)\n * @param ctx - Canvas context for text measurement\n * @returns Root layout node with computed positions and dimensions\n */\nexport async function buildLayoutTree(\n element: ReactNode,\n containerWidth: number,\n containerHeight: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n fontFamilies?: string[],\n): Promise<LayoutNode> {\n const elementYogaNode = createYogaNode();\n\n // Set font families as default on root style so all nodes inherit them\n const rootStyle = fontFamilies?.length\n ? { ...DEFAULT_STYLE, fontFamily: fontFamilies.join(\", \") }\n : DEFAULT_STYLE;\n\n // Build the tree\n const elementNode = await buildNode(\n element,\n rootStyle,\n elementYogaNode,\n containerWidth,\n containerHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n );\n\n // Wrap the user element in a canvas-sized container (like Satori) so that\n // absolute positioning, percentage sizes, etc. resolve against the canvas.\n const rootYogaNode = createYogaNode();\n rootYogaNode.setWidth(containerWidth);\n rootYogaNode.setHeight(containerHeight);\n rootYogaNode.setFlexDirection(FlexDirection.Row);\n rootYogaNode.insertChild(elementYogaNode, 0);\n\n rootYogaNode.calculateLayout(containerWidth, containerHeight);\n\n const elementLayout = extractLayout(elementNode, elementYogaNode);\n freeYogaNode(rootYogaNode);\n\n return {\n type: \"div\",\n style: rootStyle,\n children: [elementLayout],\n props: {},\n x: 0,\n y: 0,\n width: containerWidth,\n height: containerHeight,\n } as LayoutNode;\n}\n\nasync function buildNode(\n element: ReactNode,\n parentStyle: ComputedStyle,\n yogaNode: YogaNode,\n viewportWidth: number,\n viewportHeight: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n fontFamilies?: string[],\n): Promise<IntermediateNode> {\n // Handle null/undefined/boolean\n if (\n element === null ||\n element === undefined ||\n typeof element === \"boolean\"\n ) {\n return {\n type: \"empty\",\n style: parentStyle,\n children: [],\n props: {},\n yogaNode,\n };\n }\n\n // Handle text/number primitives\n if (typeof element === \"string\" || typeof element === \"number\") {\n const text = String(element);\n const style = resolveStyle(undefined, parentStyle);\n\n // Set up text measurement\n const measureFunc = createTextMeasureFunc(text, style, ctx, emojiEnabled);\n yogaNode.setMeasureFunc(measureFunc);\n\n return {\n type: \"text\",\n style,\n children: [],\n textContent: text,\n props: {},\n yogaNode,\n };\n }\n\n // Handle arrays (fragments)\n if (Array.isArray(element)) {\n const style = resolveStyle(undefined, parentStyle);\n const children: IntermediateNode[] = [];\n\n for (let i = 0; i < element.length; i++) {\n const child = element[i] as ElementChild;\n if (child === null || child === undefined || typeof child === \"boolean\")\n continue;\n\n const childYogaNode = createYogaNode();\n yogaNode.insertChild(childYogaNode, children.length);\n children.push(\n await buildNode(\n child,\n style,\n childYogaNode,\n viewportWidth,\n viewportHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n ),\n );\n }\n\n return {\n type: \"div\",\n style,\n children,\n props: {},\n yogaNode,\n };\n }\n\n // Handle React elements\n const el = element as ReactElement<Record<string, unknown>>;\n const type = el.type;\n\n // Expand function/class components\n if (typeof type === \"function\") {\n const rendered = (type as (props: Record<string, unknown>) => ReactNode)(\n el.props ?? {},\n );\n return await buildNode(\n rendered,\n parentStyle,\n yogaNode,\n viewportWidth,\n viewportHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n );\n }\n\n const props = (el.props ?? {}) as Record<string, unknown>;\n const rawStyle = (props.style ?? {}) as Record<string, unknown>;\n const expanded = expandStyle(rawStyle, fontFamilies);\n const style = resolveStyle(expanded, parentStyle);\n resolveUnits(style, viewportWidth, viewportHeight);\n\n const tagName = String(type);\n\n // For <svg> elements, merge width/height props into style when not set via CSS\n if (tagName === \"svg\") {\n if (props.width != null && style.width === undefined) {\n const v = props.width;\n style.width = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n if (props.height != null && style.height === undefined) {\n const v = props.height;\n style.height = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n\n // Derive missing dimension from viewBox aspect ratio\n const viewBox = props.viewBox as string | undefined;\n if (viewBox) {\n const parts = viewBox.split(/[\\s,]+/).map(Number);\n if (parts.length === 4) {\n const [, , vbW, vbH] = parts as [number, number, number, number];\n if (vbW > 0 && vbH > 0) {\n const wSet = style.width !== undefined;\n const hSet = style.height !== undefined;\n if (!wSet && !hSet) {\n style.width = vbW;\n style.height = vbH;\n } else if (!hSet && typeof style.width === \"number\") {\n style.height = style.width * (vbH / vbW);\n } else if (!wSet && typeof style.height === \"number\") {\n style.width = style.height * (vbW / vbH);\n }\n // When either/both are %, leave as-is for Yoga\n }\n }\n }\n }\n\n // For <img> elements, derive missing dimensions from intrinsic aspect ratio\n if (tagName === \"img\") {\n // Map HTML width/height attributes to style (like <svg>)\n if (props.width != null && style.width === undefined) {\n const v = props.width;\n style.width = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n if (props.height != null && style.height === undefined) {\n const v = props.height;\n style.height = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n\n const src = props.src as string | Buffer | undefined;\n if (src) {\n try {\n const image = await loadImage(src);\n const naturalW = image.width;\n const naturalH = image.height;\n\n const wSet = style.width !== undefined;\n const hSet = style.height !== undefined;\n\n if (wSet && !hSet && typeof style.width === \"number\" && naturalW > 0) {\n style.height = style.width * (naturalH / naturalW);\n } else if (\n hSet &&\n !wSet &&\n typeof style.height === \"number\" &&\n naturalH > 0\n ) {\n style.width = style.height * (naturalW / naturalH);\n }\n // When either/both are %, leave as-is for Yoga\n\n // Cache loaded image for reuse during drawing\n props.__loadedImage = image;\n } catch {\n // Silent fail — image will render at whatever size Yoga computes\n }\n }\n }\n\n // Apply styles to Yoga node\n applyStylesToYoga(yogaNode, style);\n\n // SVG containers: children use SVG coordinate space, not flex layout.\n // Skip Yoga child nodes and keep React children in props for the SVG drawer.\n if (tagName === \"svg\") {\n return {\n type: tagName,\n style,\n children: [],\n props,\n yogaNode,\n };\n }\n\n // Collect text content from direct string children\n const textContent = extractTextContent(props.children);\n\n // If this node has only text content, create a child text node.\n // Using a child node (instead of setMeasureFunc on this node directly)\n // ensures Yoga's baseline calculation accounts for this node's padding/border\n // when a parent uses alignItems: \"baseline\".\n if (textContent !== undefined && !hasElementChildren(props.children)) {\n const childStyle = resolveStyle(undefined, style);\n const childYogaNode = createYogaNode();\n const measureFunc = createTextMeasureFunc(\n textContent,\n childStyle,\n ctx,\n emojiEnabled,\n );\n childYogaNode.setMeasureFunc(measureFunc);\n childYogaNode.setFlexGrow(1);\n childYogaNode.setFlexShrink(1);\n yogaNode.insertChild(childYogaNode, 0);\n\n return {\n type: tagName,\n style,\n children: [\n {\n type: \"text\",\n style: childStyle,\n children: [],\n textContent,\n props: {},\n yogaNode: childYogaNode,\n },\n ],\n props,\n yogaNode,\n };\n }\n\n // Process children\n const children: IntermediateNode[] = [];\n const rawChildren = props.children;\n\n if (rawChildren !== undefined && rawChildren !== null) {\n const childArray = Array.isArray(rawChildren) ? rawChildren : [rawChildren];\n\n for (const child of childArray as ElementChild[]) {\n if (child === null || child === undefined || typeof child === \"boolean\")\n continue;\n\n const childYogaNode = createYogaNode();\n yogaNode.insertChild(childYogaNode, children.length);\n children.push(\n await buildNode(\n child,\n style,\n childYogaNode,\n viewportWidth,\n viewportHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n ),\n );\n }\n }\n\n return {\n type: tagName,\n style,\n children,\n props,\n yogaNode,\n };\n}\n\ntype IntermediateNode = {\n type: string;\n style: ComputedStyle;\n children: IntermediateNode[];\n textContent?: string;\n props: Record<string, unknown>;\n yogaNode: YogaNode;\n};\n\nfunction extractLayout(node: IntermediateNode, yogaNode: YogaNode): LayoutNode {\n const layout = yogaNode.getComputedLayout();\n\n return {\n type: node.type,\n style: node.style,\n children: node.children.map((child, i) => {\n const childYoga = yogaNode.getChild(i);\n return extractLayout(child, childYoga);\n }),\n textContent: node.textContent,\n props: node.props,\n x: layout.left,\n y: layout.top,\n width: layout.width,\n height: layout.height,\n };\n}\n\n/**\n * Extract plain text content from children if they are all strings/numbers.\n */\nfunction extractTextContent(children: unknown): string | undefined {\n if (children === undefined || children === null) return undefined;\n if (typeof children === \"string\") return children;\n if (typeof children === \"number\") return String(children);\n\n if (Array.isArray(children)) {\n const parts: string[] = [];\n for (const child of children) {\n if (typeof child === \"string\") {\n parts.push(child);\n } else if (typeof child === \"number\") {\n parts.push(String(child));\n } else if (\n child !== null &&\n child !== undefined &&\n typeof child !== \"boolean\"\n ) {\n return undefined; // Mixed content — not pure text\n }\n }\n return parts.join(\"\");\n }\n\n return undefined;\n}\n\n/**\n * Check if children contains any React elements (not just strings/numbers).\n */\nfunction hasElementChildren(children: unknown): boolean {\n if (\n children === undefined ||\n children === null ||\n typeof children === \"boolean\"\n )\n return false;\n if (typeof children === \"string\" || typeof children === \"number\")\n return false;\n\n if (Array.isArray(children)) {\n return children.some(\n (child) =>\n child !== null &&\n child !== undefined &&\n typeof child !== \"boolean\" &&\n typeof child !== \"string\" &&\n typeof child !== \"number\",\n );\n }\n\n // Single React element\n return typeof children === \"object\";\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { ExpandedStyle } from \"./compute.ts\";\n\ntype RawStyle = Record<string, unknown>;\n\nconst SIDES = [\"Top\", \"Right\", \"Bottom\", \"Left\"] as const;\n\n/**\n * Parse a CSS shorthand value like \"10px 20px\" into 1-4 parts.\n */\nfunction parseSides(value: string): string[] {\n const parts = value.toString().split(/\\s+/).filter(Boolean);\n switch (parts.length) {\n case 1:\n return [parts[0]!, parts[0]!, parts[0]!, parts[0]!];\n case 2:\n return [parts[0]!, parts[1]!, parts[0]!, parts[1]!];\n case 3:\n return [parts[0]!, parts[1]!, parts[2]!, parts[1]!];\n default:\n return [parts[0]!, parts[1]!, parts[2]!, parts[3]!];\n }\n}\n\nfunction parseValue(v: unknown): number | string | undefined {\n if (v === undefined || v === null) return undefined;\n const s = String(v);\n if (s === \"auto\") return \"auto\";\n const n = Number(s);\n if (s !== \"\" && !isNaN(n)) return n;\n return s;\n}\n\n/**\n * Expand CSS shorthand properties into their longhand equivalents.\n * Mutates and returns the style object.\n */\nexport function expandStyle(\n raw: RawStyle,\n fontFamilies?: string[],\n): ExpandedStyle {\n const style = { ...raw } as Record<string, unknown>;\n\n // margin shorthand\n if (style.margin !== undefined) {\n const sides = parseSides(String(style.margin));\n for (let i = 0; i < 4; i++) {\n const key = `margin${SIDES[i]}`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.margin;\n }\n\n // padding shorthand\n if (style.padding !== undefined) {\n const sides = parseSides(String(style.padding));\n for (let i = 0; i < 4; i++) {\n const key = `padding${SIDES[i]}`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.padding;\n }\n\n // borderRadius shorthand\n if (style.borderRadius !== undefined) {\n const sides = parseSides(String(style.borderRadius));\n const corners = [\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomRightRadius\",\n \"borderBottomLeftRadius\",\n ];\n for (let i = 0; i < 4; i++) {\n if (style[corners[i]!] === undefined)\n style[corners[i]!] = parseValue(sides[i]);\n }\n delete style.borderRadius;\n }\n\n // borderWidth shorthand\n if (style.borderWidth !== undefined) {\n const sides = parseSides(String(style.borderWidth));\n for (let i = 0; i < 4; i++) {\n const key = `border${SIDES[i]}Width`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.borderWidth;\n }\n\n // borderColor shorthand\n if (style.borderColor !== undefined) {\n const val = style.borderColor;\n for (const side of SIDES) {\n const key = `border${side}Color`;\n if (style[key] === undefined) style[key] = val;\n }\n delete style.borderColor;\n }\n\n // borderStyle shorthand\n if (style.borderStyle !== undefined) {\n const val = style.borderStyle;\n for (const side of SIDES) {\n const key = `border${side}Style`;\n if (style[key] === undefined) style[key] = val;\n }\n delete style.borderStyle;\n }\n\n // border shorthand (e.g. \"1px solid black\")\n if (style.border !== undefined) {\n const parts = String(style.border).split(/\\s+/);\n const width = parseValue(parts[0]);\n const borderStyle = parts[1] ?? \"solid\";\n const color = parts[2] ?? \"black\";\n for (const side of SIDES) {\n if (style[`border${side}Width`] === undefined)\n style[`border${side}Width`] = width;\n if (style[`border${side}Style`] === undefined)\n style[`border${side}Style`] = borderStyle;\n if (style[`border${side}Color`] === undefined)\n style[`border${side}Color`] = color;\n }\n delete style.border;\n }\n\n // Per-side border shorthands (e.g. borderLeft: \"3px solid white\")\n for (const side of SIDES) {\n const key = `border${side}`;\n if (style[key] !== undefined) {\n const parts = String(style[key]).split(/\\s+/);\n const width = parseValue(parts[0]);\n const borderStyle = parts[1] ?? \"solid\";\n const color = parts[2] ?? \"black\";\n if (style[`${key}Width`] === undefined) style[`${key}Width`] = width;\n if (style[`${key}Style`] === undefined)\n style[`${key}Style`] = borderStyle;\n if (style[`${key}Color`] === undefined) style[`${key}Color`] = color;\n delete style[key];\n }\n }\n\n // flex shorthand\n if (style.flex !== undefined) {\n const val = String(style.flex);\n const parts = val.split(/\\s+/);\n if (parts.length === 1) {\n const n = parseFloat(parts[0]!);\n if (!isNaN(n)) {\n if (style.flexGrow === undefined) style.flexGrow = n;\n if (style.flexShrink === undefined) style.flexShrink = 1;\n if (style.flexBasis === undefined) style.flexBasis = 0;\n }\n } else if (parts.length === 2) {\n if (style.flexGrow === undefined) style.flexGrow = parseFloat(parts[0]!);\n if (style.flexShrink === undefined)\n style.flexShrink = parseFloat(parts[1]!);\n } else if (parts.length >= 3) {\n if (style.flexGrow === undefined) style.flexGrow = parseFloat(parts[0]!);\n if (style.flexShrink === undefined)\n style.flexShrink = parseFloat(parts[1]!);\n if (style.flexBasis === undefined) style.flexBasis = parseValue(parts[2]);\n }\n delete style.flex;\n }\n\n // gap shorthand\n if (style.gap !== undefined) {\n const sides = parseSides(String(style.gap));\n if (style.rowGap === undefined) style.rowGap = parseValue(sides[0]);\n if (style.columnGap === undefined) style.columnGap = parseValue(sides[1]);\n delete style.gap;\n }\n\n // background shorthand\n if (style.background !== undefined) {\n const bg = String(style.background);\n if (bg.includes(\"gradient(\") || bg.includes(\"url(\")) {\n if (style.backgroundImage === undefined) style.backgroundImage = bg;\n } else {\n if (style.backgroundColor === undefined) style.backgroundColor = bg;\n }\n delete style.background;\n }\n\n // overflow shorthand\n if (style.overflow !== undefined) {\n if (style.overflowX === undefined) style.overflowX = style.overflow;\n if (style.overflowY === undefined) style.overflowY = style.overflow;\n }\n\n // textBox shorthand (e.g. \"trim-both cap alphabetic\")\n if (style.textBox !== undefined) {\n const val = String(style.textBox);\n if (val === \"normal\" || val === \"none\") {\n style.textBoxTrim ??= \"none\";\n } else {\n const parts = val.split(/\\s+/);\n style.textBoxTrim ??= parts[0];\n if (parts.length > 1) {\n style.textBoxEdge ??= parts.slice(1).join(\" \");\n }\n }\n delete style.textBox;\n }\n\n // fontFamily normalization\n if (typeof style.fontFamily === \"string\") {\n const families = style.fontFamily\n .split(\",\")\n .map((s) => s.trim().replace(/^['\"]|['\"]$/g, \"\"))\n .filter(Boolean);\n if (fontFamilies) {\n const present = new Set(families);\n for (const name of fontFamilies) {\n if (!present.has(name)) families.push(name);\n }\n }\n style.fontFamily = families.join(\", \");\n }\n\n return style as unknown as ExpandedStyle;\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\n/**\n * Style after shorthand expansion but before unit resolution.\n * Properties like fontSize may still contain CSS unit strings (e.g. \"4em\").\n */\nexport type ExpandedStyle = Omit<ComputedStyle, \"fontSize\"> & {\n fontSize?: number | string;\n};\n\n/**\n * Normalized, computed CSS style after shorthand expansion.\n * All dimension values are numbers (pixels) or percentage strings.\n */\nexport type ComputedStyle = {\n // Display & layout\n display?: \"flex\" | \"none\";\n flexDirection?: \"row\" | \"column\" | \"row-reverse\" | \"column-reverse\";\n justifyContent?:\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n alignItems?: \"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"baseline\";\n alignSelf?:\n | \"auto\"\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"stretch\"\n | \"baseline\";\n alignContent?:\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"stretch\"\n | \"space-between\"\n | \"space-around\";\n flexWrap?: \"nowrap\" | \"wrap\" | \"wrap-reverse\";\n flexGrow?: number;\n flexShrink?: number;\n flexBasis?: number | string;\n\n // Dimensions\n width?: number | string;\n height?: number | string;\n minWidth?: number | string;\n minHeight?: number | string;\n maxWidth?: number | string;\n maxHeight?: number | string;\n\n // Position\n position?: \"relative\" | \"absolute\";\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n\n // Margin\n marginTop?: number | string;\n marginRight?: number | string;\n marginBottom?: number | string;\n marginLeft?: number | string;\n\n // Padding\n paddingTop?: number | string;\n paddingRight?: number | string;\n paddingBottom?: number | string;\n paddingLeft?: number | string;\n\n // Border\n borderTopWidth?: number | string;\n borderRightWidth?: number | string;\n borderBottomWidth?: number | string;\n borderLeftWidth?: number | string;\n borderTopColor?: string;\n borderRightColor?: string;\n borderBottomColor?: string;\n borderLeftColor?: string;\n borderTopStyle?: string;\n borderRightStyle?: string;\n borderBottomStyle?: string;\n borderLeftStyle?: string;\n borderTopLeftRadius?: number | string;\n borderTopRightRadius?: number | string;\n borderBottomRightRadius?: number | string;\n borderBottomLeftRadius?: number | string;\n\n // Gap\n rowGap?: number;\n columnGap?: number;\n\n // Overflow\n overflow?: string;\n overflowX?: string;\n overflowY?: string;\n\n // Colors & background\n backgroundColor?: string;\n color?: string;\n opacity?: number;\n backgroundImage?: string;\n backgroundSize?: string;\n\n // Typography\n fontSize?: number;\n fontFamily?: string;\n fontWeight?: number | string;\n fontStyle?: \"normal\" | \"italic\";\n textAlign?: \"left\" | \"center\" | \"right\" | \"justify\";\n textDecoration?: string;\n textTransform?: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\n lineHeight?: number | string;\n letterSpacing?: number | string;\n whiteSpace?: \"normal\" | \"nowrap\" | \"pre\" | \"pre-wrap\" | \"pre-line\";\n wordBreak?: \"normal\" | \"break-all\" | \"break-word\" | \"keep-all\";\n textOverflow?: \"clip\" | \"ellipsis\";\n\n // Box shadow\n boxShadow?: string;\n textShadow?: string;\n\n // Transform\n transform?: string;\n transformOrigin?: string;\n\n // Image\n objectFit?: \"contain\" | \"cover\" | \"fill\" | \"none\" | \"scale-down\";\n\n // Filter\n filter?: string;\n\n // Text box trim\n textBoxTrim?: \"none\" | \"trim-start\" | \"trim-end\" | \"trim-both\";\n textBoxEdge?: string;\n};\n\nconst ROOT_FONT_SIZE = 16;\n\n/**\n * Default styles for the root element.\n */\nexport const DEFAULT_STYLE: ComputedStyle = {\n display: \"flex\",\n flexDirection: \"row\",\n flexWrap: \"nowrap\",\n flexGrow: 0,\n flexShrink: 0,\n alignItems: \"stretch\",\n justifyContent: \"flex-start\",\n position: \"relative\",\n fontSize: ROOT_FONT_SIZE,\n fontWeight: 400,\n fontStyle: \"normal\",\n color: \"black\",\n lineHeight: \"normal\",\n textAlign: \"left\",\n whiteSpace: \"normal\",\n wordBreak: \"normal\",\n textOverflow: \"clip\",\n opacity: 1,\n overflow: \"visible\",\n};\n\n/**\n * CSS properties that are inherited by child elements.\n */\nconst INHERITABLE_PROPS: (keyof ComputedStyle)[] = [\n \"color\",\n \"fontSize\",\n \"fontFamily\",\n \"fontWeight\",\n \"fontStyle\",\n \"textAlign\",\n \"textTransform\",\n \"textDecoration\",\n \"lineHeight\",\n \"letterSpacing\",\n \"whiteSpace\",\n \"wordBreak\",\n \"textOverflow\",\n \"textBoxTrim\",\n \"textBoxEdge\",\n];\n\n/**\n * Resolve the computed style for a node, inheriting from parent where appropriate.\n */\nexport function resolveStyle(\n rawStyle: ExpandedStyle | undefined,\n parentStyle: ComputedStyle,\n): ComputedStyle {\n const style = { ...rawStyle };\n\n // Apply inherited properties\n for (const prop of INHERITABLE_PROPS) {\n if (style[prop] === undefined && parentStyle[prop] !== undefined) {\n (style as Record<string, unknown>)[prop] = parentStyle[prop];\n }\n }\n\n // Resolve fontSize (ensure it's a number, respecting em/rem/etc units)\n if (typeof style.fontSize === \"string\") {\n const parentFontSize =\n typeof parentStyle.fontSize === \"number\"\n ? parentStyle.fontSize\n : ROOT_FONT_SIZE;\n const resolved = resolveUnit(\n style.fontSize,\n 0,\n 0,\n parentFontSize,\n ROOT_FONT_SIZE,\n );\n style.fontSize = typeof resolved === \"number\" ? resolved : parentFontSize;\n }\n\n // Resolve lineHeight: parse string values to numbers but keep multipliers\n // as-is so they're recalculated per-element in text layout (using each\n // element's own fontSize rather than the parent's).\n if (typeof style.lineHeight === \"string\") {\n const str = style.lineHeight;\n if (str.endsWith(\"%\")) {\n style.lineHeight = parseFloat(str) / 100;\n } else {\n const parsed = parseFloat(str);\n if (!isNaN(parsed)) {\n style.lineHeight = parsed;\n }\n }\n }\n\n // Resolve letterSpacing (respecting em/rem/etc units)\n if (typeof style.letterSpacing === \"string\") {\n const currentFontSize =\n typeof style.fontSize === \"number\"\n ? style.fontSize\n : typeof parentStyle.fontSize === \"number\"\n ? parentStyle.fontSize\n : ROOT_FONT_SIZE;\n const resolved = resolveUnit(\n style.letterSpacing,\n 0,\n 0,\n currentFontSize,\n ROOT_FONT_SIZE,\n );\n if (typeof resolved === \"number\") {\n style.letterSpacing = resolved;\n }\n }\n\n return style as ComputedStyle;\n}\n\n/**\n * Dimension properties that may contain CSS units needing resolution.\n */\nconst DIMENSION_PROPS: (keyof ComputedStyle)[] = [\n \"width\",\n \"height\",\n \"minWidth\",\n \"minHeight\",\n \"maxWidth\",\n \"maxHeight\",\n \"top\",\n \"right\",\n \"bottom\",\n \"left\",\n \"marginTop\",\n \"marginRight\",\n \"marginBottom\",\n \"marginLeft\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"rowGap\",\n \"columnGap\",\n \"flexBasis\",\n \"borderTopWidth\",\n \"borderRightWidth\",\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomRightRadius\",\n \"borderBottomLeftRadius\",\n];\n\n/**\n * Resolve a single CSS dimension string to a pixel number.\n * Returns the original value for `%` and `auto` (Yoga handles those),\n * and for values that are already numbers or unrecognised strings.\n */\nfunction resolveUnit(\n value: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n): number | string {\n // Percentages and auto are handled downstream by Yoga\n if (value.endsWith(\"%\") || value === \"auto\") return value;\n\n // Viewport-relative units\n if (value.endsWith(\"vmin\")) {\n const n = parseFloat(value);\n return isNaN(n)\n ? value\n : (n / 100) * Math.min(viewportWidth, viewportHeight);\n }\n if (value.endsWith(\"vmax\")) {\n const n = parseFloat(value);\n return isNaN(n)\n ? value\n : (n / 100) * Math.max(viewportWidth, viewportHeight);\n }\n if (value.endsWith(\"vw\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : (n / 100) * viewportWidth;\n }\n if (value.endsWith(\"vh\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : (n / 100) * viewportHeight;\n }\n\n // Font-relative units\n if (value.endsWith(\"rem\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * rootFontSize;\n }\n if (value.endsWith(\"em\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * fontSize;\n }\n\n // Absolute units (CSS reference pixel = 1/96 inch)\n if (value.endsWith(\"px\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n;\n }\n if (value.endsWith(\"pt\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 72);\n }\n if (value.endsWith(\"pc\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * 16;\n }\n if (value.endsWith(\"in\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * 96;\n }\n if (value.endsWith(\"cm\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 2.54);\n }\n if (value.endsWith(\"mm\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 25.4);\n }\n\n return value;\n}\n\n/**\n * Resolve CSS units (vw, vh, vmin, vmax, em, rem, px, pt, pc, in, cm, mm)\n * in a style object to pixel values. Percentages and `auto` pass through\n * unchanged for Yoga to handle.\n */\nexport function resolveUnits(\n style: ComputedStyle,\n viewportWidth: number,\n viewportHeight: number,\n rootFontSize: number = ROOT_FONT_SIZE,\n): ComputedStyle {\n const fontSize =\n typeof style.fontSize === \"number\" ? style.fontSize : rootFontSize;\n\n for (const prop of DIMENSION_PROPS) {\n const value = style[prop];\n if (typeof value !== \"string\") continue;\n const resolved = resolveUnit(\n value,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n if (resolved !== value) {\n (style as Record<string, unknown>)[prop] = resolved;\n }\n }\n\n // Resolve CSS length units inside transform strings so that by draw time\n // values are either bare numbers or `%` (which need element dimensions).\n if (style.transform) {\n style.transform = resolveTransformUnits(\n style.transform,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n }\n if (style.transformOrigin) {\n style.transformOrigin = resolveTransformUnits(\n style.transformOrigin,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n }\n\n return style;\n}\n\n/**\n * Resolve CSS length units (vw, vh, em, rem, px, etc.) inside a transform or\n * transformOrigin string. Percentages and angle units (deg, rad, turn) are\n * left untouched — percentages need element dimensions (available at draw time)\n * and angle units are not lengths.\n */\nfunction resolveTransformUnits(\n transform: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n): string {\n return transform.replace(\n /(-?\\d*\\.?\\d+)(vw|vh|vmin|vmax|em|rem|px|pt|pc|in|cm|mm)\\b/g,\n (match) => {\n const resolved = resolveUnit(\n match,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n return typeof resolved === \"number\" ? String(resolved) : match;\n },\n );\n}\n\n/**\n * Resolve a dimension value (width, height, margin, etc.) to pixels.\n * Percentage values are resolved relative to the provided container size.\n */\nexport function resolveDimension(\n value: number | string | undefined,\n containerSize: number,\n): number | undefined {\n if (value === undefined || value === \"auto\") return undefined;\n if (typeof value === \"number\") return value;\n const s = String(value);\n if (s.endsWith(\"%\")) {\n return (parseFloat(s) / 100) * containerSize;\n }\n const n = parseFloat(s);\n return isNaN(n) ? undefined : n;\n}\n","import Yoga, {\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n} from \"yoga-layout\";\nimport type { Node as YogaNode } from \"yoga-layout\";\n\nexport type { YogaNode };\n\nexport {\n Yoga,\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n};\n\nexport function createYogaNode(): YogaNode {\n return Yoga.Node.create();\n}\n\nexport function freeYogaNode(node: YogaNode): void {\n node.freeRecursive();\n}\n","import {\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n} from \"../yoga.ts\";\nimport type { YogaNode } from \"../yoga.ts\";\nimport type { ComputedStyle } from \"./compute.ts\";\n\n/**\n * Apply computed CSS styles to a Yoga node.\n */\nexport function applyStylesToYoga(node: YogaNode, style: ComputedStyle): void {\n // Display\n if (style.display === \"none\") {\n node.setDisplay(Display.None);\n } else {\n node.setDisplay(Display.Flex);\n }\n\n // Flex direction (CSS default is \"row\", Yoga defaults to \"column\")\n {\n const map: Record<string, FlexDirection> = {\n row: FlexDirection.Row,\n \"row-reverse\": FlexDirection.RowReverse,\n column: FlexDirection.Column,\n \"column-reverse\": FlexDirection.ColumnReverse,\n };\n node.setFlexDirection(\n map[style.flexDirection ?? \"row\"] ?? FlexDirection.Row,\n );\n }\n\n // Justify content\n if (style.justifyContent) {\n const map: Record<string, Justify> = {\n \"flex-start\": Justify.FlexStart,\n \"flex-end\": Justify.FlexEnd,\n center: Justify.Center,\n \"space-between\": Justify.SpaceBetween,\n \"space-around\": Justify.SpaceAround,\n \"space-evenly\": Justify.SpaceEvenly,\n };\n const jc = map[style.justifyContent];\n if (jc !== undefined) node.setJustifyContent(jc);\n }\n\n // Align items\n if (style.alignItems) {\n const map: Record<string, Align> = {\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n baseline: Align.Baseline,\n };\n const ai = map[style.alignItems];\n if (ai !== undefined) node.setAlignItems(ai);\n }\n\n // Align self\n if (style.alignSelf) {\n const map: Record<string, Align> = {\n auto: Align.Auto,\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n baseline: Align.Baseline,\n };\n const as_ = map[style.alignSelf];\n if (as_ !== undefined) node.setAlignSelf(as_);\n }\n\n // Align content\n if (style.alignContent) {\n const map: Record<string, Align> = {\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n \"space-between\": Align.SpaceBetween,\n \"space-around\": Align.SpaceAround,\n };\n const ac = map[style.alignContent];\n if (ac !== undefined) node.setAlignContent(ac);\n }\n\n // Flex wrap\n if (style.flexWrap) {\n const map: Record<string, Wrap> = {\n nowrap: Wrap.NoWrap,\n wrap: Wrap.Wrap,\n \"wrap-reverse\": Wrap.WrapReverse,\n };\n const fw = map[style.flexWrap];\n if (fw !== undefined) node.setFlexWrap(fw);\n }\n\n // Flex grow / shrink / basis\n if (style.flexGrow !== undefined) node.setFlexGrow(style.flexGrow);\n // Satori defaults flexShrink to 0 (React Native convention); match it for compatibility\n node.setFlexShrink(style.flexShrink ?? 0);\n if (style.flexBasis !== undefined) {\n if (typeof style.flexBasis === \"number\") {\n node.setFlexBasis(style.flexBasis);\n } else if (String(style.flexBasis).endsWith(\"%\")) {\n node.setFlexBasis(String(style.flexBasis) as `${number}%`);\n } else if (style.flexBasis === \"auto\") {\n node.setFlexBasis(\"auto\");\n } else {\n const n = parseFloat(String(style.flexBasis));\n if (!isNaN(n)) node.setFlexBasis(n);\n }\n }\n\n // Dimensions\n applyDimension(node, \"setWidth\", style.width);\n applyDimension(node, \"setHeight\", style.height);\n applyDimension(node, \"setMinWidth\", style.minWidth);\n applyDimension(node, \"setMinHeight\", style.minHeight);\n applyDimension(node, \"setMaxWidth\", style.maxWidth);\n applyDimension(node, \"setMaxHeight\", style.maxHeight);\n\n // Position\n if (style.position === \"absolute\") {\n node.setPositionType(PositionType.Absolute);\n } else {\n node.setPositionType(PositionType.Relative);\n }\n\n // Position edges\n applyEdgeValue(node, \"setPosition\", Edge.Top, style.top);\n applyEdgeValue(node, \"setPosition\", Edge.Right, style.right);\n applyEdgeValue(node, \"setPosition\", Edge.Bottom, style.bottom);\n applyEdgeValue(node, \"setPosition\", Edge.Left, style.left);\n\n // Margin\n applyEdgeValue(node, \"setMargin\", Edge.Top, style.marginTop);\n applyEdgeValue(node, \"setMargin\", Edge.Right, style.marginRight);\n applyEdgeValue(node, \"setMargin\", Edge.Bottom, style.marginBottom);\n applyEdgeValue(node, \"setMargin\", Edge.Left, style.marginLeft);\n\n // Padding\n applyEdgeValue(node, \"setPadding\", Edge.Top, style.paddingTop);\n applyEdgeValue(node, \"setPadding\", Edge.Right, style.paddingRight);\n applyEdgeValue(node, \"setPadding\", Edge.Bottom, style.paddingBottom);\n applyEdgeValue(node, \"setPadding\", Edge.Left, style.paddingLeft);\n\n // Border width (resolved to numbers by resolveUnits before this point)\n if (style.borderTopWidth !== undefined)\n node.setBorder(Edge.Top, style.borderTopWidth as number);\n if (style.borderRightWidth !== undefined)\n node.setBorder(Edge.Right, style.borderRightWidth as number);\n if (style.borderBottomWidth !== undefined)\n node.setBorder(Edge.Bottom, style.borderBottomWidth as number);\n if (style.borderLeftWidth !== undefined)\n node.setBorder(Edge.Left, style.borderLeftWidth as number);\n\n // Gap\n if (style.rowGap !== undefined) node.setGap(Gutter.Row, style.rowGap);\n if (style.columnGap !== undefined)\n node.setGap(Gutter.Column, style.columnGap);\n\n // Overflow\n if (\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\"\n ) {\n node.setOverflow(Overflow.Hidden);\n } else {\n node.setOverflow(Overflow.Visible);\n }\n}\n\nfunction applyDimension(\n node: YogaNode,\n setter:\n | \"setWidth\"\n | \"setHeight\"\n | \"setMinWidth\"\n | \"setMinHeight\"\n | \"setMaxWidth\"\n | \"setMaxHeight\",\n value: number | string | undefined,\n): void {\n if (value === undefined) return;\n if (value === \"auto\") {\n if (setter === \"setWidth\" || setter === \"setHeight\") {\n node[setter](\"auto\");\n }\n return;\n }\n if (typeof value === \"number\") {\n node[setter](value);\n return;\n }\n const s = String(value);\n if (s.endsWith(\"%\")) {\n node[setter](s as `${number}%`);\n } else {\n const n = parseFloat(s);\n if (!isNaN(n)) node[setter](n);\n }\n}\n\nfunction applyEdgeValue(\n node: YogaNode,\n setter: \"setMargin\" | \"setPadding\" | \"setPosition\",\n edge: Edge,\n value: number | string | undefined,\n): void {\n if (value === undefined) return;\n if (value === \"auto\" && setter === \"setMargin\") {\n node.setMargin(edge, \"auto\");\n return;\n }\n if (typeof value === \"number\") {\n node[setter](edge, value);\n return;\n }\n const s = String(value);\n if (s.endsWith(\"%\")) {\n node[setter](edge, s as `${number}%`);\n } else {\n const n = parseFloat(s);\n if (!isNaN(n)) node[setter](edge, n);\n }\n}\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\nimport type { ReactNode } from \"react\";\n\nimport type { RenderReactElementOptions } from \"../types.ts\";\nimport { drawNode } from \"./draw/index.ts\";\nimport { ensureFontsRegistered } from \"./font.ts\";\nimport { buildLayoutTree } from \"./layout.ts\";\n\n/**\n * Render a React element tree to a canvas context.\n *\n * Width and height are taken from the canvas itself (`ctx.canvas.width` /\n * `ctx.canvas.height`).\n *\n * @param ctx - Canvas 2D rendering context to draw into\n * @param element - React element tree to render\n * @param options - Rendering options (fonts, debug mode)\n *\n * @example\n * ```tsx\n * import { createCanvas, renderReactElement } from \"@effing/canvas\";\n *\n * const canvas = createCanvas(1080, 1080);\n * const ctx = canvas.getContext(\"2d\");\n *\n * await renderReactElement(ctx, <MyComponent />, { fonts: [myFont] });\n *\n * const png = canvas.encodeSync(\"png\");\n * ```\n */\nexport async function renderReactElement(\n ctx: SKRSContext2D,\n element: ReactNode,\n options: RenderReactElementOptions,\n): Promise<void> {\n // Register fonts\n ensureFontsRegistered(options.fonts);\n\n // Get dimensions from canvas\n const width = ctx.canvas.width;\n const height = ctx.canvas.height;\n\n // Build layout tree (Yoga)\n const emojiStyle =\n options.emoji === \"none\" ? undefined : (options.emoji ?? \"twemoji\");\n const fontFamilies = [...new Set(options.fonts.map((f) => f.name))];\n const layoutTree = await buildLayoutTree(\n element,\n width,\n height,\n ctx,\n !!emojiStyle,\n fontFamilies,\n );\n\n // Draw to canvas\n await drawNode(ctx, layoutTree, 0, 0, options.debug ?? false, emojiStyle);\n}\n"],"mappings":"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","names":["GlobalFonts","loadImage","createCanvas","loadImage","loadImage","measureText","loadImage","canvas","createCanvas","hasRadius","loadImage","loadImage","style","children","loadImage","createCanvas"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lottie.ts","../src/jsx/draw/index.ts","../src/jsx/language.ts","../src/jsx/text/linebreak.ts","../src/jsx/text/measure.ts","../src/jsx/text/index.ts","../src/jsx/draw/clip.ts","../src/jsx/draw/gradient.ts","../src/jsx/draw/image.ts","../src/jsx/draw/object-fit.ts","../src/jsx/draw/utils.ts","../src/jsx/draw/rect.ts","../src/jsx/draw/svg.ts","../src/jsx/draw/text.ts","../src/jsx/emoji.ts","../src/jsx/text/emoji-split.ts","../src/jsx/font.ts","../src/jsx/layout.ts","../src/jsx/style/expand.ts","../src/jsx/style/compute.ts","../src/jsx/yoga.ts","../src/jsx/style/properties.ts","../src/jsx/index.ts"],"sourcesContent":["// Re-export canvas primitives from @napi-rs/canvas\nimport { createCanvas as _createCanvas } from \"@napi-rs/canvas\";\nexport {\n Canvas,\n type SKRSContext2D,\n GlobalFonts,\n loadImage,\n Image,\n} from \"@napi-rs/canvas\";\n\nexport function createCanvas(width: number, height: number) {\n const canvas = _createCanvas(width, height);\n const origEncode = canvas.encode.bind(canvas);\n type Encode = typeof canvas.encode;\n\n // The native @napi-rs/canvas encode() returns Buffers backed by Rust/Skia\n // memory that can be freed before downstream consumers finish reading (e.g.\n // when streaming frames concurrently). We patch encode to copy the result\n // to the JS heap so the data remains valid regardless of native GC timing.\n canvas.encode = (async (...args: unknown[]) =>\n Buffer.from(await origEncode(...(args as Parameters<Encode>)))) as Encode;\n\n return canvas;\n}\n\n// Lottie API\nexport { LottieAnimation, loadLottie, renderLottieFrame } from \"./lottie.ts\";\n\n// JSX API\nexport { renderReactElement } from \"./jsx/index.ts\";\n\n// Font management\nexport {\n registerFont,\n registerFontFromPath,\n registeredFamilies,\n} from \"./jsx/font.ts\";\n\n// Types\nexport type {\n FontData,\n RenderReactElementOptions,\n EmojiStyle,\n} from \"./types.ts\";\n","import { LottieAnimation } from \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\n\nexport { LottieAnimation };\n\n/**\n * Load a Lottie animation from a JSON string or Buffer.\n *\n * @param data - Lottie JSON string or Buffer\n * @param options - Optional resource path for external assets\n * @returns A `LottieAnimation` handle ready for rendering\n *\n * @example\n * ```ts\n * const anim = loadLottie(fs.readFileSync(\"animation.json\", \"utf-8\"));\n * ```\n */\nexport function loadLottie(\n data: string | Buffer,\n options?: { resourcePath?: string },\n): LottieAnimation {\n const jsonString = typeof data === \"string\" ? data : data.toString(\"utf-8\");\n return LottieAnimation.loadFromData(jsonString, {\n resourcePath: options?.resourcePath,\n });\n}\n\n/**\n * Render a specific frame of a Lottie animation to a canvas context.\n *\n * Seeks the animation to the given frame, then renders it onto the\n * provided context. The canvas dimensions determine the render size.\n *\n * @param ctx - Canvas 2D rendering context to draw into\n * @param animation - Lottie animation handle (from {@link loadLottie})\n * @param frame - Zero-based frame number to render\n *\n * @example\n * ```ts\n * import { createCanvas, loadLottie, renderLottieFrame } from \"@effing/canvas\";\n *\n * const canvas = createCanvas(1080, 1080);\n * const ctx = canvas.getContext(\"2d\");\n * const anim = loadLottie(jsonString);\n *\n * renderLottieFrame(ctx, anim, 0);\n * const png = canvas.encodeSync(\"png\");\n * ```\n */\nexport function renderLottieFrame(\n ctx: SKRSContext2D,\n animation: LottieAnimation,\n frame: number,\n): void {\n animation.seekFrame(frame);\n animation.render(ctx);\n}\n","import type { Canvas, Image, SKRSContext2D } from \"@napi-rs/canvas\";\n\nimport { createCanvas, loadImage } from \"@napi-rs/canvas\";\n\nconst canvasPool = new Map<string, WeakRef<Canvas>[]>();\n\nfunction acquireOffscreen(w: number, h: number): [Canvas, SKRSContext2D] {\n const key = `${w}x${h}`;\n const stack = canvasPool.get(key);\n if (stack) {\n while (stack.length > 0) {\n const ref = stack.pop()!;\n const canvas = ref.deref();\n if (canvas) {\n const ctx = canvas.getContext(\"2d\");\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, w, h);\n return [canvas, ctx];\n }\n }\n }\n const canvas = createCanvas(w, h);\n return [canvas, canvas.getContext(\"2d\")];\n}\n\nfunction releaseOffscreen(canvas: Canvas): void {\n const key = `${canvas.width}x${canvas.height}`;\n let stack = canvasPool.get(key);\n if (!stack) {\n stack = [];\n canvasPool.set(key, stack);\n }\n stack.push(new WeakRef(canvas));\n}\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport type { LayoutNode } from \"../layout.ts\";\nimport { layoutText } from \"../text/index.ts\";\nimport { applyClip, hasRadius, roundedRect } from \"./clip.ts\";\nimport { createGradientFromCSS, splitGradientArgs } from \"./gradient.ts\";\nimport { drawImage } from \"./image.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\nimport { drawRect, getBorderRadiusFromStyle } from \"./rect.ts\";\nimport { drawSvgContainer } from \"./svg.ts\";\nimport { drawText } from \"./text.ts\";\nimport { parseCSSLength, resolveBoxValue } from \"./utils.ts\";\n\n/**\n * Main draw dispatcher: recursively draws the layout tree onto the canvas.\n */\nexport async function drawNode(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n debug: boolean,\n emojiStyle?: EmojiStyle,\n): Promise<void> {\n const x = parentX + node.x;\n const y = parentY + node.y;\n const { width, height, style } = node;\n\n if (style.display === \"none\") return;\n\n const opacity = style.opacity ?? 1;\n if (opacity <= 0) return;\n\n // Detect scale in transform — if present, render to offscreen buffer at 1x\n // then composite scaled. This avoids Skia re-rasterizing glyphs per-frame.\n const scaleInfo = style.transform ? extractScale(style.transform) : null;\n if (scaleInfo && (scaleInfo.sx !== 1 || scaleInfo.sy !== 1)) {\n const sx = scaleInfo.sx;\n const sy = scaleInfo.sy;\n const transformWithoutScale = scaleInfo.remaining;\n\n // Quantize to ceil(|scale|) — buffer resolution only changes at\n // integer boundaries (no jitter), and composite is always ≤1x (sharp).\n const qx = Math.max(1, Math.ceil(Math.abs(sx)));\n const qy = Math.max(1, Math.ceil(Math.abs(sy)));\n\n const bufW = Math.ceil((width + 2) * qx);\n const bufH = Math.ceil((height + 2) * qy);\n if (bufW > 0 && bufH > 0) {\n const [offscreen, offCtx] = acquireOffscreen(bufW, bufH);\n\n // Render at qx×qy resolution — logical coords produce more pixels\n offCtx.save();\n offCtx.scale(qx, qy);\n await drawNodeCore(\n offCtx,\n node,\n parentX,\n parentY,\n 1 - x,\n 1 - y,\n debug,\n emojiStyle,\n transformWithoutScale,\n );\n offCtx.restore();\n\n ctx.save();\n if (opacity < 1) {\n ctx.globalAlpha *= opacity;\n }\n\n let ox = x + width / 2;\n let oy = y + height / 2;\n if (style.transformOrigin) {\n const parts = style.transformOrigin.split(/\\s+/);\n ox = resolveOrigin(parts[0], x, width);\n oy = resolveOrigin(parts[1], y, height);\n }\n\n // Apply the original scale — drawImage maps the high-res buffer\n // back to logical size, so the transform needs the full scale value.\n ctx.translate(ox, oy);\n ctx.scale(sx, sy);\n ctx.translate(-ox, -oy);\n\n // Draw high-res buffer back at logical size (qx→1x downscale happens here)\n ctx.drawImage(\n offscreen,\n 0,\n 0,\n bufW,\n bufH,\n x - 1,\n y - 1,\n width + 2,\n height + 2,\n );\n releaseOffscreen(offscreen);\n ctx.restore();\n return;\n }\n }\n\n await drawNodeCore(ctx, node, parentX, parentY, 0, 0, debug, emojiStyle);\n}\n\n/**\n * Extract scale(sx, sy) from a transform string, returning the scale values\n * and the remaining transform with scale removed.\n */\nfunction extractScale(\n transform: string,\n): { sx: number; sy: number; remaining: string } | null {\n const scaleMatch = transform.match(/\\b(scale|scaleX|scaleY)\\(([^)]+)\\)/);\n if (!scaleMatch) return null;\n\n const [fullMatch, name, args] = scaleMatch;\n const values = args!.split(\",\").map((s) => s.trim());\n\n const sx = name === \"scaleY\" ? 1 : parseFloat(values[0]!);\n const sy =\n name === \"scaleX\"\n ? 1\n : parseFloat(values[name === \"scale\" ? 1 : 0] ?? String(sx));\n\n const remaining = transform.replace(fullMatch!, \"\").trim();\n return { sx, sy, remaining };\n}\n\n/**\n * Core draw logic shared by both the normal path and the offscreen-buffer path.\n * offsetX/offsetY shift all coordinates so the node renders at a buffer-local position.\n * overrideTransform replaces the node's transform (used to strip scale for offscreen).\n */\nasync function drawNodeCore(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n offsetX: number,\n offsetY: number,\n debug: boolean,\n emojiStyle: EmojiStyle | undefined,\n overrideTransform?: string,\n): Promise<void> {\n const x = parentX + node.x + offsetX;\n const y = parentY + node.y + offsetY;\n const { width, height, style } = node;\n\n if (style.display === \"none\") return;\n\n const opacity = style.opacity ?? 1;\n if (opacity <= 0) return;\n\n ctx.save();\n\n // Apply opacity\n if (opacity < 1) {\n ctx.globalAlpha *= opacity;\n }\n\n // Apply CSS filter\n if (style.filter) {\n ctx.filter = style.filter;\n }\n\n // Apply transform (use override when provided, e.g. scale stripped)\n const transformToApply =\n overrideTransform !== undefined ? overrideTransform : style.transform;\n if (transformToApply) {\n applyTransform(\n ctx,\n transformToApply,\n x,\n y,\n width,\n height,\n style.transformOrigin,\n );\n }\n\n // Apply clipping for overflow: hidden\n const isClipped =\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\";\n\n if (isClipped) {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n\n // Draw background and borders\n if (\n style.backgroundColor ||\n style.borderTopWidth ||\n style.borderRightWidth ||\n style.borderBottomWidth ||\n style.borderLeftWidth ||\n style.boxShadow\n ) {\n drawRect(ctx, x, y, width, height, style);\n }\n\n // Draw background-image (gradient or url) — supports multiple comma-separated layers\n if (style.backgroundImage) {\n const layers = splitGradientArgs(style.backgroundImage);\n // CSS paints last layer first (bottommost)\n for (let i = layers.length - 1; i >= 0; i--) {\n const layer = layers[i]!.trim();\n const gradient = createGradientFromCSS(ctx, layer, x, y, width, height);\n if (gradient) {\n ctx.fillStyle = gradient;\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n if (hasRadius(borderRadius)) {\n ctx.beginPath();\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n );\n ctx.fill();\n } else {\n ctx.fillRect(x, y, width, height);\n }\n } else {\n // Try url(...) background image\n const urlMatch = layer.match(/url\\([\"']?(.*?)[\"']?\\)/);\n if (urlMatch) {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n if (hasRadius(borderRadius)) {\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n\n const image = await loadImage(urlMatch[1]!);\n const bgSize = style.backgroundSize;\n\n if (bgSize === \"cover\") {\n // Cover fills the box completely — no tiling needed\n const r = computeCover(\n image.width,\n image.height,\n x,\n y,\n width,\n height,\n );\n ctx.drawImage(\n image,\n r.sx,\n r.sy,\n r.sw,\n r.sh,\n r.dx,\n r.dy,\n r.dw,\n r.dh,\n );\n } else {\n // Compute tile dimensions based on backgroundSize\n let tileW: number, tileH: number;\n if (bgSize === \"contain\") {\n const r = computeContain(\n image.width,\n image.height,\n 0,\n 0,\n width,\n height,\n );\n tileW = r.dw;\n tileH = r.dh;\n } else if (bgSize === \"100% 100%\") {\n tileW = width;\n tileH = height;\n } else {\n // CSS default (auto): natural image size\n tileW = image.width;\n tileH = image.height;\n }\n // Tile the image to fill the box (CSS background-repeat: repeat)\n for (let ty = y; ty < y + height; ty += tileH) {\n for (let tx = x; tx < x + width; tx += tileW) {\n ctx.drawImage(image, tx, ty, tileW, tileH);\n }\n }\n }\n }\n }\n }\n }\n\n // Debug: draw bounding boxes\n if (debug) {\n ctx.strokeStyle = \"rgba(255, 0, 0, 0.5)\";\n ctx.lineWidth = 1;\n ctx.strokeRect(x, y, width, height);\n }\n\n // Draw text content\n if (node.textContent !== undefined && node.textContent !== \"\") {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n\n const borderTopW = resolveBoxValue(style.borderTopWidth, width);\n const borderLeftW = resolveBoxValue(style.borderLeftWidth, width);\n const borderRightW = resolveBoxValue(style.borderRightWidth, width);\n\n const contentX = x + paddingLeft + borderLeftW;\n const contentY = y + paddingTop + borderTopW;\n const contentWidth =\n width - paddingLeft - paddingRight - borderLeftW - borderRightW;\n\n const textLayout = layoutText(\n node.textContent,\n style,\n contentWidth,\n ctx,\n !!emojiStyle,\n );\n await drawText(\n ctx,\n textLayout.segments,\n contentX,\n contentY,\n style.textShadow,\n emojiStyle,\n );\n }\n\n // Draw <img> elements\n if (node.type === \"img\" && node.props.src) {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n const paddingBottom = resolveBoxValue(style.paddingBottom, width);\n\n const imgX = x + paddingLeft;\n const imgY = y + paddingTop;\n const imgW = width - paddingLeft - paddingRight;\n const imgH = height - paddingTop - paddingBottom;\n\n // Images are replaced content — borderRadius clips them directly\n // (unlike child content which requires overflow:hidden)\n if (!isClipped) {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n if (hasRadius(borderRadius)) {\n applyClip(ctx, imgX, imgY, imgW, imgH, borderRadius);\n }\n }\n\n await drawImage(\n ctx,\n node.props.src as string | Buffer,\n imgX,\n imgY,\n imgW,\n imgH,\n style,\n node.props.__loadedImage as Image | undefined,\n );\n }\n\n // Draw <svg> containers (handle their own child traversal in SVG coordinate space)\n if (node.type === \"svg\") {\n drawSvgContainer(ctx, node, x, y, width, height);\n } else {\n // Recursively draw children\n // When rendering via offset (offscreen buffer), children use offset 0\n // since x,y already incorporates the offset.\n for (const child of node.children) {\n if (offsetX === 0 && offsetY === 0) {\n await drawNode(ctx, child, x, y, debug, emojiStyle);\n } else {\n await drawNodeCore(\n ctx,\n child,\n x,\n y,\n 0,\n 0,\n debug,\n emojiStyle,\n undefined,\n );\n }\n }\n }\n\n ctx.restore();\n}\n\nfunction applyTransform(\n ctx: SKRSContext2D,\n transform: string,\n x: number,\n y: number,\n width: number,\n height: number,\n transformOrigin?: string,\n): void {\n // Resolve transform-origin (default: center)\n let ox = x + width / 2;\n let oy = y + height / 2;\n\n if (transformOrigin) {\n const parts = transformOrigin.split(/\\s+/);\n ox = resolveOrigin(parts[0], x, width);\n oy = resolveOrigin(parts[1], y, height);\n }\n\n ctx.translate(ox, oy);\n\n // Parse and apply transform functions\n const funcs = transform.matchAll(/(\\w+)\\(([^)]+)\\)/g);\n\n for (const [, name, args] of funcs) {\n const values = args!.split(\",\").map((s) => s.trim());\n\n switch (name) {\n case \"translate\":\n case \"translateX\":\n case \"translateY\": {\n const tx =\n name === \"translateY\" ? 0 : parseCSSLength(values[0]!, width);\n const ty =\n name === \"translateX\"\n ? 0\n : parseCSSLength(\n values[name === \"translate\" ? 1 : 0] ?? \"0\",\n height,\n );\n ctx.translate(tx, ty);\n break;\n }\n case \"scale\":\n case \"scaleX\":\n case \"scaleY\": {\n const sx = name === \"scaleY\" ? 1 : parseFloat(values[0]!);\n const sy =\n name === \"scaleX\"\n ? 1\n : parseFloat(values[name === \"scale\" ? 1 : 0] ?? String(sx));\n ctx.scale(sx, sy);\n break;\n }\n case \"rotate\": {\n const angle = parseAngle(values[0]!);\n ctx.rotate(angle);\n break;\n }\n case \"skewX\": {\n const angle = parseAngle(values[0]!);\n ctx.transform(1, 0, Math.tan(angle), 1, 0, 0);\n break;\n }\n case \"skewY\": {\n const angle = parseAngle(values[0]!);\n ctx.transform(1, Math.tan(angle), 0, 1, 0, 0);\n break;\n }\n }\n }\n\n ctx.translate(-ox, -oy);\n}\n\nfunction resolveOrigin(\n value: string | undefined,\n base: number,\n size: number,\n): number {\n if (!value) return base + size / 2;\n if (value === \"left\" || value === \"top\") return base;\n if (value === \"right\" || value === \"bottom\") return base + size;\n if (value === \"center\") return base + size / 2;\n return base + parseCSSLength(value, size);\n}\n\nfunction parseAngle(value: string): number {\n if (value.endsWith(\"deg\")) return (parseFloat(value) * Math.PI) / 180;\n if (value.endsWith(\"rad\")) return parseFloat(value);\n if (value.endsWith(\"turn\")) return parseFloat(value) * 2 * Math.PI;\n return parseFloat(value);\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\n/**\n * Detect the primary script/language of a text string.\n * Used for font selection and line-breaking behavior.\n */\nexport function detectLanguageCode(text: string): string | undefined {\n for (const char of text) {\n const cp = char.codePointAt(0);\n if (cp === undefined) continue;\n\n // CJK Unified Ideographs\n if (cp >= 0x4e00 && cp <= 0x9fff) return \"zh\";\n // CJK Extension A\n if (cp >= 0x3400 && cp <= 0x4dbf) return \"zh\";\n // Hiragana\n if (cp >= 0x3040 && cp <= 0x309f) return \"ja\";\n // Katakana\n if (cp >= 0x30a0 && cp <= 0x30ff) return \"ja\";\n // Hangul Syllables\n if (cp >= 0xac00 && cp <= 0xd7af) return \"ko\";\n // Hangul Jamo\n if (cp >= 0x1100 && cp <= 0x11ff) return \"ko\";\n // Thai\n if (cp >= 0x0e00 && cp <= 0x0e7f) return \"th\";\n // Arabic\n if (cp >= 0x0600 && cp <= 0x06ff) return \"ar\";\n // Hebrew\n if (cp >= 0x0590 && cp <= 0x05ff) return \"he\";\n // Devanagari\n if (cp >= 0x0900 && cp <= 0x097f) return \"hi\";\n // Bengali\n if (cp >= 0x0980 && cp <= 0x09ff) return \"bn\";\n // Tamil\n if (cp >= 0x0b80 && cp <= 0x0bff) return \"ta\";\n // Telugu\n if (cp >= 0x0c00 && cp <= 0x0c7f) return \"te\";\n // Kannada\n if (cp >= 0x0c80 && cp <= 0x0cff) return \"kn\";\n // Malayalam\n if (cp >= 0x0d00 && cp <= 0x0d7f) return \"ml\";\n }\n\n return undefined;\n}\n\n/**\n * Check if a character is an emoji.\n */\nexport function isEmoji(char: string): boolean {\n const cp = char.codePointAt(0);\n if (cp === undefined) return false;\n\n // Common emoji ranges\n if (cp >= 0x1f600 && cp <= 0x1f64f) return true; // Emoticons\n if (cp >= 0x1f300 && cp <= 0x1f5ff) return true; // Misc Symbols & Pictographs\n if (cp >= 0x1f680 && cp <= 0x1f6ff) return true; // Transport & Map\n if (cp >= 0x1f900 && cp <= 0x1f9ff) return true; // Supplemental Symbols\n if (cp >= 0x2600 && cp <= 0x26ff) return true; // Misc Symbols\n if (cp >= 0x2700 && cp <= 0x27bf) return true; // Dingbats\n if (cp >= 0x2b50 && cp <= 0x2b55) return true; // Misc Symbols & Arrows (star, circle)\n if (cp >= 0x200d && cp <= 0x200d) return true; // Zero Width Joiner\n if (cp >= 0xfe00 && cp <= 0xfe0f) return true; // Variation Selectors\n if (cp >= 0x1fa00 && cp <= 0x1fa6f) return true; // Chess Symbols\n if (cp >= 0x1fa70 && cp <= 0x1faff) return true; // Symbols Extended-A\n if (cp >= 0x231a && cp <= 0x23f3) return true; // Misc Technical (watch, hourglass)\n if (cp >= 0x23e9 && cp <= 0x23fa) return true; // Misc Technical (play, pause)\n if (cp >= 0x25aa && cp <= 0x25fe) return true; // Geometric Shapes\n if (cp >= 0x2934 && cp <= 0x2935) return true; // Arrows\n if (cp >= 0x2b05 && cp <= 0x2b07) return true; // Arrows\n if (cp >= 0x3030 && cp <= 0x3030) return true; // Wavy dash\n if (cp >= 0x303d && cp <= 0x303d) return true; // Part alternation mark\n if (cp >= 0x3297 && cp <= 0x3299) return true; // CJK symbols\n\n return false;\n}\n","import LineBreaker from \"linebreak\";\n\nexport type BreakOpportunity = {\n position: number;\n required: boolean;\n};\n\n/**\n * Find line-break opportunities in text using UAX #14 algorithm.\n *\n * @param text - The text to analyze\n * @returns Array of break opportunities with positions and whether they're required (hard breaks)\n */\nexport function findBreakOpportunities(text: string): BreakOpportunity[] {\n const breaker = new LineBreaker(text);\n const opportunities: BreakOpportunity[] = [];\n\n let bk = breaker.nextBreak();\n while (bk) {\n opportunities.push({\n position: bk.position,\n required: bk.required ?? false,\n });\n bk = breaker.nextBreak();\n }\n\n return opportunities;\n}\n","import { createCanvas } from \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\n\nexport type TextMetrics = {\n width: number;\n ascent: number;\n descent: number;\n height: number;\n};\n\n// Scratch canvas for text measurement when no ctx is available\nlet scratchCtx: SKRSContext2D | null = null;\n\nfunction getScratchCtx(): SKRSContext2D {\n if (!scratchCtx) {\n scratchCtx = createCanvas(1, 1).getContext(\"2d\");\n }\n return scratchCtx;\n}\n\nconst GENERIC_FAMILIES = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"math\",\n \"emoji\",\n \"fangsong\",\n]);\n\nfunction quoteFontFamily(family: string): string {\n if (!family || GENERIC_FAMILIES.has(family)) return family;\n return `\"${family}\"`;\n}\n\n/**\n * Set font properties on a canvas context for measurement.\n */\nexport function setFont(\n ctx: SKRSContext2D,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n): void {\n const quoted = fontFamily\n .split(\",\")\n .map((f) => quoteFontFamily(f.trim()))\n .join(\", \");\n ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${quoted}`;\n}\n\n/**\n * Measure text using the canvas ctx.measureText() API.\n * Returns width, ascent, descent, and total height.\n */\nexport function measureText(\n text: string,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n ctx?: SKRSContext2D,\n): TextMetrics {\n const c = ctx ?? getScratchCtx();\n setFont(c, fontSize, fontFamily, fontWeight, fontStyle);\n\n const m = c.measureText(text);\n\n const ascent =\n m.fontBoundingBoxAscent ?? m.actualBoundingBoxAscent ?? fontSize * 0.8;\n const descent =\n m.fontBoundingBoxDescent ?? m.actualBoundingBoxDescent ?? fontSize * 0.2;\n\n return {\n width: m.width,\n ascent,\n descent,\n height: ascent + descent,\n };\n}\n\n/**\n * Measure how many pixels to trim from the top (overTrim) and bottom\n * (underTrim) of a line box based on `text-box-edge` keywords.\n *\n * The trim amount is the difference between the full line-height half-leading\n * and the target metric for each edge.\n */\nexport function measureTrimMetrics(\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n lineHeight: number,\n edge: string,\n ctx?: SKRSContext2D,\n): { overTrim: number; underTrim: number } {\n const c = ctx ?? getScratchCtx();\n setFont(c, fontSize, fontFamily, fontWeight, fontStyle);\n\n const refMetrics = c.measureText(\"M\");\n const fontAscent =\n refMetrics.fontBoundingBoxAscent ??\n refMetrics.actualBoundingBoxAscent ??\n fontSize * 0.8;\n const fontDescent =\n refMetrics.fontBoundingBoxDescent ??\n refMetrics.actualBoundingBoxDescent ??\n fontSize * 0.2;\n\n // Parse edge into over-edge and under-edge keywords\n const parts = edge.trim().split(/\\s+/);\n const overEdge = parts[0] ?? \"text\";\n const underEdge = parts.length > 1 ? parts[1]! : overEdge;\n\n // Resolve over-edge keyword → target ascent\n let targetAscent: number;\n switch (overEdge) {\n case \"cap\": {\n const capMetrics = c.measureText(\"H\");\n targetAscent = capMetrics.actualBoundingBoxAscent ?? fontSize * 0.7;\n break;\n }\n case \"ex\": {\n const exMetrics = c.measureText(\"x\");\n targetAscent = exMetrics.actualBoundingBoxAscent ?? fontSize * 0.5;\n break;\n }\n case \"ideographic\":\n case \"ideographic-ink\":\n case \"text\":\n default:\n targetAscent = fontAscent;\n break;\n }\n\n // Resolve under-edge keyword → target descent\n let targetDescent: number;\n switch (underEdge) {\n case \"alphabetic\":\n targetDescent = 0;\n break;\n case \"ideographic\":\n case \"ideographic-ink\":\n case \"text\":\n default:\n targetDescent = fontDescent;\n break;\n }\n\n const halfLeading = (lineHeight - (fontAscent + fontDescent)) / 2;\n const overTrim = halfLeading + (fontAscent - targetAscent);\n const underTrim = halfLeading + (fontDescent - targetDescent);\n\n return {\n overTrim: Math.max(0, overTrim),\n underTrim: Math.max(0, underTrim),\n };\n}\n\n/**\n * Measure the width of a single word.\n */\nexport function measureWord(\n word: string,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n): number {\n const base = measureText(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n ).width;\n if (letterSpacing === 0 || word.length === 0) return base;\n return base + letterSpacing * word.length;\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { isEmoji } from \"../language.ts\";\nimport { findBreakOpportunities } from \"./linebreak.ts\";\nimport { measureText, measureTrimMetrics, measureWord } from \"./measure.ts\";\nimport type { TextMetrics } from \"./measure.ts\";\n\nexport type TextSegment = {\n text: string;\n x: number;\n y: number;\n width: number;\n height: number;\n fontSize: number;\n fontFamily: string;\n fontWeight: number | string;\n fontStyle: string;\n color: string;\n ascent: number;\n textDecoration?: string;\n letterSpacing: number;\n lineIndex: number;\n};\n\nexport type TextLayoutResult = {\n segments: TextSegment[];\n width: number;\n height: number;\n};\n\n/**\n * Measure the width of a word, accounting for emoji characters when enabled.\n * Emoji characters are treated as square images sized to fontSize.\n */\nfunction emojiAwareMeasureWord(\n word: string,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n): number {\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n let totalWidth = 0;\n let textBuffer = \"\";\n\n for (const { segment } of segmenter.segment(word)) {\n let isEmojiSegment = false;\n for (const char of segment) {\n if (isEmoji(char)) {\n isEmojiSegment = true;\n break;\n }\n }\n\n if (isEmojiSegment) {\n if (textBuffer) {\n totalWidth += measureWord(\n textBuffer,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n textBuffer = \"\";\n }\n totalWidth += fontSize;\n } else {\n textBuffer += segment;\n }\n }\n\n if (textBuffer) {\n totalWidth += measureWord(\n textBuffer,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n }\n\n return totalWidth;\n}\n\n/**\n * Lay out text content into positioned segments with line-breaking.\n *\n * @param text - The text to lay out\n * @param style - Computed style\n * @param maxWidth - Maximum width for wrapping\n * @param ctx - Canvas context for measurement\n * @param emojiEnabled - Whether to use emoji-aware measurement\n * @returns Text segments with positions and total dimensions\n */\nexport function layoutText(\n text: string,\n style: ComputedStyle,\n maxWidth: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n): TextLayoutResult {\n const fontSize = style.fontSize ?? 16;\n const fontFamily = style.fontFamily ?? \"sans-serif\";\n const fontWeight = style.fontWeight ?? 400;\n const fontStyle = style.fontStyle ?? \"normal\";\n const color = style.color ?? \"black\";\n const textAlign = style.textAlign ?? \"left\";\n // Measure reference metrics for \"normal\" lineHeight (font ascent + descent)\n const refMetrics = measureText(\n \"M\",\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n );\n const lineHeightPx = resolveLineHeight(\n style.lineHeight,\n fontSize,\n refMetrics,\n );\n const letterSpacing =\n typeof style.letterSpacing === \"number\" ? style.letterSpacing : 0;\n const whiteSpace = style.whiteSpace ?? \"normal\";\n const wordBreak = style.wordBreak ?? \"normal\";\n const textOverflow = style.textOverflow ?? \"clip\";\n const textDecoration = style.textDecoration;\n\n // Choose measurement function based on emoji mode\n const measure = emojiEnabled\n ? (word: string, ls?: number) =>\n emojiAwareMeasureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n ls ?? letterSpacing,\n )\n : (word: string, ls?: number) =>\n measureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n ls ?? letterSpacing,\n );\n\n // Apply text transform\n let processedText = text;\n if (style.textTransform === \"uppercase\") {\n processedText = text.toUpperCase();\n } else if (style.textTransform === \"lowercase\") {\n processedText = text.toLowerCase();\n } else if (style.textTransform === \"capitalize\") {\n processedText = text.replace(/\\b\\w/g, (c) => c.toUpperCase());\n }\n\n const noWrap = whiteSpace === \"nowrap\" || whiteSpace === \"pre\";\n\n // Split by explicit newlines\n const paragraphs = processedText.split(\"\\n\");\n\n const lines: string[] = [];\n\n for (const paragraph of paragraphs) {\n if (noWrap) {\n lines.push(paragraph);\n continue;\n }\n\n // Wrap text\n const wrapped = wrapText(\n paragraph,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n letterSpacing,\n wordBreak,\n ctx,\n measure,\n );\n lines.push(...wrapped);\n }\n\n // Handle text-overflow: ellipsis\n if (textOverflow === \"ellipsis\" && noWrap && lines.length === 1) {\n const line = lines[0]!;\n const lineWidth = measure(line);\n if (lineWidth > maxWidth) {\n lines[0] = truncateWithEllipsis(\n line,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n }\n }\n\n // Create positioned segments\n const segments: TextSegment[] = [];\n let totalHeight = 0;\n let maxLineWidth = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const lineWidth = measure(line);\n\n let x = 0;\n if (textAlign === \"center\") {\n x = (maxWidth - lineWidth) / 2;\n } else if (textAlign === \"right\") {\n x = maxWidth - lineWidth;\n }\n\n const metrics = measureText(\n line || \"M\",\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n );\n\n segments.push({\n text: line,\n x,\n y: totalHeight + (lineHeightPx + metrics.ascent - metrics.descent) / 2,\n width: lineWidth,\n height: lineHeightPx,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n color,\n ascent: metrics.ascent,\n textDecoration,\n letterSpacing,\n lineIndex: i,\n });\n\n totalHeight += lineHeightPx;\n maxLineWidth = Math.max(maxLineWidth, lineWidth);\n }\n\n // Apply text-box-trim\n const textBoxTrim = style.textBoxTrim;\n if (textBoxTrim && textBoxTrim !== \"none\" && segments.length > 0) {\n const textBoxEdge = style.textBoxEdge ?? \"text\";\n const trimMetrics = measureTrimMetrics(\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n lineHeightPx,\n textBoxEdge,\n ctx,\n );\n\n if (textBoxTrim === \"trim-start\" || textBoxTrim === \"trim-both\") {\n for (const seg of segments) {\n seg.y -= trimMetrics.overTrim;\n }\n totalHeight -= trimMetrics.overTrim;\n }\n\n if (textBoxTrim === \"trim-end\" || textBoxTrim === \"trim-both\") {\n totalHeight -= trimMetrics.underTrim;\n }\n }\n\n return {\n segments,\n width: maxLineWidth,\n height: totalHeight,\n };\n}\n\nfunction resolveLineHeight(\n lineHeight: number | string | undefined,\n fontSize: number,\n metrics?: TextMetrics,\n): number {\n if (lineHeight === undefined || lineHeight === \"normal\") {\n // CSS \"normal\": use font ascent + descent (matches satori behaviour)\n return metrics ? metrics.ascent + metrics.descent : fontSize * 1.2;\n }\n if (typeof lineHeight === \"number\") {\n // Already resolved to px in compute.ts if > 5, else multiplier\n return lineHeight > 5 ? lineHeight : lineHeight * fontSize;\n }\n const parsed = parseFloat(String(lineHeight));\n return isNaN(parsed) ? fontSize * 1.2 : parsed;\n}\n\nfunction wrapText(\n text: string,\n maxWidth: number,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n letterSpacing: number,\n wordBreak: string,\n ctx?: SKRSContext2D,\n measureFn?: (word: string, ls?: number) => number,\n): string[] {\n if (!text) return [\"\"];\n\n const mw =\n measureFn ??\n ((word: string) =>\n measureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n ));\n\n const breakOpps = findBreakOpportunities(text);\n const lines: string[] = [];\n let lineStart = 0;\n let lastBreak = 0;\n\n for (const opp of breakOpps) {\n const segment = text.slice(lineStart, opp.position);\n const segWidth = mw(segment);\n\n if (segWidth > maxWidth && lastBreak > lineStart) {\n // Line overflows — break at last opportunity\n const line = text.slice(lineStart, lastBreak).replace(/\\s+$/, \"\");\n lines.push(line);\n lineStart = lastBreak;\n } else if (segWidth > maxWidth && wordBreak === \"break-all\") {\n // Force break within word\n const broken = forceBreakWord(\n text,\n lineStart,\n opp.position,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n measureFn,\n );\n lines.push(...broken.lines);\n lineStart = broken.endPos;\n }\n\n if (opp.required) {\n // Hard break (newline)\n const line = text.slice(lineStart, opp.position).replace(/\\s+$/, \"\");\n lines.push(line);\n lineStart = opp.position;\n }\n\n lastBreak = opp.position;\n }\n\n // Remaining text\n if (lineStart < text.length) {\n const remaining = text.slice(lineStart).replace(/\\s+$/, \"\");\n if (remaining) {\n const remWidth = mw(remaining);\n if (remWidth > maxWidth && wordBreak === \"break-all\") {\n const broken = forceBreakWord(\n text,\n lineStart,\n text.length,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n measureFn,\n );\n lines.push(...broken.lines);\n } else {\n lines.push(remaining);\n }\n }\n }\n\n return lines.length > 0 ? lines : [\"\"];\n}\n\nfunction forceBreakWord(\n text: string,\n start: number,\n end: number,\n maxWidth: number,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n measureFn?: (word: string, ls?: number) => number,\n): { lines: string[]; endPos: number } {\n const mw =\n measureFn ??\n ((word: string) =>\n measureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n ));\n const lines: string[] = [];\n let pos = start;\n\n while (pos < end) {\n let breakPos = pos + 1;\n while (breakPos < end) {\n const chunk = text.slice(pos, breakPos + 1);\n const w = mw(chunk);\n if (w > maxWidth) break;\n breakPos++;\n }\n\n const line = text.slice(pos, breakPos);\n if (line.trim()) lines.push(line);\n pos = breakPos;\n }\n\n return { lines, endPos: end };\n}\n\nfunction truncateWithEllipsis(\n text: string,\n maxWidth: number,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n): string {\n const ellipsis = \"\\u2026\";\n const ellipsisWidth = measureWord(\n ellipsis,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n const availWidth = maxWidth - ellipsisWidth;\n\n for (let i = text.length - 1; i > 0; i--) {\n const truncated = text.slice(0, i);\n const w = measureWord(\n truncated,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n if (w <= availWidth) {\n return truncated + ellipsis;\n }\n }\n\n return ellipsis;\n}\n\n/**\n * Yoga-compatible measure function for text nodes.\n * Returns the dimensions needed for the text content.\n */\nexport function createTextMeasureFunc(\n text: string,\n style: ComputedStyle,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n) {\n // Strip textOverflow during measurement so ellipsis truncation doesn't\n // shrink the reported width below the Yoga constraint. The draw phase\n // still uses the original style (with textOverflow) for rendering.\n const measureStyle = { ...style, textOverflow: \"clip\" as const };\n return (\n width: number,\n _widthMode: number,\n _height: number,\n _heightMode: number,\n ) => {\n const maxWidth = width > 0 ? width : Infinity;\n const result = layoutText(text, measureStyle, maxWidth, ctx, emojiEnabled);\n // When text wraps to multiple lines, return the constraint width (like CSS\n // block layout). This ensures the draw phase re-layout gets the same\n // maxWidth and produces identical line-breaking. Without this, the\n // measured content width (widest trimmed line) can be narrower than what\n // the wrapping algorithm needs (it checks untrimmed segments), causing the\n // draw phase to wrap differently.\n const wrapped = result.segments.length > 1;\n const reportedWidth = wrapped\n ? Math.min(maxWidth, width > 0 ? width : result.width)\n : result.width;\n return { width: Math.min(reportedWidth, maxWidth), height: result.height };\n };\n}\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\n\n/**\n * Apply overflow:hidden clipping to a canvas context.\n * Creates a rectangular clip path with optional border-radius.\n */\nexport function applyClip(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n borderRadius?: {\n topLeft: number;\n topRight: number;\n bottomRight: number;\n bottomLeft: number;\n },\n): void {\n ctx.beginPath();\n\n if (borderRadius && hasRadius(borderRadius)) {\n const { topLeft, topRight, bottomRight, bottomLeft } = borderRadius;\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n topLeft,\n topRight,\n bottomRight,\n bottomLeft,\n );\n } else {\n ctx.rect(x, y, width, height);\n }\n\n ctx.clip();\n}\n\n/**\n * Draw a rounded rectangle path on the context.\n */\nexport function roundedRect(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n tl: number,\n tr: number,\n br: number,\n bl: number,\n): void {\n // Clamp radii to half the smallest dimension\n const maxR = Math.min(w, h) / 2;\n tl = Math.min(tl, maxR);\n tr = Math.min(tr, maxR);\n br = Math.min(br, maxR);\n bl = Math.min(bl, maxR);\n\n ctx.moveTo(x + tl, y);\n ctx.lineTo(x + w - tr, y);\n if (tr > 0) ctx.arcTo(x + w, y, x + w, y + tr, tr);\n ctx.lineTo(x + w, y + h - br);\n if (br > 0) ctx.arcTo(x + w, y + h, x + w - br, y + h, br);\n ctx.lineTo(x + bl, y + h);\n if (bl > 0) ctx.arcTo(x, y + h, x, y + h - bl, bl);\n ctx.lineTo(x, y + tl);\n if (tl > 0) ctx.arcTo(x, y, x + tl, y, tl);\n ctx.closePath();\n}\n\nexport function hasRadius(r: {\n topLeft: number;\n topRight: number;\n bottomRight: number;\n bottomLeft: number;\n}): boolean {\n return (\n r.topLeft > 0 || r.topRight > 0 || r.bottomRight > 0 || r.bottomLeft > 0\n );\n}\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\n\n/**\n * Parse and create a canvas gradient from a CSS gradient string.\n * Supports linear-gradient and radial-gradient.\n *\n * @returns A CanvasGradient or null if parsing fails\n */\nexport function createGradientFromCSS(\n ctx: SKRSContext2D,\n cssGradient: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n const trimmed = cssGradient.trim();\n\n if (trimmed.startsWith(\"linear-gradient\")) {\n return parseLinearGradient(ctx, trimmed, x, y, width, height);\n }\n\n if (trimmed.startsWith(\"radial-gradient\")) {\n return parseRadialGradient(ctx, trimmed, x, y, width, height);\n }\n\n return null;\n}\n\nfunction parseLinearGradient(\n ctx: SKRSContext2D,\n css: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n // Extract content between parentheses\n const match = css.match(/linear-gradient\\((.*)\\)/s);\n if (!match) return null;\n\n const content = match[1]!.trim();\n const parts = splitGradientArgs(content);\n\n let angle = 180; // default: to bottom\n let colorStartIdx = 0;\n\n // Parse direction\n const first = parts[0]?.trim();\n if (first) {\n if (first.startsWith(\"to \")) {\n angle = directionToAngle(first);\n colorStartIdx = 1;\n } else if (first.endsWith(\"deg\")) {\n angle = parseFloat(first);\n colorStartIdx = 1;\n } else if (first.endsWith(\"turn\")) {\n angle = parseFloat(first) * 360;\n colorStartIdx = 1;\n }\n }\n\n // Calculate gradient line endpoints\n const rad = ((angle - 90) * Math.PI) / 180;\n const cx = x + width / 2;\n const cy = y + height / 2;\n const halfDiag =\n Math.abs(width * Math.cos(rad)) / 2 + Math.abs(height * Math.sin(rad)) / 2;\n\n const x0 = cx - halfDiag * Math.cos(rad);\n const y0 = cy - halfDiag * Math.sin(rad);\n const x1 = cx + halfDiag * Math.cos(rad);\n const y1 = cy + halfDiag * Math.sin(rad);\n\n const gradient = ctx.createLinearGradient(x0, y0, x1, y1);\n\n // Parse color stops\n const stops = parts.slice(colorStartIdx);\n addColorStops(gradient, stops);\n\n return gradient;\n}\n\nfunction parseRadialGradient(\n ctx: SKRSContext2D,\n css: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n const match = css.match(/radial-gradient\\((.*)\\)/s);\n if (!match) return null;\n\n const content = match[1]!.trim();\n const parts = splitGradientArgs(content);\n\n const cx = x + width / 2;\n const cy = y + height / 2;\n const radius = Math.max(width, height) / 2;\n\n const gradient = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius);\n\n // Simple parsing: skip shape/size/position, just get color stops\n let colorStartIdx = 0;\n const first = parts[0]?.trim() ?? \"\";\n if (\n first.startsWith(\"circle\") ||\n first.startsWith(\"ellipse\") ||\n first.startsWith(\"closest\") ||\n first.startsWith(\"farthest\")\n ) {\n colorStartIdx = 1;\n }\n\n addColorStops(gradient, parts.slice(colorStartIdx));\n\n return gradient;\n}\n\nfunction addColorStops(gradient: CanvasGradient, stops: string[]): void {\n if (stops.length === 0) return;\n\n for (let i = 0; i < stops.length; i++) {\n const stop = stops[i]!.trim();\n const percentMatch = stop.match(/^(.+?)\\s+(\\d+(?:\\.\\d+)?%?)$/);\n\n if (percentMatch) {\n const color = percentMatch[1]!;\n const pos = percentMatch[2]!;\n const offset = pos.endsWith(\"%\")\n ? parseFloat(pos) / 100\n : parseFloat(pos);\n gradient.addColorStop(Math.max(0, Math.min(1, offset)), color);\n } else {\n // Auto-distribute\n const offset = stops.length === 1 ? 0.5 : i / (stops.length - 1);\n gradient.addColorStop(offset, stop);\n }\n }\n}\n\nfunction directionToAngle(dir: string): number {\n const map: Record<string, number> = {\n \"to top\": 0,\n \"to right\": 90,\n \"to bottom\": 180,\n \"to left\": 270,\n \"to top right\": 45,\n \"to top left\": 315,\n \"to bottom right\": 135,\n \"to bottom left\": 225,\n };\n return map[dir] ?? 180;\n}\n\nexport function splitGradientArgs(content: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let parenDepth = 0;\n\n for (const char of content) {\n if (char === \"(\") parenDepth++;\n if (char === \")\") parenDepth--;\n if (char === \",\" && parenDepth === 0) {\n parts.push(current);\n current = \"\";\n } else {\n current += char;\n }\n }\n if (current.trim()) parts.push(current);\n\n return parts;\n}\n","import { loadImage } from \"@napi-rs/canvas\";\nimport type { Image, SKRSContext2D } from \"@napi-rs/canvas\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\n\n/**\n * Draw an image element onto the canvas.\n *\n * @param ctx - Canvas rendering context\n * @param src - Image source (URL, file path, or Buffer)\n * @param x - X position\n * @param y - Y position\n * @param width - Target width\n * @param height - Target height\n * @param style - Computed style (for objectFit)\n */\nexport async function drawImage(\n ctx: SKRSContext2D,\n src: string | Buffer,\n x: number,\n y: number,\n width: number,\n height: number,\n style?: ComputedStyle,\n preloadedImage?: Image,\n): Promise<void> {\n const image = preloadedImage ?? (await loadImage(src));\n const objectFit = style?.objectFit ?? \"fill\";\n\n if (objectFit === \"fill\") {\n ctx.drawImage(image, x, y, width, height);\n return;\n }\n\n const imgW = image.width;\n const imgH = image.height;\n\n if (objectFit === \"contain\") {\n const r = computeContain(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.dx, r.dy, r.dw, r.dh);\n } else if (objectFit === \"cover\") {\n const r = computeCover(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.sx, r.sy, r.sw, r.sh, r.dx, r.dy, r.dw, r.dh);\n } else if (objectFit === \"none\") {\n const dx = x + (width - imgW) / 2;\n const dy = y + (height - imgH) / 2;\n ctx.drawImage(image, dx, dy);\n } else if (objectFit === \"scale-down\") {\n if (imgW <= width && imgH <= height) {\n const dx = x + (width - imgW) / 2;\n const dy = y + (height - imgH) / 2;\n ctx.drawImage(image, dx, dy);\n } else {\n const r = computeContain(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.dx, r.dy, r.dw, r.dh);\n }\n }\n}\n","/**\n * Shared cover/contain sizing logic used by both `<img>` objectFit\n * and `backgroundImage` + `backgroundSize`.\n */\n\nexport interface FitRect {\n sx: number;\n sy: number;\n sw: number;\n sh: number;\n dx: number;\n dy: number;\n dw: number;\n dh: number;\n}\n\n/**\n * Compute source and destination rectangles for \"cover\" sizing.\n * The image fills the box completely, cropping the excess.\n */\nexport function computeCover(\n imgW: number,\n imgH: number,\n boxX: number,\n boxY: number,\n boxW: number,\n boxH: number,\n): FitRect {\n const imgRatio = imgW / imgH;\n const boxRatio = boxW / boxH;\n\n let sx: number, sy: number, sw: number, sh: number;\n\n if (imgRatio > boxRatio) {\n sh = imgH;\n sw = imgH * boxRatio;\n sx = (imgW - sw) / 2;\n sy = 0;\n } else {\n sw = imgW;\n sh = imgW / boxRatio;\n sx = 0;\n sy = (imgH - sh) / 2;\n }\n\n return { sx, sy, sw, sh, dx: boxX, dy: boxY, dw: boxW, dh: boxH };\n}\n\n/**\n * Compute destination rectangle for \"contain\" sizing.\n * The image fits entirely within the box, centered, with no cropping.\n */\nexport function computeContain(\n imgW: number,\n imgH: number,\n boxX: number,\n boxY: number,\n boxW: number,\n boxH: number,\n): FitRect {\n const imgRatio = imgW / imgH;\n const boxRatio = boxW / boxH;\n\n let dw: number, dh: number;\n\n if (imgRatio > boxRatio) {\n dw = boxW;\n dh = boxW / imgRatio;\n } else {\n dh = boxH;\n dw = boxH * imgRatio;\n }\n\n const dx = boxX + (boxW - dw) / 2;\n const dy = boxY + (boxH - dh) / 2;\n\n return { sx: 0, sy: 0, sw: imgW, sh: imgH, dx, dy, dw, dh };\n}\n","/**\n * Shared CSS utility functions used by the draw system.\n */\n\nexport function parseCSSLength(value: string, referenceSize: number): number {\n if (value.endsWith(\"%\")) return (parseFloat(value) / 100) * referenceSize;\n return parseFloat(value);\n}\n\nexport function toNumber(v: unknown): number {\n if (typeof v === \"number\") return v;\n if (v === undefined || v === null) return 0;\n const n = parseFloat(String(v));\n return isNaN(n) ? 0 : n;\n}\n\n/**\n * Resolve a box-model value (padding, border-width) that may be a percentage.\n * Per CSS spec, percentage padding/border resolves against the element's width\n * (even for top/bottom).\n */\nexport function resolveBoxValue(v: unknown, referenceWidth: number): number {\n if (typeof v === \"number\") return v;\n if (v === undefined || v === null) return 0;\n const s = String(v);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * referenceWidth;\n const n = parseFloat(s);\n return isNaN(n) ? 0 : n;\n}\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { hasRadius, roundedRect } from \"./clip.ts\";\nimport { parseCSSLength, toNumber, resolveBoxValue } from \"./utils.ts\";\n\n/**\n * Draw the background, borders, and box-shadow for a rectangular element.\n */\nexport function drawRect(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n style: ComputedStyle,\n): void {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n const hasRoundedCorners = hasRadius(borderRadius);\n\n // Box shadow (drawn before background)\n if (style.boxShadow) {\n drawBoxShadow(ctx, x, y, width, height, style.boxShadow, borderRadius);\n }\n\n // Background\n if (style.backgroundColor) {\n ctx.fillStyle = style.backgroundColor;\n\n if (hasRoundedCorners) {\n ctx.beginPath();\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n );\n ctx.fill();\n } else {\n ctx.fillRect(x, y, width, height);\n }\n }\n\n // Borders\n drawBorders(ctx, x, y, width, height, style, borderRadius);\n}\n\nfunction resolveRadius(v: unknown, width: number, height: number): number {\n if (typeof v === \"string\") return parseCSSLength(v, Math.min(width, height));\n return toNumber(v);\n}\n\nexport function getBorderRadiusFromStyle(\n style: ComputedStyle,\n width: number,\n height: number,\n) {\n return {\n topLeft: resolveRadius(style.borderTopLeftRadius, width, height),\n topRight: resolveRadius(style.borderTopRightRadius, width, height),\n bottomRight: resolveRadius(style.borderBottomRightRadius, width, height),\n bottomLeft: resolveRadius(style.borderBottomLeftRadius, width, height),\n };\n}\n\nfunction drawBorders(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n style: ComputedStyle,\n borderRadius: ReturnType<typeof getBorderRadiusFromStyle>,\n): void {\n const hasRoundedCorners = hasRadius(borderRadius);\n\n // If all borders are the same, draw as a single stroke\n const tw = resolveBoxValue(style.borderTopWidth, width);\n const rw = resolveBoxValue(style.borderRightWidth, width);\n const bw = resolveBoxValue(style.borderBottomWidth, width);\n const lw = resolveBoxValue(style.borderLeftWidth, width);\n\n if (tw === 0 && rw === 0 && bw === 0 && lw === 0) return;\n\n const allSameWidth = tw === rw && rw === bw && bw === lw && tw > 0;\n const tc = style.borderTopColor ?? \"black\";\n const rc = style.borderRightColor ?? \"black\";\n const bc = style.borderBottomColor ?? \"black\";\n const lc = style.borderLeftColor ?? \"black\";\n const allSameColor = tc === rc && rc === bc && bc === lc;\n\n if (allSameWidth && allSameColor) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n\n if (hasRoundedCorners) {\n ctx.beginPath();\n const half = tw / 2;\n roundedRect(\n ctx,\n x + half,\n y + half,\n width - tw,\n height - tw,\n Math.max(0, borderRadius.topLeft - half),\n Math.max(0, borderRadius.topRight - half),\n Math.max(0, borderRadius.bottomRight - half),\n Math.max(0, borderRadius.bottomLeft - half),\n );\n ctx.stroke();\n } else {\n ctx.strokeRect(x + tw / 2, y + tw / 2, width - tw, height - tw);\n }\n return;\n }\n\n // Draw individual borders\n if (tw > 0) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n ctx.beginPath();\n ctx.moveTo(x, y + tw / 2);\n ctx.lineTo(x + width, y + tw / 2);\n ctx.stroke();\n }\n if (rw > 0) {\n ctx.strokeStyle = rc;\n ctx.lineWidth = rw;\n ctx.beginPath();\n ctx.moveTo(x + width - rw / 2, y);\n ctx.lineTo(x + width - rw / 2, y + height);\n ctx.stroke();\n }\n if (bw > 0) {\n ctx.strokeStyle = bc;\n ctx.lineWidth = bw;\n ctx.beginPath();\n ctx.moveTo(x, y + height - bw / 2);\n ctx.lineTo(x + width, y + height - bw / 2);\n ctx.stroke();\n }\n if (lw > 0) {\n ctx.strokeStyle = lc;\n ctx.lineWidth = lw;\n ctx.beginPath();\n ctx.moveTo(x + lw / 2, y);\n ctx.lineTo(x + lw / 2, y + height);\n ctx.stroke();\n }\n}\n\nfunction drawBoxShadow(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n boxShadow: string,\n borderRadius: ReturnType<typeof getBorderRadiusFromStyle>,\n): void {\n // Parse simple box-shadow: offsetX offsetY blur spread? color\n const parts = boxShadow.match(\n /(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?(?:\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?)?\\s+(.*)/,\n );\n if (!parts) return;\n\n const offsetX = parseFloat(parts[1]!);\n const offsetY = parseFloat(parts[2]!);\n const blur = parseFloat(parts[3]!);\n const color = parts[5]!.trim();\n\n const radii = [\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n ];\n\n // Clip to area OUTSIDE the element so shadow renders but inner fill is hidden\n const margin = blur * 2 + Math.abs(offsetX) + Math.abs(offsetY);\n ctx.save();\n ctx.beginPath();\n ctx.rect(x - margin, y - margin, width + margin * 2, height + margin * 2);\n ctx.roundRect(x, y, width, height, radii);\n ctx.clip(\"evenodd\");\n\n // Use CSS filter blur (sigma = blur/2) instead of the canvas shadow API\n // because it matches SVG feGaussianBlur (used by satori) much more closely.\n ctx.filter = `blur(${blur / 2}px)`;\n ctx.translate(offsetX, offsetY);\n ctx.fillStyle = color;\n ctx.beginPath();\n ctx.roundRect(x, y, width, height, radii);\n ctx.fill();\n ctx.restore();\n}\n","import { Path2D } from \"@napi-rs/canvas\";\nimport type {\n CanvasGradient,\n DOMMatrix2DInit,\n SKRSContext2D,\n} from \"@napi-rs/canvas\";\n\nimport type { LayoutNode } from \"../layout.ts\";\n\ntype SvgChild = {\n type: string;\n props: Record<string, unknown>;\n children?: SvgChild | SvgChild[];\n};\n\ntype BBox = { x: number; y: number; width: number; height: number };\n\n/** Collected `<defs>` definitions: clip paths and gradients. */\ntype SvgDefs = {\n clips: Map<string, SvgChild[]>;\n gradients: Map<string, SvgChild>;\n};\n\n/** Replace `\"currentColor\"` with the inherited CSS `color` value. */\nfunction resolveCurrentColor(\n value: string | undefined,\n color: string,\n): string | undefined {\n if (value?.toLowerCase() === \"currentcolor\") return color;\n return value;\n}\n\n/**\n * Merge SVG presentation properties from `props.style` into the props object.\n * Style values win over direct props, matching browser CSS specificity rules.\n */\nfunction mergeStyleIntoProps(\n props: Record<string, unknown>,\n): Record<string, unknown> {\n const style = props.style as Record<string, unknown> | undefined;\n if (!style) return props;\n return { ...props, ...style };\n}\n\n/**\n * Collect `<clipPath>` and gradient definitions from `<defs>` elements.\n */\nfunction collectDefs(children: SvgChild[]): SvgDefs {\n const clips = new Map<string, SvgChild[]>();\n const gradients = new Map<string, SvgChild>();\n for (const child of children) {\n if (child.type !== \"defs\") continue;\n for (const def of normalizeChildren(child)) {\n const id = def.props.id as string | undefined;\n if (!id) continue;\n if (def.type === \"clipPath\") clips.set(id, normalizeChildren(def));\n else if (def.type === \"radialGradient\" || def.type === \"linearGradient\")\n gradients.set(id, def);\n }\n }\n return { clips, gradients };\n}\n\n/** Parse `url(#id)` references and return the id, or undefined. */\nfunction parseUrlRef(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const m = value.match(/^url\\(#(.+)\\)$/);\n return m?.[1];\n}\n\n/** Normalize children from either `.children` or `.props.children` into an array. */\nfunction normalizeChildren(node: SvgChild): SvgChild[] {\n const raw =\n node.children ?? (node.props.children as SvgChild | SvgChild[] | undefined);\n if (raw == null) return [];\n return Array.isArray(raw) ? raw : [raw];\n}\n\n// ---------------------------------------------------------------------------\n// Gradient helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Parse an SVG length value, resolving percentages against a reference dimension.\n * Unlike `parseFrac`, this returns absolute coordinates (not 0–1 fractions).\n */\nfunction svgLength(value: unknown, reference: number, fallback = 0): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * reference;\n const n = Number(s);\n return isNaN(n) ? fallback : n;\n}\n\n/** Parse a gradient coordinate percentage/fraction to a 0–1 value. */\nfunction parseFrac(value: unknown, fallback: number): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return parseFloat(s) / 100;\n return Number(s);\n}\n\n/** Apply opacity to a CSS color string. */\nfunction applyOpacity(color: string, opacity: number): string {\n if (opacity >= 1) return color;\n const m = color.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);\n if (m)\n return `rgba(${parseInt(m[1]!, 16)}, ${parseInt(m[2]!, 16)}, ${parseInt(m[3]!, 16)}, ${opacity})`;\n return color;\n}\n\n/** Add color stops from SVG `<stop>` children to a canvas gradient. */\nfunction addGradientStops(gradient: CanvasGradient, def: SvgChild): void {\n for (const stop of normalizeChildren(def)) {\n if (stop.type !== \"stop\") continue;\n const sp = stop.props;\n const offsetRaw = (sp.offset as string | number) ?? 0;\n const offset =\n typeof offsetRaw === \"string\" && offsetRaw.endsWith(\"%\")\n ? parseFloat(offsetRaw) / 100\n : Number(offsetRaw);\n const stopColor =\n ((sp.stopColor ?? sp[\"stop-color\"]) as string | undefined) ?? \"black\";\n const stopOpacity = Number(sp.stopOpacity ?? sp[\"stop-opacity\"] ?? 1);\n gradient.addColorStop(offset, applyOpacity(stopColor, stopOpacity));\n }\n}\n\n/**\n * Fill `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n *\n * For `<linearGradient>` the bbox-to-canvas mapping is straightforward.\n * For `<radialGradient>` the SVG default `objectBoundingBox` produces an\n * *elliptical* gradient when the bbox is non-square. Canvas only supports\n * circular radial gradients, so we apply a non-uniform scale transform to\n * the context and fill an inverse-transformed copy of the path.\n */\nfunction fillWithSvgGradient(\n ctx: SKRSContext2D,\n def: SvgChild,\n bbox: BBox,\n path: Path2D,\n fillRule: CanvasFillRule,\n): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n const x1 = bbox.x + parseFrac(props.x1, 0) * bbox.width;\n const y1 = bbox.y + parseFrac(props.y1, 0) * bbox.height;\n const x2 = bbox.x + parseFrac(props.x2, 1) * bbox.width;\n const y2 = bbox.y + parseFrac(props.y2, 0) * bbox.height;\n const gradient = ctx.createLinearGradient(x1, y1, x2, y2);\n addGradientStops(gradient, def);\n ctx.fillStyle = gradient;\n ctx.fill(path, fillRule);\n return true;\n }\n\n if (def.type === \"radialGradient\") {\n const cxF = parseFrac(props.cx, 0.5);\n const cyF = parseFrac(props.cy, 0.5);\n const rF = parseFrac(props.r, 0.5);\n const fxF = parseFrac(props.fx, cxF);\n const fyF = parseFrac(props.fy, cyF);\n\n // Render in a transformed space where the bbox maps to a unit square.\n // This turns canvas's circular radial gradient into the correct ellipse.\n ctx.save();\n ctx.translate(bbox.x, bbox.y);\n ctx.scale(bbox.width, bbox.height);\n\n const gradient = ctx.createRadialGradient(fxF, fyF, 0, cxF, cyF, rF);\n addGradientStops(gradient, def);\n ctx.fillStyle = gradient;\n\n // The path is in original (absolute) coordinates. Inverse-transform it\n // into the unit-square space so the fill aligns with the shape.\n // inverse of translate(bx,by) · scale(bw,bh) = scale(1/bw,1/bh) · translate(-bx,-by)\n const unitPath = new Path2D();\n const invTransform: DOMMatrix2DInit = {\n a: 1 / bbox.width,\n b: 0,\n c: 0,\n d: 1 / bbox.height,\n e: -bbox.x / bbox.width,\n f: -bbox.y / bbox.height,\n };\n unitPath.addPath(path, invTransform);\n\n ctx.fill(unitPath, fillRule);\n ctx.restore();\n return true;\n }\n\n return false;\n}\n\n/**\n * Stroke `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n */\nfunction strokeWithSvgGradient(\n ctx: SKRSContext2D,\n def: SvgChild,\n bbox: BBox,\n path: Path2D,\n): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n const x1 = bbox.x + parseFrac(props.x1, 0) * bbox.width;\n const y1 = bbox.y + parseFrac(props.y1, 0) * bbox.height;\n const x2 = bbox.x + parseFrac(props.x2, 1) * bbox.width;\n const y2 = bbox.y + parseFrac(props.y2, 0) * bbox.height;\n const gradient = ctx.createLinearGradient(x1, y1, x2, y2);\n addGradientStops(gradient, def);\n ctx.strokeStyle = gradient;\n ctx.stroke(path);\n return true;\n }\n\n if (def.type === \"radialGradient\") {\n // For stroke, use a simple circular approximation (geometric mean radius)\n const cxAbs = bbox.x + parseFrac(props.cx, 0.5) * bbox.width;\n const cyAbs = bbox.y + parseFrac(props.cy, 0.5) * bbox.height;\n const rAbs = parseFrac(props.r, 0.5) * Math.sqrt(bbox.width * bbox.height);\n const fxAbs = bbox.x + parseFrac(props.fx, 0.5) * bbox.width;\n const fyAbs = bbox.y + parseFrac(props.fy, 0.5) * bbox.height;\n const gradient = ctx.createRadialGradient(\n fxAbs,\n fyAbs,\n 0,\n cxAbs,\n cyAbs,\n rAbs,\n );\n addGradientStops(gradient, def);\n ctx.strokeStyle = gradient;\n ctx.stroke(path);\n return true;\n }\n\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Bounding-box helpers\n// ---------------------------------------------------------------------------\n\n/** Compute a conservative bounding box from SVG path data. */\nfunction pathBBox(d: string): BBox {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let cx = 0;\n let cy = 0;\n\n const update = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n };\n\n // Tokenize: commands and numbers (including negative)\n const tokens = d.match(/[a-zA-Z]|[-+]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?/g);\n if (!tokens) return { x: 0, y: 0, width: 0, height: 0 };\n\n let cmd = \"\";\n let i = 0;\n const num = () => Number(tokens[i++]);\n\n while (i < tokens.length) {\n const t = tokens[i]!;\n if (/[a-zA-Z]/.test(t)) {\n cmd = t;\n i++;\n }\n\n switch (cmd) {\n case \"M\":\n cx = num();\n cy = num();\n update(cx, cy);\n cmd = \"L\"; // implicit lineTo after moveTo\n break;\n case \"m\":\n cx += num();\n cy += num();\n update(cx, cy);\n cmd = \"l\";\n break;\n case \"L\":\n cx = num();\n cy = num();\n update(cx, cy);\n break;\n case \"l\":\n cx += num();\n cy += num();\n update(cx, cy);\n break;\n case \"H\":\n cx = num();\n update(cx, cy);\n break;\n case \"h\":\n cx += num();\n update(cx, cy);\n break;\n case \"V\":\n cy = num();\n update(cx, cy);\n break;\n case \"v\":\n cy += num();\n update(cx, cy);\n break;\n case \"C\": {\n // Cubic bezier: use control points as conservative bounds\n for (let j = 0; j < 3; j++) {\n const px = num();\n const py = num();\n update(px, py);\n }\n cx = Number(tokens[i - 2]);\n cy = Number(tokens[i - 1]);\n break;\n }\n case \"c\": {\n for (let j = 0; j < 3; j++) {\n const dx = num();\n const dy = num();\n update(cx + dx, cy + dy);\n if (j === 2) {\n cx += dx;\n cy += dy;\n }\n }\n break;\n }\n case \"Q\": {\n for (let j = 0; j < 2; j++) {\n const px = num();\n const py = num();\n update(px, py);\n }\n cx = Number(tokens[i - 2]);\n cy = Number(tokens[i - 1]);\n break;\n }\n case \"q\": {\n for (let j = 0; j < 2; j++) {\n const dx = num();\n const dy = num();\n update(cx + dx, cy + dy);\n if (j === 1) {\n cx += dx;\n cy += dy;\n }\n }\n break;\n }\n case \"A\": {\n // Arc: skip rx, ry, rotation, flags; endpoint is the bound\n num();\n num();\n num();\n num();\n num(); // rx ry rot largeArc sweep\n cx = num();\n cy = num();\n update(cx, cy);\n break;\n }\n case \"a\": {\n num();\n num();\n num();\n num();\n num();\n cx += num();\n cy += num();\n update(cx, cy);\n break;\n }\n case \"Z\":\n case \"z\":\n break;\n default:\n // Unknown command — skip token to avoid infinite loop\n i++;\n break;\n }\n }\n\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/** Compute bounding box from a points attribute (polygon/polyline). */\nfunction pointsBBox(points: [number, number][]): BBox {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of points) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Build a `Path2D` from an SVG shape element (without drawing it).\n * Returns `undefined` for unsupported element types.\n */\nfunction buildPath(\n child: SvgChild,\n vbW: number,\n vbH: number,\n): Path2D | undefined {\n const props = mergeStyleIntoProps(child.props);\n switch (child.type) {\n case \"path\": {\n const d = props.d as string | undefined;\n if (!d) return undefined;\n return new Path2D(d);\n }\n case \"circle\": {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const r = svgLength(props.r, Math.min(vbW, vbH));\n if (r <= 0) return undefined;\n const p = new Path2D();\n p.arc(cx, cy, r, 0, Math.PI * 2);\n return p;\n }\n case \"rect\": {\n const rx = svgLength(props.x, vbW);\n const ry = svgLength(props.y, vbH);\n const w = svgLength(props.width, vbW);\n const h = svgLength(props.height, vbH);\n if (w <= 0 || h <= 0) return undefined;\n const p = new Path2D();\n p.rect(rx, ry, w, h);\n return p;\n }\n case \"ellipse\": {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const rx = svgLength(props.rx, vbW);\n const ry = svgLength(props.ry, vbH);\n if (rx <= 0 || ry <= 0) return undefined;\n const p = new Path2D();\n p.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n return p;\n }\n case \"polygon\": {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return undefined;\n const p = new Path2D();\n p.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n p.lineTo(points[i]![0], points[i]![1]);\n }\n p.closePath();\n return p;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Build a combined `Path2D` from all children of a `<clipPath>` definition.\n */\nfunction buildClipPath(\n shapes: SvgChild[],\n vbW: number,\n vbH: number,\n): Path2D | undefined {\n let combined: Path2D | undefined;\n for (const shape of shapes) {\n const p = buildPath(shape, vbW, vbH);\n if (!p) continue;\n if (!combined) {\n combined = p;\n } else {\n combined.addPath(p);\n }\n }\n return combined;\n}\n\n/**\n * Draw an `<svg>` container and its SVG children (path, circle, rect, etc.).\n *\n * Parses the `viewBox` prop to compute scale factors, then recurses into\n * the React children stored in `node.props.children`.\n */\nexport function drawSvgContainer(\n ctx: SKRSContext2D,\n node: LayoutNode,\n x: number,\n y: number,\n width: number,\n height: number,\n): void {\n ctx.save();\n ctx.translate(x, y);\n\n // Parse viewBox for coordinate mapping; default to rendered size when absent\n const viewBox = node.props.viewBox as string | undefined;\n let vbW = width;\n let vbH = height;\n if (viewBox) {\n const parts = viewBox.split(/[\\s,]+/).map(Number);\n if (parts.length === 4) {\n const [vbX, vbY, parsedW, parsedH] = parts as [\n number,\n number,\n number,\n number,\n ];\n vbW = parsedW;\n vbH = parsedH;\n const scaleX = width / vbW;\n const scaleY = height / vbH;\n ctx.scale(scaleX, scaleY);\n ctx.translate(-vbX, -vbY);\n }\n }\n\n // Resolve the CSS `color` property for `currentColor` references\n const color = (node.style.color as string | undefined) ?? \"black\";\n\n // Inherited fill from the <svg> element (SVG fill is inheritable)\n const merged = mergeStyleIntoProps(node.props);\n const inheritedFill =\n resolveCurrentColor(merged.fill as string | undefined, color) ?? \"black\";\n\n // Traverse React children\n const children = node.props.children;\n if (children != null) {\n const childArray = Array.isArray(children) ? children : [children];\n const svgChildren = childArray.filter(\n (c): c is SvgChild => c != null && typeof c === \"object\",\n );\n\n // First pass: collect definitions from <defs>\n const defs = collectDefs(svgChildren);\n\n // Second pass: draw children\n for (const child of svgChildren) {\n drawSvgChild(ctx, child, inheritedFill, color, defs, vbW, vbH);\n }\n }\n\n ctx.restore();\n}\n\nconst EMPTY_DEFS: SvgDefs = {\n clips: new Map(),\n gradients: new Map(),\n};\n\nfunction drawSvgChild(\n ctx: SKRSContext2D,\n child: SvgChild,\n inheritedFill: string,\n color: string,\n defs: SvgDefs = EMPTY_DEFS,\n vbW = 0,\n vbH = 0,\n): void {\n const { type } = child;\n const props = mergeStyleIntoProps(child.props);\n\n // Skip non-drawable definition elements\n if (type === \"defs\" || type === \"clipPath\") return;\n\n // Check for clip-path=\"url(#id)\" reference\n const clipRef = parseUrlRef(props.clipPath ?? props[\"clip-path\"]);\n const clipShapes = clipRef ? defs.clips.get(clipRef) : undefined;\n const clipPath = clipShapes ? buildClipPath(clipShapes, vbW, vbH) : undefined;\n\n if (clipPath) ctx.save();\n if (clipPath) ctx.clip(clipPath);\n\n switch (type) {\n case \"path\":\n drawPath(ctx, props, inheritedFill, color, defs);\n break;\n case \"circle\":\n drawCircle(ctx, props, inheritedFill, color, defs, vbW, vbH);\n break;\n case \"rect\":\n drawSvgRect(ctx, props, inheritedFill, color, defs, vbW, vbH);\n break;\n case \"line\":\n drawLine(ctx, props, color, defs, vbW, vbH);\n break;\n case \"ellipse\":\n drawEllipse(ctx, props, inheritedFill, color, defs, vbW, vbH);\n break;\n case \"polygon\":\n drawPolygon(ctx, props, inheritedFill, color, defs);\n break;\n case \"polyline\":\n drawPolyline(ctx, props, inheritedFill, color, defs);\n break;\n case \"g\":\n drawGroup(ctx, child, inheritedFill, color, defs, vbW, vbH);\n break;\n }\n\n if (clipPath) ctx.restore();\n}\n\nfunction drawPath(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n): void {\n const d = props.d as string | undefined;\n if (!d) return;\n\n const path = new Path2D(d);\n const bbox = pathBBox(d);\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawCircle(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const r = svgLength(props.r, Math.min(vbW, vbH));\n if (r <= 0) return;\n\n const path = new Path2D();\n path.arc(cx, cy, r, 0, Math.PI * 2);\n const bbox: BBox = { x: cx - r, y: cy - r, width: 2 * r, height: 2 * r };\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawSvgRect(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const rx = svgLength(props.x, vbW);\n const ry = svgLength(props.y, vbH);\n const w = svgLength(props.width, vbW);\n const h = svgLength(props.height, vbH);\n if (w <= 0 || h <= 0) return;\n\n const path = new Path2D();\n path.rect(rx, ry, w, h);\n const bbox: BBox = { x: rx, y: ry, width: w, height: h };\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawLine(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const x1 = svgLength(props.x1, vbW);\n const y1 = svgLength(props.y1, vbH);\n const x2 = svgLength(props.x2, vbW);\n const y2 = svgLength(props.y2, vbH);\n\n const path = new Path2D();\n path.moveTo(x1, y1);\n path.lineTo(x2, y2);\n // Lines are stroke-only\n const bbox: BBox = {\n x: Math.min(x1, x2),\n y: Math.min(y1, y2),\n width: Math.abs(x2 - x1),\n height: Math.abs(y2 - y1),\n };\n applyStroke(ctx, props, path, color, defs, bbox);\n}\n\nfunction drawEllipse(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const rx = svgLength(props.rx, vbW);\n const ry = svgLength(props.ry, vbH);\n if (rx <= 0 || ry <= 0) return;\n\n const path = new Path2D();\n path.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n const bbox: BBox = {\n x: cx - rx,\n y: cy - ry,\n width: 2 * rx,\n height: 2 * ry,\n };\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawPolygon(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n): void {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return;\n\n const path = new Path2D();\n path.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n path.lineTo(points[i]![0], points[i]![1]);\n }\n path.closePath();\n const bbox = pointsBBox(points);\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\nfunction drawPolyline(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n): void {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return;\n\n const path = new Path2D();\n path.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n path.lineTo(points[i]![0], points[i]![1]);\n }\n const bbox = pointsBBox(points);\n applyFillAndStroke(ctx, props, path, inheritedFill, color, defs, bbox);\n}\n\n/**\n * Parse an SVG `transform` attribute and apply it to the canvas context.\n *\n * Supports: translate, scale, rotate, skewX, skewY, matrix.\n * Multiple transforms are applied left-to-right (same order as SVG spec).\n */\nfunction applySvgTransform(ctx: SKRSContext2D, transform: string): void {\n const re = /\\b(translate|scale|rotate|skewX|skewY|matrix)\\s*\\(([^)]*)\\)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(transform)) !== null) {\n const fn = match[1]!;\n const args = match[2]!\n .split(/[\\s,]+/)\n .filter(Boolean)\n .map(Number);\n\n switch (fn) {\n case \"translate\":\n ctx.translate(args[0] ?? 0, args[1] ?? 0);\n break;\n case \"scale\": {\n const sx = args[0] ?? 1;\n ctx.scale(sx, args[1] ?? sx);\n break;\n }\n case \"rotate\": {\n const angle = ((args[0] ?? 0) * Math.PI) / 180;\n if (args.length >= 3) {\n const cx = args[1]!;\n const cy = args[2]!;\n ctx.translate(cx, cy);\n ctx.rotate(angle);\n ctx.translate(-cx, -cy);\n } else {\n ctx.rotate(angle);\n }\n break;\n }\n case \"skewX\":\n ctx.transform(\n 1,\n 0,\n Math.tan(((args[0] ?? 0) * Math.PI) / 180),\n 1,\n 0,\n 0,\n );\n break;\n case \"skewY\":\n ctx.transform(\n 1,\n Math.tan(((args[0] ?? 0) * Math.PI) / 180),\n 0,\n 1,\n 0,\n 0,\n );\n break;\n case \"matrix\":\n ctx.transform(\n args[0] ?? 1,\n args[1] ?? 0,\n args[2] ?? 0,\n args[3] ?? 1,\n args[4] ?? 0,\n args[5] ?? 0,\n );\n break;\n }\n }\n}\n\nfunction drawGroup(\n ctx: SKRSContext2D,\n node: SvgChild,\n inheritedFill: string,\n color: string,\n defs: SvgDefs = EMPTY_DEFS,\n vbW = 0,\n vbH = 0,\n): void {\n const children = normalizeChildren(node);\n if (children.length === 0) return;\n // Group can override inherited fill\n const merged = mergeStyleIntoProps(node.props);\n const groupFill =\n resolveCurrentColor(merged.fill as string | undefined, color) ??\n inheritedFill;\n\n const transform = merged.transform as string | undefined;\n if (transform) {\n ctx.save();\n applySvgTransform(ctx, transform);\n }\n\n for (const child of children) {\n if (child != null && typeof child === \"object\") {\n drawSvgChild(ctx, child, groupFill, color, defs, vbW, vbH);\n }\n }\n\n if (transform) {\n ctx.restore();\n }\n}\n\nfunction parsePoints(value: string | undefined): [number, number][] {\n if (!value) return [];\n const nums = value\n .trim()\n .split(/[\\s,]+/)\n .map(Number);\n const result: [number, number][] = [];\n for (let i = 0; i + 1 < nums.length; i += 2) {\n result.push([nums[i]!, nums[i + 1]!]);\n }\n return result;\n}\n\nfunction applyFillAndStroke(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n path: Path2D,\n inheritedFill: string,\n color: string,\n defs: SvgDefs,\n bbox: BBox,\n): void {\n // Use element's own fill if set, otherwise inherit from parent\n const fill =\n resolveCurrentColor(props.fill as string | undefined, color) ??\n inheritedFill;\n const fillRule = (props.fillRule ?? props[\"fill-rule\"]) as\n | CanvasFillRule\n | undefined;\n // Resolve url(#id) gradient reference\n const fillRef = parseUrlRef(fill);\n if (fillRef) {\n const gradientDef = defs.gradients.get(fillRef);\n if (gradientDef) {\n fillWithSvgGradient(ctx, gradientDef, bbox, path, fillRule ?? \"nonzero\");\n }\n } else if (fill !== \"none\") {\n ctx.fillStyle = fill;\n ctx.fill(path, fillRule ?? \"nonzero\");\n }\n\n applyStroke(ctx, props, path, color, defs, bbox);\n}\n\nfunction applyStroke(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n path: Path2D,\n color: string,\n defs: SvgDefs,\n bbox: BBox,\n): void {\n const stroke = resolveCurrentColor(props.stroke as string | undefined, color);\n if (!stroke || stroke === \"none\") return;\n\n ctx.lineWidth = Number(props.strokeWidth ?? props[\"stroke-width\"] ?? 1);\n ctx.lineCap =\n ((props.strokeLinecap ?? props[\"stroke-linecap\"]) as CanvasLineCap) ??\n \"butt\";\n ctx.lineJoin =\n ((props.strokeLinejoin ?? props[\"stroke-linejoin\"]) as CanvasLineJoin) ??\n \"miter\";\n\n // Resolve url(#id) gradient reference for stroke\n const strokeRef = parseUrlRef(stroke);\n if (strokeRef) {\n const gradientDef = defs.gradients.get(strokeRef);\n if (gradientDef) {\n strokeWithSvgGradient(ctx, gradientDef, bbox, path);\n return;\n }\n }\n\n ctx.strokeStyle = stroke;\n ctx.stroke(path);\n}\n","import { loadImage } from \"@napi-rs/canvas\";\nimport type { SKRSContext2D, Image } from \"@napi-rs/canvas\";\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport { getEmojiCode, loadEmoji } from \"../emoji.ts\";\nimport type { TextSegment } from \"../text/index.ts\";\nimport { splitTextIntoRuns } from \"../text/emoji-split.ts\";\nimport { setFont } from \"../text/measure.ts\";\n\nconst emojiImageCache = new Map<string, Promise<Image | null>>();\n\nfunction loadEmojiImage(\n style: EmojiStyle,\n char: string,\n): Promise<Image | null> {\n const code = getEmojiCode(char);\n const key = style + \":\" + code;\n let cached = emojiImageCache.get(key);\n if (!cached) {\n cached = loadEmoji(style, code)\n .then((svgText) => {\n if (!svgText || !svgText.includes(\"<svg\")) return null;\n const dataUri =\n \"data:image/svg+xml;base64,\" +\n Buffer.from(svgText).toString(\"base64\");\n return loadImage(dataUri);\n })\n .catch(() => null);\n emojiImageCache.set(key, cached);\n }\n return cached;\n}\n\n/**\n * Draw text segments onto the canvas context.\n *\n * @param ctx - Canvas 2D rendering context\n * @param segments - Positioned text segments from the text layout engine\n * @param offsetX - X offset for the text block\n * @param offsetY - Y offset for the text block\n * @param textShadow - Optional text-shadow CSS value\n * @param emojiStyle - Optional emoji style for rendering emoji as images\n */\nexport async function drawText(\n ctx: SKRSContext2D,\n segments: TextSegment[],\n offsetX: number,\n offsetY: number,\n textShadow?: string,\n emojiStyle?: EmojiStyle,\n): Promise<void> {\n for (const seg of segments) {\n if (!seg.text) continue;\n\n setFont(ctx, seg.fontSize, seg.fontFamily, seg.fontWeight, seg.fontStyle);\n ctx.fillStyle = seg.color;\n\n const x = offsetX + seg.x;\n const y = offsetY + seg.y;\n\n if (emojiStyle) {\n await drawSegmentWithEmoji(ctx, seg, x, y, textShadow, emojiStyle);\n } else if (seg.letterSpacing && seg.letterSpacing !== 0) {\n drawTextWithLetterSpacing(ctx, seg.text, x, y, seg.letterSpacing);\n } else {\n if (textShadow) {\n drawTextShadow(ctx, seg.text, x, y, textShadow);\n }\n ctx.fillText(seg.text, x, y);\n }\n\n // Text decoration\n if (seg.textDecoration) {\n drawTextDecoration(ctx, seg, offsetX, offsetY);\n }\n }\n}\n\nasync function drawSegmentWithEmoji(\n ctx: SKRSContext2D,\n seg: TextSegment,\n x: number,\n y: number,\n textShadow: string | undefined,\n emojiStyle: EmojiStyle,\n): Promise<void> {\n const letterSpacing = seg.letterSpacing ?? 0;\n const runs = splitTextIntoRuns(\n seg.text,\n (text) => {\n setFont(ctx, seg.fontSize, seg.fontFamily, seg.fontWeight, seg.fontStyle);\n return ctx.measureText(text).width;\n },\n seg.fontSize,\n letterSpacing,\n );\n\n for (const run of runs) {\n if (run.kind === \"text\") {\n if (textShadow) {\n drawTextShadow(ctx, run.text, x + run.x, y, textShadow);\n }\n if (letterSpacing !== 0) {\n drawTextWithLetterSpacing(ctx, run.text, x + run.x, y, letterSpacing);\n } else {\n ctx.fillText(run.text, x + run.x, y);\n }\n } else {\n const img = await loadEmojiImage(emojiStyle, run.char);\n if (img) {\n const emojiSize = seg.fontSize;\n // Position emoji so it aligns vertically with text:\n // y is the baseline, ascent goes up from baseline\n const emojiY = y - seg.ascent + (seg.height - seg.fontSize) / 2;\n ctx.drawImage(img, x + run.x, emojiY, emojiSize, emojiSize);\n } else {\n // Emoji image unavailable — fall back to text rendering\n ctx.fillText(run.char, x + run.x, y);\n }\n }\n }\n}\n\nfunction drawTextWithLetterSpacing(\n ctx: SKRSContext2D,\n text: string,\n x: number,\n y: number,\n letterSpacing: number,\n): void {\n let currentX = x;\n for (const char of text) {\n ctx.fillText(char, currentX, y);\n const metrics = ctx.measureText(char);\n currentX += metrics.width + letterSpacing;\n }\n}\n\nfunction drawTextShadow(\n ctx: SKRSContext2D,\n text: string,\n x: number,\n y: number,\n shadow: string,\n): void {\n const parts = shadow.match(\n /(-?\\d+(?:\\.\\d+)?)\\s*px?\\s+(-?\\d+(?:\\.\\d+)?)\\s*px?\\s+(-?\\d+(?:\\.\\d+)?)\\s*px?\\s+(.*)/,\n );\n if (!parts) return;\n\n ctx.save();\n ctx.shadowOffsetX = parseFloat(parts[1]!);\n ctx.shadowOffsetY = parseFloat(parts[2]!);\n ctx.shadowBlur = parseFloat(parts[3]!);\n ctx.shadowColor = parts[4]!.trim();\n ctx.fillText(text, x, y);\n ctx.restore();\n}\n\nfunction drawTextDecoration(\n ctx: SKRSContext2D,\n seg: TextSegment,\n offsetX: number,\n offsetY: number,\n): void {\n const decoration = seg.textDecoration;\n if (!decoration || decoration === \"none\") return;\n\n ctx.strokeStyle = seg.color;\n ctx.lineWidth = Math.max(1, seg.fontSize * 0.1);\n\n const x = offsetX + seg.x;\n const baseY = offsetY + seg.y;\n\n if (decoration.includes(\"underline\")) {\n const y = baseY + seg.ascent * 0.1;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n\n if (decoration.includes(\"line-through\")) {\n const y = baseY - seg.fontSize * 0.3;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n\n if (decoration.includes(\"overline\")) {\n const y = baseY - seg.fontSize * 0.85;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\n/**\n * Emoji style options for rendering\n */\nexport type EmojiStyle =\n | \"twemoji\"\n | \"openmoji\"\n | \"blobmoji\"\n | \"noto\"\n | \"fluent\"\n | \"fluentFlat\";\n\nexport const emojiApis: Record<\n EmojiStyle,\n string | ((code: string) => string)\n> = {\n twemoji: (code: string) =>\n `https://cdnjs.cloudflare.com/ajax/libs/twemoji/16.0.1/svg/${code.toLowerCase()}.svg`,\n openmoji: \"https://cdn.jsdelivr.net/npm/@svgmoji/openmoji@2.0.0/svg/\",\n blobmoji: \"https://cdn.jsdelivr.net/npm/@svgmoji/blob@2.0.0/svg/\",\n noto: \"https://cdn.jsdelivr.net/gh/svgmoji/svgmoji/packages/svgmoji__noto/svg/\",\n fluent: (code: string) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_color.svg`,\n fluentFlat: (code: string) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_flat.svg`,\n};\n\nconst U200D = String.fromCharCode(8205);\nconst UFE0Fg = /\\uFE0F/g;\n\nexport function getEmojiCode(char: string): string {\n return toCodePoint(char.indexOf(U200D) < 0 ? char.replace(UFE0Fg, \"\") : char);\n}\n\nexport function toCodePoint(unicodeSurrogates: string): string {\n const r: string[] = [];\n let c = 0,\n p = 0,\n i = 0;\n\n while (i < unicodeSurrogates.length) {\n c = unicodeSurrogates.charCodeAt(i++);\n if (p) {\n r.push((65536 + ((p - 55296) << 10) + (c - 56320)).toString(16));\n p = 0;\n } else if (55296 <= c && c <= 56319) {\n p = c;\n } else {\n r.push(c.toString(16));\n }\n }\n return r.join(\"-\");\n}\n\nconst emojiCache: Record<string, Promise<string>> = {};\n\nexport async function loadEmoji(\n type: EmojiStyle,\n code: string,\n): Promise<string> {\n const key = type + \":\" + code;\n if (key in emojiCache) return emojiCache[key];\n\n const api = emojiApis[type];\n if (typeof api === \"function\") {\n return (emojiCache[key] = fetch(api(code)).then((r) => r.text()));\n }\n return (emojiCache[key] = fetch(`${api}${code.toUpperCase()}.svg`).then((r) =>\n r.text(),\n ));\n}\n","import { isEmoji } from \"../language.ts\";\n\nexport type TextRun =\n | { kind: \"text\"; text: string; x: number; width: number }\n | { kind: \"emoji\"; char: string; x: number; width: number };\n\n/**\n * Split a text string into runs of plain text and individual emoji characters.\n * Uses Intl.Segmenter for correct grapheme cluster handling (multi-codepoint emoji).\n */\nexport function splitTextIntoRuns(\n text: string,\n measureText: (text: string) => number,\n emojiSize: number,\n letterSpacing: number = 0,\n): TextRun[] {\n const runs: TextRun[] = [];\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n let currentText = \"\";\n let currentGraphemeCount = 0;\n let currentX = 0;\n let textStartX = 0;\n\n for (const { segment } of segmenter.segment(text)) {\n if (isEmojiGrapheme(segment)) {\n // Flush accumulated text\n if (currentText) {\n const textWidth = measureText(currentText);\n runs.push({\n kind: \"text\",\n text: currentText,\n x: textStartX,\n width: textWidth + letterSpacing * currentGraphemeCount,\n });\n currentX =\n textStartX + textWidth + letterSpacing * currentGraphemeCount;\n currentText = \"\";\n currentGraphemeCount = 0;\n }\n runs.push({\n kind: \"emoji\",\n char: segment,\n x: currentX,\n width: emojiSize,\n });\n currentX += emojiSize + letterSpacing;\n textStartX = currentX;\n } else {\n if (!currentText) textStartX = currentX;\n currentText += segment;\n currentGraphemeCount++;\n }\n }\n\n // Flush remaining text\n if (currentText) {\n const textWidth = measureText(currentText);\n runs.push({\n kind: \"text\",\n text: currentText,\n x: textStartX,\n width: textWidth + letterSpacing * currentGraphemeCount,\n });\n }\n\n return runs;\n}\n\n/**\n * Check if a grapheme cluster is an emoji.\n * Checks the first code point of the grapheme.\n */\nfunction isEmojiGrapheme(grapheme: string): boolean {\n for (const char of grapheme) {\n if (isEmoji(char)) return true;\n }\n return false;\n}\n","import { GlobalFonts } from \"@napi-rs/canvas\";\n\nimport type { FontData } from \"../types.ts\";\n\nconst registeredFonts = new Set<string>();\n\n/**\n * Reset internal font state (test-only).\n */\nexport function _resetForTest(): void {\n registeredFonts.clear();\n}\n\n/**\n * Register a font from a FontData buffer.\n * Registration is idempotent — re-registering the same font name is a no-op.\n *\n * @param font - Font data to register\n */\nexport function registerFont(font: FontData): void {\n const key = `${font.name}:${font.weight}:${font.style}`;\n if (registeredFonts.has(key)) return;\n\n const buffer = Buffer.isBuffer(font.data)\n ? font.data\n : Buffer.from(font.data);\n\n GlobalFonts.register(buffer, font.name);\n\n registeredFonts.add(key);\n}\n\n/**\n * Register a font from a file path.\n *\n * @param path - Path to the font file\n * @param nameAlias - Optional font family name override\n */\nexport function registerFontFromPath(path: string, nameAlias?: string): void {\n GlobalFonts.registerFromPath(path, nameAlias ?? \"\");\n}\n\n/**\n * Get the list of registered font family names.\n *\n * @returns Array of font family names\n */\nexport function registeredFamilies(): string[] {\n return GlobalFonts.families.map((f: { family: string }) => f.family);\n}\n\n/**\n * Ensure all fonts from the given array are registered.\n * Called internally by `renderReactElement()`.\n */\nexport function ensureFontsRegistered(fonts: FontData[]): void {\n for (const font of fonts) {\n registerFont(font);\n }\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\nimport { loadImage } from \"@napi-rs/canvas\";\nimport type { ReactElement, ReactNode } from \"react\";\n\nimport { expandStyle } from \"./style/expand.ts\";\nimport { resolveStyle, resolveUnits, DEFAULT_STYLE } from \"./style/compute.ts\";\nimport type { ComputedStyle } from \"./style/compute.ts\";\nimport { applyStylesToYoga } from \"./style/properties.ts\";\nimport { createTextMeasureFunc } from \"./text/index.ts\";\nimport { createYogaNode, freeYogaNode, FlexDirection } from \"./yoga.ts\";\nimport type { YogaNode } from \"./yoga.ts\";\n\n/**\n * A node in the computed layout tree, ready for drawing.\n */\nexport type LayoutNode = {\n type: string;\n style: ComputedStyle;\n children: LayoutNode[];\n textContent?: string;\n props: Record<string, unknown>;\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\ntype ElementChild = string | number | ReactElement | null | undefined | boolean;\n\n/**\n * Build a layout tree from a React element tree.\n * Creates Yoga nodes, calculates layout, and returns the positioned tree.\n *\n * @param element - React element tree to lay out\n * @param containerWidth - Width of the container (from canvas)\n * @param containerHeight - Height of the container (from canvas)\n * @param ctx - Canvas context for text measurement\n * @returns Root layout node with computed positions and dimensions\n */\nexport async function buildLayoutTree(\n element: ReactNode,\n containerWidth: number,\n containerHeight: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n fontFamilies?: string[],\n): Promise<LayoutNode> {\n const elementYogaNode = createYogaNode();\n\n // Set font families as default on root style so all nodes inherit them\n const rootStyle = fontFamilies?.length\n ? { ...DEFAULT_STYLE, fontFamily: fontFamilies.join(\", \") }\n : DEFAULT_STYLE;\n\n // Build the tree\n const elementNode = await buildNode(\n element,\n rootStyle,\n elementYogaNode,\n containerWidth,\n containerHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n );\n\n // Wrap the user element in a canvas-sized container (like Satori) so that\n // absolute positioning, percentage sizes, etc. resolve against the canvas.\n const rootYogaNode = createYogaNode();\n rootYogaNode.setWidth(containerWidth);\n rootYogaNode.setHeight(containerHeight);\n rootYogaNode.setFlexDirection(FlexDirection.Row);\n rootYogaNode.insertChild(elementYogaNode, 0);\n\n rootYogaNode.calculateLayout(containerWidth, containerHeight);\n\n const elementLayout = extractLayout(elementNode, elementYogaNode);\n freeYogaNode(rootYogaNode);\n\n return {\n type: \"div\",\n style: rootStyle,\n children: [elementLayout],\n props: {},\n x: 0,\n y: 0,\n width: containerWidth,\n height: containerHeight,\n } as LayoutNode;\n}\n\nasync function buildNode(\n element: ReactNode,\n parentStyle: ComputedStyle,\n yogaNode: YogaNode,\n viewportWidth: number,\n viewportHeight: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n fontFamilies?: string[],\n): Promise<IntermediateNode> {\n // Handle null/undefined/boolean\n if (\n element === null ||\n element === undefined ||\n typeof element === \"boolean\"\n ) {\n return {\n type: \"empty\",\n style: parentStyle,\n children: [],\n props: {},\n yogaNode,\n };\n }\n\n // Handle text/number primitives\n if (typeof element === \"string\" || typeof element === \"number\") {\n const text = String(element);\n const style = resolveStyle(undefined, parentStyle);\n\n // Set up text measurement\n const measureFunc = createTextMeasureFunc(text, style, ctx, emojiEnabled);\n yogaNode.setMeasureFunc(measureFunc);\n\n return {\n type: \"text\",\n style,\n children: [],\n textContent: text,\n props: {},\n yogaNode,\n };\n }\n\n // Handle arrays (fragments)\n if (Array.isArray(element)) {\n const style = resolveStyle(undefined, parentStyle);\n const children: IntermediateNode[] = [];\n\n for (let i = 0; i < element.length; i++) {\n const child = element[i] as ElementChild;\n if (child === null || child === undefined || typeof child === \"boolean\")\n continue;\n\n const childYogaNode = createYogaNode();\n yogaNode.insertChild(childYogaNode, children.length);\n children.push(\n await buildNode(\n child,\n style,\n childYogaNode,\n viewportWidth,\n viewportHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n ),\n );\n }\n\n return {\n type: \"div\",\n style,\n children,\n props: {},\n yogaNode,\n };\n }\n\n // Handle React elements\n const el = element as ReactElement<Record<string, unknown>>;\n const type = el.type;\n\n // Expand function/class components\n if (typeof type === \"function\") {\n const rendered = (type as (props: Record<string, unknown>) => ReactNode)(\n el.props ?? {},\n );\n return await buildNode(\n rendered,\n parentStyle,\n yogaNode,\n viewportWidth,\n viewportHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n );\n }\n\n const props = (el.props ?? {}) as Record<string, unknown>;\n const rawStyle = (props.style ?? {}) as Record<string, unknown>;\n const expanded = expandStyle(rawStyle, fontFamilies);\n const style = resolveStyle(expanded, parentStyle);\n resolveUnits(style, viewportWidth, viewportHeight);\n\n const tagName = String(type);\n\n // For <svg> elements, merge width/height props into style when not set via CSS\n if (tagName === \"svg\") {\n if (props.width != null && style.width === undefined) {\n const v = props.width;\n style.width = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n if (props.height != null && style.height === undefined) {\n const v = props.height;\n style.height = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n\n // Derive missing dimension from viewBox aspect ratio\n const viewBox = props.viewBox as string | undefined;\n if (viewBox) {\n const parts = viewBox.split(/[\\s,]+/).map(Number);\n if (parts.length === 4) {\n const [, , vbW, vbH] = parts as [number, number, number, number];\n if (vbW > 0 && vbH > 0) {\n const wSet = style.width !== undefined;\n const hSet = style.height !== undefined;\n if (!wSet && !hSet) {\n style.width = vbW;\n style.height = vbH;\n } else if (!hSet && typeof style.width === \"number\") {\n style.height = style.width * (vbH / vbW);\n } else if (!wSet && typeof style.height === \"number\") {\n style.width = style.height * (vbW / vbH);\n }\n // When either/both are %, leave as-is for Yoga\n }\n }\n }\n }\n\n // For <img> elements, derive missing dimensions from intrinsic aspect ratio\n if (tagName === \"img\") {\n // Map HTML width/height attributes to style (like <svg>)\n if (props.width != null && style.width === undefined) {\n const v = props.width;\n style.width = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n if (props.height != null && style.height === undefined) {\n const v = props.height;\n style.height = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n\n const src = props.src as string | Buffer | undefined;\n if (src) {\n try {\n const image = await loadImage(src);\n const naturalW = image.width;\n const naturalH = image.height;\n\n const wSet = style.width !== undefined;\n const hSet = style.height !== undefined;\n\n if (wSet && !hSet && typeof style.width === \"number\" && naturalW > 0) {\n style.height = style.width * (naturalH / naturalW);\n } else if (\n hSet &&\n !wSet &&\n typeof style.height === \"number\" &&\n naturalH > 0\n ) {\n style.width = style.height * (naturalW / naturalH);\n }\n // When either/both are %, leave as-is for Yoga\n\n // Cache loaded image for reuse during drawing\n props.__loadedImage = image;\n } catch {\n // Silent fail — image will render at whatever size Yoga computes\n }\n }\n }\n\n // Apply styles to Yoga node\n applyStylesToYoga(yogaNode, style);\n\n // SVG containers: children use SVG coordinate space, not flex layout.\n // Skip Yoga child nodes and keep React children in props for the SVG drawer.\n if (tagName === \"svg\") {\n return {\n type: tagName,\n style,\n children: [],\n props,\n yogaNode,\n };\n }\n\n // Collect text content from direct string children\n const textContent = extractTextContent(props.children);\n\n // If this node has only text content, create a child text node.\n // Using a child node (instead of setMeasureFunc on this node directly)\n // ensures Yoga's baseline calculation accounts for this node's padding/border\n // when a parent uses alignItems: \"baseline\".\n if (textContent !== undefined && !hasElementChildren(props.children)) {\n const childStyle = resolveStyle(undefined, style);\n const childYogaNode = createYogaNode();\n const measureFunc = createTextMeasureFunc(\n textContent,\n childStyle,\n ctx,\n emojiEnabled,\n );\n childYogaNode.setMeasureFunc(measureFunc);\n childYogaNode.setFlexGrow(1);\n childYogaNode.setFlexShrink(1);\n yogaNode.insertChild(childYogaNode, 0);\n\n return {\n type: tagName,\n style,\n children: [\n {\n type: \"text\",\n style: childStyle,\n children: [],\n textContent,\n props: {},\n yogaNode: childYogaNode,\n },\n ],\n props,\n yogaNode,\n };\n }\n\n // Process children\n const children: IntermediateNode[] = [];\n const rawChildren = props.children;\n\n if (rawChildren !== undefined && rawChildren !== null) {\n const childArray = Array.isArray(rawChildren) ? rawChildren : [rawChildren];\n\n for (const child of childArray as ElementChild[]) {\n if (child === null || child === undefined || typeof child === \"boolean\")\n continue;\n\n const childYogaNode = createYogaNode();\n yogaNode.insertChild(childYogaNode, children.length);\n children.push(\n await buildNode(\n child,\n style,\n childYogaNode,\n viewportWidth,\n viewportHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n ),\n );\n }\n }\n\n return {\n type: tagName,\n style,\n children,\n props,\n yogaNode,\n };\n}\n\ntype IntermediateNode = {\n type: string;\n style: ComputedStyle;\n children: IntermediateNode[];\n textContent?: string;\n props: Record<string, unknown>;\n yogaNode: YogaNode;\n};\n\nfunction extractLayout(node: IntermediateNode, yogaNode: YogaNode): LayoutNode {\n const layout = yogaNode.getComputedLayout();\n\n return {\n type: node.type,\n style: node.style,\n children: node.children.map((child, i) => {\n const childYoga = yogaNode.getChild(i);\n return extractLayout(child, childYoga);\n }),\n textContent: node.textContent,\n props: node.props,\n x: layout.left,\n y: layout.top,\n width: layout.width,\n height: layout.height,\n };\n}\n\n/**\n * Extract plain text content from children if they are all strings/numbers.\n */\nfunction extractTextContent(children: unknown): string | undefined {\n if (children === undefined || children === null) return undefined;\n if (typeof children === \"string\") return children;\n if (typeof children === \"number\") return String(children);\n\n if (Array.isArray(children)) {\n const parts: string[] = [];\n for (const child of children) {\n if (typeof child === \"string\") {\n parts.push(child);\n } else if (typeof child === \"number\") {\n parts.push(String(child));\n } else if (\n child !== null &&\n child !== undefined &&\n typeof child !== \"boolean\"\n ) {\n return undefined; // Mixed content — not pure text\n }\n }\n return parts.join(\"\");\n }\n\n return undefined;\n}\n\n/**\n * Check if children contains any React elements (not just strings/numbers).\n */\nfunction hasElementChildren(children: unknown): boolean {\n if (\n children === undefined ||\n children === null ||\n typeof children === \"boolean\"\n )\n return false;\n if (typeof children === \"string\" || typeof children === \"number\")\n return false;\n\n if (Array.isArray(children)) {\n return children.some(\n (child) =>\n child !== null &&\n child !== undefined &&\n typeof child !== \"boolean\" &&\n typeof child !== \"string\" &&\n typeof child !== \"number\",\n );\n }\n\n // Single React element\n return typeof children === \"object\";\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { ExpandedStyle } from \"./compute.ts\";\n\ntype RawStyle = Record<string, unknown>;\n\nconst SIDES = [\"Top\", \"Right\", \"Bottom\", \"Left\"] as const;\n\n/**\n * Parse a CSS shorthand value like \"10px 20px\" into 1-4 parts.\n */\nfunction parseSides(value: string): string[] {\n const parts = value.toString().split(/\\s+/).filter(Boolean);\n switch (parts.length) {\n case 1:\n return [parts[0]!, parts[0]!, parts[0]!, parts[0]!];\n case 2:\n return [parts[0]!, parts[1]!, parts[0]!, parts[1]!];\n case 3:\n return [parts[0]!, parts[1]!, parts[2]!, parts[1]!];\n default:\n return [parts[0]!, parts[1]!, parts[2]!, parts[3]!];\n }\n}\n\nfunction parseValue(v: unknown): number | string | undefined {\n if (v === undefined || v === null) return undefined;\n const s = String(v);\n if (s === \"auto\") return \"auto\";\n const n = Number(s);\n if (s !== \"\" && !isNaN(n)) return n;\n return s;\n}\n\n/**\n * Expand CSS shorthand properties into their longhand equivalents.\n * Mutates and returns the style object.\n */\nexport function expandStyle(\n raw: RawStyle,\n fontFamilies?: string[],\n): ExpandedStyle {\n const style = { ...raw } as Record<string, unknown>;\n\n // margin shorthand\n if (style.margin !== undefined) {\n const sides = parseSides(String(style.margin));\n for (let i = 0; i < 4; i++) {\n const key = `margin${SIDES[i]}`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.margin;\n }\n\n // padding shorthand\n if (style.padding !== undefined) {\n const sides = parseSides(String(style.padding));\n for (let i = 0; i < 4; i++) {\n const key = `padding${SIDES[i]}`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.padding;\n }\n\n // borderRadius shorthand\n if (style.borderRadius !== undefined) {\n const sides = parseSides(String(style.borderRadius));\n const corners = [\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomRightRadius\",\n \"borderBottomLeftRadius\",\n ];\n for (let i = 0; i < 4; i++) {\n if (style[corners[i]!] === undefined)\n style[corners[i]!] = parseValue(sides[i]);\n }\n delete style.borderRadius;\n }\n\n // borderWidth shorthand\n if (style.borderWidth !== undefined) {\n const sides = parseSides(String(style.borderWidth));\n for (let i = 0; i < 4; i++) {\n const key = `border${SIDES[i]}Width`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.borderWidth;\n }\n\n // borderColor shorthand\n if (style.borderColor !== undefined) {\n const val = style.borderColor;\n for (const side of SIDES) {\n const key = `border${side}Color`;\n if (style[key] === undefined) style[key] = val;\n }\n delete style.borderColor;\n }\n\n // borderStyle shorthand\n if (style.borderStyle !== undefined) {\n const val = style.borderStyle;\n for (const side of SIDES) {\n const key = `border${side}Style`;\n if (style[key] === undefined) style[key] = val;\n }\n delete style.borderStyle;\n }\n\n // border shorthand (e.g. \"1px solid black\")\n if (style.border !== undefined) {\n const parts = String(style.border).split(/\\s+/);\n const width = parseValue(parts[0]);\n const borderStyle = parts[1] ?? \"solid\";\n const color = parts[2] ?? \"black\";\n for (const side of SIDES) {\n if (style[`border${side}Width`] === undefined)\n style[`border${side}Width`] = width;\n if (style[`border${side}Style`] === undefined)\n style[`border${side}Style`] = borderStyle;\n if (style[`border${side}Color`] === undefined)\n style[`border${side}Color`] = color;\n }\n delete style.border;\n }\n\n // Per-side border shorthands (e.g. borderLeft: \"3px solid white\")\n for (const side of SIDES) {\n const key = `border${side}`;\n if (style[key] !== undefined) {\n const parts = String(style[key]).split(/\\s+/);\n const width = parseValue(parts[0]);\n const borderStyle = parts[1] ?? \"solid\";\n const color = parts[2] ?? \"black\";\n if (style[`${key}Width`] === undefined) style[`${key}Width`] = width;\n if (style[`${key}Style`] === undefined)\n style[`${key}Style`] = borderStyle;\n if (style[`${key}Color`] === undefined) style[`${key}Color`] = color;\n delete style[key];\n }\n }\n\n // flex shorthand\n if (style.flex !== undefined) {\n const val = String(style.flex);\n const parts = val.split(/\\s+/);\n if (parts.length === 1) {\n const n = parseFloat(parts[0]!);\n if (!isNaN(n)) {\n if (style.flexGrow === undefined) style.flexGrow = n;\n if (style.flexShrink === undefined) style.flexShrink = 1;\n if (style.flexBasis === undefined) style.flexBasis = 0;\n }\n } else if (parts.length === 2) {\n if (style.flexGrow === undefined) style.flexGrow = parseFloat(parts[0]!);\n if (style.flexShrink === undefined)\n style.flexShrink = parseFloat(parts[1]!);\n } else if (parts.length >= 3) {\n if (style.flexGrow === undefined) style.flexGrow = parseFloat(parts[0]!);\n if (style.flexShrink === undefined)\n style.flexShrink = parseFloat(parts[1]!);\n if (style.flexBasis === undefined) style.flexBasis = parseValue(parts[2]);\n }\n delete style.flex;\n }\n\n // gap shorthand\n if (style.gap !== undefined) {\n const sides = parseSides(String(style.gap));\n if (style.rowGap === undefined) style.rowGap = parseValue(sides[0]);\n if (style.columnGap === undefined) style.columnGap = parseValue(sides[1]);\n delete style.gap;\n }\n\n // background shorthand\n if (style.background !== undefined) {\n const bg = String(style.background);\n if (bg.includes(\"gradient(\") || bg.includes(\"url(\")) {\n if (style.backgroundImage === undefined) style.backgroundImage = bg;\n } else {\n if (style.backgroundColor === undefined) style.backgroundColor = bg;\n }\n delete style.background;\n }\n\n // overflow shorthand\n if (style.overflow !== undefined) {\n if (style.overflowX === undefined) style.overflowX = style.overflow;\n if (style.overflowY === undefined) style.overflowY = style.overflow;\n }\n\n // textBox shorthand (e.g. \"trim-both cap alphabetic\")\n if (style.textBox !== undefined) {\n const val = String(style.textBox);\n if (val === \"normal\" || val === \"none\") {\n style.textBoxTrim ??= \"none\";\n } else {\n const parts = val.split(/\\s+/);\n style.textBoxTrim ??= parts[0];\n if (parts.length > 1) {\n style.textBoxEdge ??= parts.slice(1).join(\" \");\n }\n }\n delete style.textBox;\n }\n\n // fontFamily normalization\n if (typeof style.fontFamily === \"string\") {\n const families = style.fontFamily\n .split(\",\")\n .map((s) => s.trim().replace(/^['\"]|['\"]$/g, \"\"))\n .filter(Boolean);\n if (fontFamilies) {\n const present = new Set(families);\n for (const name of fontFamilies) {\n if (!present.has(name)) families.push(name);\n }\n }\n style.fontFamily = families.join(\", \");\n }\n\n return style as unknown as ExpandedStyle;\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\n/**\n * Style after shorthand expansion but before unit resolution.\n * Properties like fontSize may still contain CSS unit strings (e.g. \"4em\").\n */\nexport type ExpandedStyle = Omit<ComputedStyle, \"fontSize\"> & {\n fontSize?: number | string;\n};\n\n/**\n * Normalized, computed CSS style after shorthand expansion.\n * All dimension values are numbers (pixels) or percentage strings.\n */\nexport type ComputedStyle = {\n // Display & layout\n display?: \"flex\" | \"none\";\n flexDirection?: \"row\" | \"column\" | \"row-reverse\" | \"column-reverse\";\n justifyContent?:\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n alignItems?: \"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"baseline\";\n alignSelf?:\n | \"auto\"\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"stretch\"\n | \"baseline\";\n alignContent?:\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"stretch\"\n | \"space-between\"\n | \"space-around\";\n flexWrap?: \"nowrap\" | \"wrap\" | \"wrap-reverse\";\n flexGrow?: number;\n flexShrink?: number;\n flexBasis?: number | string;\n\n // Dimensions\n width?: number | string;\n height?: number | string;\n minWidth?: number | string;\n minHeight?: number | string;\n maxWidth?: number | string;\n maxHeight?: number | string;\n\n // Position\n position?: \"relative\" | \"absolute\";\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n\n // Margin\n marginTop?: number | string;\n marginRight?: number | string;\n marginBottom?: number | string;\n marginLeft?: number | string;\n\n // Padding\n paddingTop?: number | string;\n paddingRight?: number | string;\n paddingBottom?: number | string;\n paddingLeft?: number | string;\n\n // Border\n borderTopWidth?: number | string;\n borderRightWidth?: number | string;\n borderBottomWidth?: number | string;\n borderLeftWidth?: number | string;\n borderTopColor?: string;\n borderRightColor?: string;\n borderBottomColor?: string;\n borderLeftColor?: string;\n borderTopStyle?: string;\n borderRightStyle?: string;\n borderBottomStyle?: string;\n borderLeftStyle?: string;\n borderTopLeftRadius?: number | string;\n borderTopRightRadius?: number | string;\n borderBottomRightRadius?: number | string;\n borderBottomLeftRadius?: number | string;\n\n // Gap\n rowGap?: number;\n columnGap?: number;\n\n // Overflow\n overflow?: string;\n overflowX?: string;\n overflowY?: string;\n\n // Colors & background\n backgroundColor?: string;\n color?: string;\n opacity?: number;\n backgroundImage?: string;\n backgroundSize?: string;\n\n // Typography\n fontSize?: number;\n fontFamily?: string;\n fontWeight?: number | string;\n fontStyle?: \"normal\" | \"italic\";\n textAlign?: \"left\" | \"center\" | \"right\" | \"justify\";\n textDecoration?: string;\n textTransform?: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\n lineHeight?: number | string;\n letterSpacing?: number | string;\n whiteSpace?: \"normal\" | \"nowrap\" | \"pre\" | \"pre-wrap\" | \"pre-line\";\n wordBreak?: \"normal\" | \"break-all\" | \"break-word\" | \"keep-all\";\n textOverflow?: \"clip\" | \"ellipsis\";\n\n // Box shadow\n boxShadow?: string;\n textShadow?: string;\n\n // Transform\n transform?: string;\n transformOrigin?: string;\n\n // Image\n objectFit?: \"contain\" | \"cover\" | \"fill\" | \"none\" | \"scale-down\";\n\n // Filter\n filter?: string;\n\n // Text box trim\n textBoxTrim?: \"none\" | \"trim-start\" | \"trim-end\" | \"trim-both\";\n textBoxEdge?: string;\n};\n\nconst ROOT_FONT_SIZE = 16;\n\n/**\n * Default styles for the root element.\n */\nexport const DEFAULT_STYLE: ComputedStyle = {\n display: \"flex\",\n flexDirection: \"row\",\n flexWrap: \"nowrap\",\n flexGrow: 0,\n flexShrink: 0,\n alignItems: \"stretch\",\n justifyContent: \"flex-start\",\n position: \"relative\",\n fontSize: ROOT_FONT_SIZE,\n fontWeight: 400,\n fontStyle: \"normal\",\n color: \"black\",\n lineHeight: \"normal\",\n textAlign: \"left\",\n whiteSpace: \"normal\",\n wordBreak: \"normal\",\n textOverflow: \"clip\",\n opacity: 1,\n overflow: \"visible\",\n};\n\n/**\n * CSS properties that are inherited by child elements.\n */\nconst INHERITABLE_PROPS: (keyof ComputedStyle)[] = [\n \"color\",\n \"fontSize\",\n \"fontFamily\",\n \"fontWeight\",\n \"fontStyle\",\n \"textAlign\",\n \"textTransform\",\n \"textDecoration\",\n \"lineHeight\",\n \"letterSpacing\",\n \"whiteSpace\",\n \"wordBreak\",\n \"textOverflow\",\n \"textBoxTrim\",\n \"textBoxEdge\",\n];\n\n/**\n * Resolve the computed style for a node, inheriting from parent where appropriate.\n */\nexport function resolveStyle(\n rawStyle: ExpandedStyle | undefined,\n parentStyle: ComputedStyle,\n): ComputedStyle {\n const style = { ...rawStyle };\n\n // Apply inherited properties\n for (const prop of INHERITABLE_PROPS) {\n if (style[prop] === undefined && parentStyle[prop] !== undefined) {\n (style as Record<string, unknown>)[prop] = parentStyle[prop];\n }\n }\n\n // Resolve fontSize (ensure it's a number, respecting em/rem/etc units)\n if (typeof style.fontSize === \"string\") {\n const parentFontSize =\n typeof parentStyle.fontSize === \"number\"\n ? parentStyle.fontSize\n : ROOT_FONT_SIZE;\n const resolved = resolveUnit(\n style.fontSize,\n 0,\n 0,\n parentFontSize,\n ROOT_FONT_SIZE,\n );\n style.fontSize = typeof resolved === \"number\" ? resolved : parentFontSize;\n }\n\n // Resolve lineHeight: parse string values to numbers but keep multipliers\n // as-is so they're recalculated per-element in text layout (using each\n // element's own fontSize rather than the parent's).\n if (typeof style.lineHeight === \"string\") {\n const str = style.lineHeight;\n if (str.endsWith(\"%\")) {\n style.lineHeight = parseFloat(str) / 100;\n } else {\n const parsed = parseFloat(str);\n if (!isNaN(parsed)) {\n style.lineHeight = parsed;\n }\n }\n }\n\n // Resolve letterSpacing (respecting em/rem/etc units)\n if (typeof style.letterSpacing === \"string\") {\n const currentFontSize =\n typeof style.fontSize === \"number\"\n ? style.fontSize\n : typeof parentStyle.fontSize === \"number\"\n ? parentStyle.fontSize\n : ROOT_FONT_SIZE;\n const resolved = resolveUnit(\n style.letterSpacing,\n 0,\n 0,\n currentFontSize,\n ROOT_FONT_SIZE,\n );\n if (typeof resolved === \"number\") {\n style.letterSpacing = resolved;\n }\n }\n\n return style as ComputedStyle;\n}\n\n/**\n * Dimension properties that may contain CSS units needing resolution.\n */\nconst DIMENSION_PROPS: (keyof ComputedStyle)[] = [\n \"width\",\n \"height\",\n \"minWidth\",\n \"minHeight\",\n \"maxWidth\",\n \"maxHeight\",\n \"top\",\n \"right\",\n \"bottom\",\n \"left\",\n \"marginTop\",\n \"marginRight\",\n \"marginBottom\",\n \"marginLeft\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"rowGap\",\n \"columnGap\",\n \"flexBasis\",\n \"borderTopWidth\",\n \"borderRightWidth\",\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomRightRadius\",\n \"borderBottomLeftRadius\",\n];\n\n/**\n * Resolve a single CSS dimension string to a pixel number.\n * Returns the original value for `%` and `auto` (Yoga handles those),\n * and for values that are already numbers or unrecognised strings.\n */\nfunction resolveUnit(\n value: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n): number | string {\n // Percentages and auto are handled downstream by Yoga\n if (value.endsWith(\"%\") || value === \"auto\") return value;\n\n // Viewport-relative units\n if (value.endsWith(\"vmin\")) {\n const n = parseFloat(value);\n return isNaN(n)\n ? value\n : (n / 100) * Math.min(viewportWidth, viewportHeight);\n }\n if (value.endsWith(\"vmax\")) {\n const n = parseFloat(value);\n return isNaN(n)\n ? value\n : (n / 100) * Math.max(viewportWidth, viewportHeight);\n }\n if (value.endsWith(\"vw\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : (n / 100) * viewportWidth;\n }\n if (value.endsWith(\"vh\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : (n / 100) * viewportHeight;\n }\n\n // Font-relative units\n if (value.endsWith(\"rem\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * rootFontSize;\n }\n if (value.endsWith(\"em\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * fontSize;\n }\n\n // Absolute units (CSS reference pixel = 1/96 inch)\n if (value.endsWith(\"px\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n;\n }\n if (value.endsWith(\"pt\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 72);\n }\n if (value.endsWith(\"pc\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * 16;\n }\n if (value.endsWith(\"in\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * 96;\n }\n if (value.endsWith(\"cm\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 2.54);\n }\n if (value.endsWith(\"mm\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 25.4);\n }\n\n return value;\n}\n\n/**\n * Resolve CSS units (vw, vh, vmin, vmax, em, rem, px, pt, pc, in, cm, mm)\n * in a style object to pixel values. Percentages and `auto` pass through\n * unchanged for Yoga to handle.\n */\nexport function resolveUnits(\n style: ComputedStyle,\n viewportWidth: number,\n viewportHeight: number,\n rootFontSize: number = ROOT_FONT_SIZE,\n): ComputedStyle {\n const fontSize =\n typeof style.fontSize === \"number\" ? style.fontSize : rootFontSize;\n\n for (const prop of DIMENSION_PROPS) {\n const value = style[prop];\n if (typeof value !== \"string\") continue;\n const resolved = resolveUnit(\n value,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n if (resolved !== value) {\n (style as Record<string, unknown>)[prop] = resolved;\n }\n }\n\n // Resolve CSS length units inside transform strings so that by draw time\n // values are either bare numbers or `%` (which need element dimensions).\n if (style.transform) {\n style.transform = resolveTransformUnits(\n style.transform,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n }\n if (style.transformOrigin) {\n style.transformOrigin = resolveTransformUnits(\n style.transformOrigin,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n }\n\n return style;\n}\n\n/**\n * Resolve CSS length units (vw, vh, em, rem, px, etc.) inside a transform or\n * transformOrigin string. Percentages and angle units (deg, rad, turn) are\n * left untouched — percentages need element dimensions (available at draw time)\n * and angle units are not lengths.\n */\nfunction resolveTransformUnits(\n transform: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n): string {\n return transform.replace(\n /(-?\\d*\\.?\\d+)(vw|vh|vmin|vmax|em|rem|px|pt|pc|in|cm|mm)\\b/g,\n (match) => {\n const resolved = resolveUnit(\n match,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n return typeof resolved === \"number\" ? String(resolved) : match;\n },\n );\n}\n\n/**\n * Resolve a dimension value (width, height, margin, etc.) to pixels.\n * Percentage values are resolved relative to the provided container size.\n */\nexport function resolveDimension(\n value: number | string | undefined,\n containerSize: number,\n): number | undefined {\n if (value === undefined || value === \"auto\") return undefined;\n if (typeof value === \"number\") return value;\n const s = String(value);\n if (s.endsWith(\"%\")) {\n return (parseFloat(s) / 100) * containerSize;\n }\n const n = parseFloat(s);\n return isNaN(n) ? undefined : n;\n}\n","import Yoga, {\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n} from \"yoga-layout\";\nimport type { Node as YogaNode } from \"yoga-layout\";\n\nexport type { YogaNode };\n\nexport {\n Yoga,\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n};\n\nexport function createYogaNode(): YogaNode {\n return Yoga.Node.create();\n}\n\nexport function freeYogaNode(node: YogaNode): void {\n node.freeRecursive();\n}\n","import {\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n} from \"../yoga.ts\";\nimport type { YogaNode } from \"../yoga.ts\";\nimport type { ComputedStyle } from \"./compute.ts\";\n\n/**\n * Apply computed CSS styles to a Yoga node.\n */\nexport function applyStylesToYoga(node: YogaNode, style: ComputedStyle): void {\n // Display\n if (style.display === \"none\") {\n node.setDisplay(Display.None);\n } else {\n node.setDisplay(Display.Flex);\n }\n\n // Flex direction (CSS default is \"row\", Yoga defaults to \"column\")\n {\n const map: Record<string, FlexDirection> = {\n row: FlexDirection.Row,\n \"row-reverse\": FlexDirection.RowReverse,\n column: FlexDirection.Column,\n \"column-reverse\": FlexDirection.ColumnReverse,\n };\n node.setFlexDirection(\n map[style.flexDirection ?? \"row\"] ?? FlexDirection.Row,\n );\n }\n\n // Justify content\n if (style.justifyContent) {\n const map: Record<string, Justify> = {\n \"flex-start\": Justify.FlexStart,\n \"flex-end\": Justify.FlexEnd,\n center: Justify.Center,\n \"space-between\": Justify.SpaceBetween,\n \"space-around\": Justify.SpaceAround,\n \"space-evenly\": Justify.SpaceEvenly,\n };\n const jc = map[style.justifyContent];\n if (jc !== undefined) node.setJustifyContent(jc);\n }\n\n // Align items\n if (style.alignItems) {\n const map: Record<string, Align> = {\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n baseline: Align.Baseline,\n };\n const ai = map[style.alignItems];\n if (ai !== undefined) node.setAlignItems(ai);\n }\n\n // Align self\n if (style.alignSelf) {\n const map: Record<string, Align> = {\n auto: Align.Auto,\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n baseline: Align.Baseline,\n };\n const as_ = map[style.alignSelf];\n if (as_ !== undefined) node.setAlignSelf(as_);\n }\n\n // Align content\n if (style.alignContent) {\n const map: Record<string, Align> = {\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n \"space-between\": Align.SpaceBetween,\n \"space-around\": Align.SpaceAround,\n };\n const ac = map[style.alignContent];\n if (ac !== undefined) node.setAlignContent(ac);\n }\n\n // Flex wrap\n if (style.flexWrap) {\n const map: Record<string, Wrap> = {\n nowrap: Wrap.NoWrap,\n wrap: Wrap.Wrap,\n \"wrap-reverse\": Wrap.WrapReverse,\n };\n const fw = map[style.flexWrap];\n if (fw !== undefined) node.setFlexWrap(fw);\n }\n\n // Flex grow / shrink / basis\n if (style.flexGrow !== undefined) node.setFlexGrow(style.flexGrow);\n // Satori defaults flexShrink to 0 (React Native convention); match it for compatibility\n node.setFlexShrink(style.flexShrink ?? 0);\n if (style.flexBasis !== undefined) {\n if (typeof style.flexBasis === \"number\") {\n node.setFlexBasis(style.flexBasis);\n } else if (String(style.flexBasis).endsWith(\"%\")) {\n node.setFlexBasis(String(style.flexBasis) as `${number}%`);\n } else if (style.flexBasis === \"auto\") {\n node.setFlexBasis(\"auto\");\n } else {\n const n = parseFloat(String(style.flexBasis));\n if (!isNaN(n)) node.setFlexBasis(n);\n }\n }\n\n // Dimensions\n applyDimension(node, \"setWidth\", style.width);\n applyDimension(node, \"setHeight\", style.height);\n applyDimension(node, \"setMinWidth\", style.minWidth);\n applyDimension(node, \"setMinHeight\", style.minHeight);\n applyDimension(node, \"setMaxWidth\", style.maxWidth);\n applyDimension(node, \"setMaxHeight\", style.maxHeight);\n\n // Position\n if (style.position === \"absolute\") {\n node.setPositionType(PositionType.Absolute);\n } else {\n node.setPositionType(PositionType.Relative);\n }\n\n // Position edges\n applyEdgeValue(node, \"setPosition\", Edge.Top, style.top);\n applyEdgeValue(node, \"setPosition\", Edge.Right, style.right);\n applyEdgeValue(node, \"setPosition\", Edge.Bottom, style.bottom);\n applyEdgeValue(node, \"setPosition\", Edge.Left, style.left);\n\n // Margin\n applyEdgeValue(node, \"setMargin\", Edge.Top, style.marginTop);\n applyEdgeValue(node, \"setMargin\", Edge.Right, style.marginRight);\n applyEdgeValue(node, \"setMargin\", Edge.Bottom, style.marginBottom);\n applyEdgeValue(node, \"setMargin\", Edge.Left, style.marginLeft);\n\n // Padding\n applyEdgeValue(node, \"setPadding\", Edge.Top, style.paddingTop);\n applyEdgeValue(node, \"setPadding\", Edge.Right, style.paddingRight);\n applyEdgeValue(node, \"setPadding\", Edge.Bottom, style.paddingBottom);\n applyEdgeValue(node, \"setPadding\", Edge.Left, style.paddingLeft);\n\n // Border width (resolved to numbers by resolveUnits before this point)\n if (style.borderTopWidth !== undefined)\n node.setBorder(Edge.Top, style.borderTopWidth as number);\n if (style.borderRightWidth !== undefined)\n node.setBorder(Edge.Right, style.borderRightWidth as number);\n if (style.borderBottomWidth !== undefined)\n node.setBorder(Edge.Bottom, style.borderBottomWidth as number);\n if (style.borderLeftWidth !== undefined)\n node.setBorder(Edge.Left, style.borderLeftWidth as number);\n\n // Gap\n if (style.rowGap !== undefined) node.setGap(Gutter.Row, style.rowGap);\n if (style.columnGap !== undefined)\n node.setGap(Gutter.Column, style.columnGap);\n\n // Overflow\n if (\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\"\n ) {\n node.setOverflow(Overflow.Hidden);\n } else {\n node.setOverflow(Overflow.Visible);\n }\n}\n\nfunction applyDimension(\n node: YogaNode,\n setter:\n | \"setWidth\"\n | \"setHeight\"\n | \"setMinWidth\"\n | \"setMinHeight\"\n | \"setMaxWidth\"\n | \"setMaxHeight\",\n value: number | string | undefined,\n): void {\n if (value === undefined) return;\n if (value === \"auto\") {\n if (setter === \"setWidth\" || setter === \"setHeight\") {\n node[setter](\"auto\");\n }\n return;\n }\n if (typeof value === \"number\") {\n node[setter](value);\n return;\n }\n const s = String(value);\n if (s.endsWith(\"%\")) {\n node[setter](s as `${number}%`);\n } else {\n const n = parseFloat(s);\n if (!isNaN(n)) node[setter](n);\n }\n}\n\nfunction applyEdgeValue(\n node: YogaNode,\n setter: \"setMargin\" | \"setPadding\" | \"setPosition\",\n edge: Edge,\n value: number | string | undefined,\n): void {\n if (value === undefined) return;\n if (value === \"auto\" && setter === \"setMargin\") {\n node.setMargin(edge, \"auto\");\n return;\n }\n if (typeof value === \"number\") {\n node[setter](edge, value);\n return;\n }\n const s = String(value);\n if (s.endsWith(\"%\")) {\n node[setter](edge, s as `${number}%`);\n } else {\n const n = parseFloat(s);\n if (!isNaN(n)) node[setter](edge, n);\n }\n}\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\nimport type { ReactNode } from \"react\";\n\nimport type { RenderReactElementOptions } from \"../types.ts\";\nimport { drawNode } from \"./draw/index.ts\";\nimport { ensureFontsRegistered } from \"./font.ts\";\nimport { buildLayoutTree } from \"./layout.ts\";\n\n/**\n * Render a React element tree to a canvas context.\n *\n * Width and height are taken from the canvas itself (`ctx.canvas.width` /\n * `ctx.canvas.height`).\n *\n * @param ctx - Canvas 2D rendering context to draw into\n * @param element - React element tree to render\n * @param options - Rendering options (fonts, debug mode)\n *\n * @example\n * ```tsx\n * import { createCanvas, renderReactElement } from \"@effing/canvas\";\n *\n * const canvas = createCanvas(1080, 1080);\n * const ctx = canvas.getContext(\"2d\");\n *\n * await renderReactElement(ctx, <MyComponent />, { fonts: [myFont] });\n *\n * const png = canvas.encodeSync(\"png\");\n * ```\n */\nexport async function renderReactElement(\n ctx: SKRSContext2D,\n element: ReactNode,\n options: RenderReactElementOptions,\n): Promise<void> {\n // Register fonts\n ensureFontsRegistered(options.fonts);\n\n // Get dimensions from canvas\n const width = ctx.canvas.width;\n const height = ctx.canvas.height;\n\n // Build layout tree (Yoga)\n const emojiStyle =\n options.emoji === \"none\" ? undefined : (options.emoji ?? \"twemoji\");\n const fontFamilies = [...new Set(options.fonts.map((f) => f.name))];\n const layoutTree = await buildLayoutTree(\n element,\n width,\n height,\n ctx,\n !!emojiStyle,\n fontFamilies,\n );\n\n // Draw to canvas\n await drawNode(ctx, layoutTree, 0, 0, options.debug ?? false, emojiStyle);\n}\n"],"mappings":"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","names":["GlobalFonts","loadImage","createCanvas","loadImage","loadImage","measureText","loadImage","canvas","createCanvas","loadImage","loadImage","style","children","loadImage","createCanvas"]}
|