- Use twirlwind for CSS-to-Tailwind class conversion instead of
450 lines of manual lookup tables and formatting functions
- Build a CSS style object from scene node properties, pass to twirl()
- Remove design-jsx/tailwind.ts (pxToSpacing, colorToTwClass, etc.)
- Remove unused Tailwind-specific helpers from jsx/helpers.ts
- Update tests for twirlwind's v4-native output format
- shapeTextForClipboard() now processes all lines, not just the first
- buildFigmaClipboardHTML() passes CanvasKit-shaped positions to
derivedTextData when available (browser with CanvasKit loaded)
- Add @chenglou/pretext for proper Unicode-aware word wrapping as
fallback when CanvasKit isn't available (CLI, headless, .fig export)
- Falls back to basic word-boundary wrapping if pretext fails
Replace hand-rolled regex heuristic with proper acorn JS parsing.
The AST correctly identifies ExpressionStatement as the last node
regardless of trailing semicolons, comments, or complex syntax.
Fixes edge cases like '42;' which the regex wrongly treated as a
statement.
Co-authored-by: stiff <v.stiff@gmail.com>
Co-authored-by: Jais Pedersen <jais@pedersens.net>
Use @ai-sdk/deepseek instead of openai-compatible, which properly
handles reasoning_content in conversation history. DeepSeek V4
requires reasoning_content on every assistant turn — the dedicated
provider backfills it automatically.
Adds DeepSeek V3 and R1 models to the provider list.
Vector PDF output via jsPDF + svg2pdf.js (lazy-loaded, 124KB gzipped).
Reuses existing SVG export pipeline — text stays selectable, paths
stay sharp at any zoom.
- packages/core/src/io/formats/pdf/ — SVG→PDF conversion module
- export_pdf tool for MCP/AI
- PDF format in IO registry and app export panel
- CLI: bun open-pencil export file.fig --format pdf
- Upgrade @open-pencil/yoga-layout to include free() and freeRecursive()
- freeYogaTree() in layout.ts now properly releases WASM memory
- FinalizationRegistry remains as a safety net for missed cleanup
Fixes#183
- Move clipboard-text-outlines.ts → text/opentype.ts
- Move kiwi/serialize-clipboard-v4.ts → text/clipboard-derived-text.ts
- Delete types-opentype.d.ts in favor of @types/opentype.js
- Add opentype.js to core package dependencies
- Add Vite alias for opentype.js ESM resolution
- Update all imports across core, kiwi, clipboard, and tests
* chore: remove unused pi context file
- Delete .pi/context.md
- Remove an unused local context artifact from the repository
* Add clipboard text v4 export
* fix(clipboard): rebase v4 export branch onto master
- Resolve conflicts after the core text module reorganization
- Fix clipboard text export imports and bundled font asset loading
- Update raw binary expectations for textUserLayoutVersion 4
- Re-run check and unit tests after the rebase
Adds a new scenario to the pen tool specifications defining the behavior for relocating the active vertex with spacebar during a curve drag, including asserting that the cursor remains a crosshair instead of switching to the hand tool.
Made-with: Cursor
nanostores + @nanostores/i18n + @nanostores/vue (~6 KB total).
English base translations defined inline in messages.ts, other
locales loaded on demand from JSON. Grouped by domain: menu,
commands, tools, panels, pages, dialogs.
useI18n() composable returns reactive translation objects plus
locale controls. Russian locale included as first translation.
Browser language auto-detected, user preference persisted in
localStorage.
- Add interaction constants to core barrel export (were in constants.ts
but not reachable via '@open-pencil/core')
- Fix variable shadowing in use-text-edit.ts: rename inner 'editor'
(textEditor) to 'textEd' to avoid shadowing the Editor parameter
- Fix unused params: prefix with _ in scene.ts, describe-issues.ts, xpath.ts
- Remove unused getCoords param from setupPanZoom
- Move cursorCanvasX/Y assignment to app callback (not on EditorState)
- Simplify EditorStore return: spread editor instead of listing 80+ methods
individually — new Editor methods auto-forward, no more manual sync
- Add tsgo to check script, add check:vue script for vue-tsc
- Add vue-tsc as dev dependency
- Reduces vue-tsc errors from 172 (pre-existing) to 135 (37 fixed)
Renderless components (Reka UI-style) exposing editor logic via slots:
- OpenPencilProvider — injects editor via Vue provide/inject
- OpenPencilCanvas — CanvasKit/Skia surface with render loop
- PageList, LayerTree, ToolSelector, NodeProperties — slot-based
Composables:
- useEditor() — access editor from any descendant
- useCanvas() — low-level surface lifecycle (moved from app)
The app's use-canvas.ts is now a 2-line re-export from the SDK.
Includes example app in packages/vue/example/.
Remove headless SceneGraph mode — the MCP server now always proxies
tool calls to the browser via WebSocket. One server, one architecture:
HTTP :7600 — /health, /rpc (CLI), /mcp (MCP Streamable HTTP)
WS :7601 — browser connects, executes tool calls against live editor
- Delete http.ts (merged into server.ts)
- Delete headless SceneGraph, open_file, save_file, new_document
- Delete canvaskit-wasm dependency (no headless rendering)
- Add ws dependency for WebSocket server
- Rewrite tests with mock browser over real HTTP+WebSocket
- Simplify bridge.ts to 6 lines (just imports and starts the server)
- Replace ssrLoadModule hacks with direct imports from @open-pencil/core
- Replace isBunRuntime() hack with @hono/node-server (works everywhere)
- Remove ViteServer type parameter from startAutomationBridge
- Upgrade @open-pencil/mcp zod dependency from v3 to v4
- Add @open-pencil/mcp as root devDependency for bridge imports
Replace npm vue-stream-markdown with open-pencil fork that guards
bundledThemesInfo/bundledLanguagesInfo with ?. to prevent TypeError
when shiki is not installed. Revert shiki shim and cdn-options hacks.