openpencil/tests/engine
mcdmags c847eab75c
feat(mcp): add export_image_file tool and fix headless PNG rendering (#108)
* feat(mcp): add export_image_file tool — saves PNG/JPG/WEBP to disk

The existing export_image tool returns base64 inline, which MCP clients
display in chat but don't save to disk. This new tool writes the image
directly to a file path, making exports usable for documentation,
mockup reviews, and CI pipelines.

Parameters:
- path: absolute file path to save (required)
- ids: node IDs to export (optional, defaults to all top-level nodes)
- format: PNG | JPG | WEBP (default: PNG)
- scale: 0.1–4 (default: 2)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(mcp): add export_image_file tool and fix headless PNG rendering

**New tool: `export_image_file`**
Saves rendered PNG/JPG/WEBP images directly to a file path on disk.
The existing `export_image` returns base64 inline — useful for chat
but doesn't produce files. AI agents and CI pipelines need actual files.

Path validation runs before the expensive render call. The tool
respects `fileRoot` restrictions.

**Fix: headless PNG rendering now matches the editor**

1. `computeAllLayouts()` called after `render` creates nodes via JSX.
2. Bundled Inter font loaded from disk — tries `../fonts/` (installed
   package) then `../../public/` (project root). The web-based
   `fetch('/Inter-Regular.ttf')` fails in Node.js.
3. Text measurement uses `renderer.measureTextNode()` — the same
   ParagraphBuilder the renderer uses to draw text. Measurement and
   rendering use the same SkiaRenderer instance, same fontProvider,
   same font shaping. Zero hacks.

Export pipeline:
  ensureInterFont() → SkiaRenderer + loadFonts() →
  setTextMeasurer(renderer.measureTextNode) →
  computeAllLayouts() → renderNodesToImage()

**Tests added** (6 new tests in mcp-server.test.ts):
- export_image_file produces valid PNG after render
- export_image_file without ids exports all page children
- export_image_file without document returns error
- export_image_file with out-of-root path returns error
- JPG and WEBP formats produce non-empty output
- export_image_file is listed in tools

* Remove .cue directory and revert .gitignore changes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Move computeAllLayouts into renderTree, reuse exportImage in MCP

computeAllLayouts was in the render tool but renderJSX has multiple
callers (render, replace_node, automation server). Moving it into
renderTree ensures layout is always computed after JSX rendering.

export_image_file in MCP server was duplicating export_image logic.
Now delegates to exportImage.execute and just handles the file write.

---------

Co-authored-by: Michael Magsuci <mcdmag@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Danila Poyarkov <dev@dannote.net>
2026-03-14 18:43:50 +03:00
..
abspos-cache.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
acp-agent.test.ts Add ACP agent package with tests 2026-03-05 09:14:54 +03:00
clipboard.test.ts Add gold-preview.fig clipboard roundtrip tests 2026-03-12 17:05:00 +03:00
color.test.ts Centralize all color utilities in color.ts 2026-03-07 10:02:11 +03:00
copy.test.ts Fix copyFill missing gradientTransform/imageTransform, add copy tests 2026-03-09 08:50:28 +03:00
effects-and-resize.test.ts Fix effects rendering: shadows, blur, spread (#24) 2026-03-03 09:53:39 +03:00
eval-cli.test.ts Fix hit-testing: scope hover to current page, click-through empty containers 2026-03-05 08:56:35 +03:00
export-jsx.test.ts CSS Grid layout mode (#73) 2026-03-08 18:23:53 +03:00
fig-export-worker.test.ts Fix .fig export roundtrip: variable GUIDs colliding with document 2026-03-13 13:27:15 +03:00
fig-import.test.ts Don't clip content on group-like frames (resizeToFit) 2026-03-13 19:43:52 +03:00
fig-roundtrip.test.ts Fix text rendering with wrong fonts on file open 2026-03-12 22:05:59 +03:00
figma-api.test.ts Fix layout axis mismatch, reduce describe noise, add bail-out strategy 2026-03-13 10:21:46 +03:00
fonts.test.ts Fix text rendering with wrong fonts on file open 2026-03-12 22:05:59 +03:00
iconify.test.ts Address PR #94 review: dedup, replace hand-rolled code, cleanup 2026-03-13 14:46:18 +03:00
image.test.ts Image drag-and-drop, clipboard paste, and paste-at-cursor (#92) 2026-03-11 07:52:04 +03:00
individual-strokes.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
instance-overrides.test.ts Fix instance swap override propagation through clone chains 2026-03-13 18:58:33 +03:00
label-cache.test.ts Perf: 5.4× faster file open, worker-based parsing, instance index (#96) 2026-03-12 14:49:28 +03:00
layout.test.ts Fix layout axis mismatch, reduce describe noise, add bail-out strategy 2026-03-13 10:21:46 +03:00
mcp-server.test.ts feat(mcp): add export_image_file tool and fix headless PNG rendering (#108) 2026-03-14 18:43:50 +03:00
mcp.test.ts Fix hit-testing: scope hover to current page, click-through empty containers 2026-03-05 08:56:35 +03:00
multi-selection.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
mutation.test.ts Add mutation unit tests: toggleBoldInRange, vectorNetworkBlob precision, SceneGraph+UndoManager integration 2026-03-07 23:11:03 +03:00
perf.bench.ts Fix copyFill missing gradientTransform/imageTransform, add copy tests 2026-03-09 08:50:28 +03:00
profiler.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
render-text.test.ts Fix text rendering with wrong fonts on file open 2026-03-12 22:05:59 +03:00
render.test.ts Optimize AI token usage: ~61% reduction in per-step context 2026-03-13 10:20:56 +03:00
renderer-effects.test.ts Use child shape for drop shadows on transparent containers 2026-03-14 12:25:51 +03:00
scene-graph.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
snap.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
style-runs.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
svg-export.test.ts SVG export (#52) 2026-03-05 10:31:02 +03:00
svg-path-parse.test.ts Add step budget warnings and Continue button for AI chat 2026-03-13 10:18:20 +03:00
tailwind-jsx.test.ts CSS Grid layout mode (#73) 2026-03-08 18:23:53 +03:00
text-editor.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
tools-ai-adapter.test.ts Unify tool definitions: define once, adapt for AI/CLI/MCP 2026-03-01 15:02:05 +03:00
tools-cli.test.ts Fix hit-testing: scope hover to current page, click-through empty containers 2026-03-05 08:56:35 +03:00
tools.test.ts XPath query for node selection (#82) 2026-03-09 15:32:27 +03:00
undo.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
vector.test.ts Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests 2026-03-06 22:33:10 +03:00
xpath.test.ts XPath query for node selection (#82) 2026-03-09 15:32:27 +03:00