Initial commit: Tauri + CanvasKit + React editor scaffold
- Tauri v2 desktop shell with 1280x800 window
- CanvasKit WASM (Skia) rendering via WebGL2
- Scene graph with typed nodes (Frame, Rectangle, Ellipse, Line, etc.)
- Skia renderer with fills, strokes, rounded corners, opacity, rotation
- Selection system with resize handles
- Undo/redo manager (inverse command pattern with batching)
- Bottom toolbar (Select, Frame, Rect, Ellipse, Line) matching Figma UI3
- Left layers panel, right properties panel
- Pan (scroll), zoom (Ctrl+scroll toward cursor)
- Keyboard shortcuts: V/F/R/O/L for tools, Cmd+Z undo, Backspace delete
- 5 demo shapes rendered on canvas
2026-02-27 12:48:29 +00:00
{
"name" : "open-pencil-app" ,
2026-09-18 13:19:49 +00:00
"version" : "0.15.1" ,
Refactor architecture boundaries across core, app, and packages (#234)
* refactor(core): decompose editor factory and action modules
Split the monolithic editor factory and large action modules into focused
domain helpers:
- create.ts assembles context through bridge modules (clipboard,
components, structure, undo) and delegates to graph-reads, graph-events,
layout-runner, component-sync, and state factory
- structure.ts delegates to group, container-wrap, auto-layout-wrap,
reorder, and state-toggle helpers
- selection.ts delegates to hit-test, overlays, container navigation,
and read helpers
- clipboard.ts delegates to subtree-history, images, export, copy,
fonts, and placement helpers
- shapes.ts delegates to pen actions and section-adopt
- components.ts delegates to focus and instances helpers
- alignment.ts delegates to flip-rotate helper
- text.ts uses explicit TextEditSession for snapshot comparison
New focused modules: nudge, variable-bindings, layout-mode,
page-viewports, tool-registry, color-space
Undo: history/position and history/snapshot helpers, hardened
batch/rollback with nested batch support and configurable limit
* refactor(core): split tool definitions by domain
Split the monolithic tool registry into domain-specific modules:
- read/ — selection, find, pages, fonts, components, nodes, query, jsx
- create/ — basic shapes, components, vector, JSX render
- modify/ — paint, effects, geometry, layout, state, text, update
- structure/ — basic, arrange, batch, hierarchy, replace, tree
- variables/ — bindings, collections, read, values
- vector/ — boolean, path, export, viewport
- analyze/ — colors, typography, spacing, clusters, diff, eval
- describe/ — summaries, tree, roles, layout-issues
- stock-photo/ — providers, requests, apply
- codegen/ — component-map, tokens
Split registry into core/extended tiers; refine schema and AI adapter
* refactor(core): restructure kiwi codec and instance overrides
Reorganize the Kiwi .fig codec into domain subdirectories:
- binary/ — codec, schema, protocol
- fig/ — file, import, parse (core, worker, transfer)
- node-change/ — convert, export-node, serialize, plugin-data
- instance-overrides/ — constraints, dsd, populate, props, resolve,
symbol-overrides, symbol-props, sync, types
Vendored kiwi-schema/ left isolated
* refactor(core): split profiler, icons, IO, and add subpath exports
Profiler: speedscope-export, capture-session, hud-controller
Icons: api, svg, types, render, create-icons tool
IO: format registry and subpath exports
Canvas/color/text/vector: targeted cleanup
Add deliberate subpath exports: random, xpath, vector, color, canvas,
scene-graph, kiwi, design-jsx, io, tools, editor, layout, canvaskit,
profiler, text, lint, rpc, figma-api, constants
* refactor(vue): decompose canvas input, surface lifecycle, and controls
Canvas surface: gl-surface, kit-loader, render-loop, resize-observer
Canvas input handlers:
- move: drop-target, move-snap, duplicate-drag
- select: select-move, select-hover, select-hit
- resize: resize-rect, resize-vector, resize-start
- transform: rotation, marquee, pan, text-selection
- text-edit: navigation, clipboard, textarea lifecycle
- Shared: click-count, space-key, pan, pan-zoom, draw, raf-scheduler
Editor composition:
- commands split: actions, context, metadata, edit, selection, view
- menu-model split: command-groups, builders, types
- Gradient stop composable reuse in primitive root
Controls: fill, layout, typography, appearance, effects, stroke,
okhcl, prop-scrub, node-props, undo-batch, color-variable-binding
Variables/i18n/document/export helpers
Organize canvas, primitives, controls, editor, and variables into
cohesive module directories with package-local import aliases
Expose MenuActionNode/MenuSeparatorNode from public API
* refactor(app): split document IO, editor session, and automation bridge
Document IO: source-state, naming, writer, reload-source, reload-state,
imported-document, watch-targets, save-targets
Editor session: create, modules, types, accessors, computed, refs
Editor canvas: loader-overlay, collaboration-awareness,
context-selection, menu-actions, menu-model
Automation bridge: eval, tools, exports, files, selection, RPC fallback
AI/ACP: transport, map-update, permission, debug, chat effects/storage
Collab: awareness, graph-bindings, yjs-sync, follow, session, types
Shell keyboard: actions, bindings, clipboard, focus, nudging,
raw-events, registry, reserved, shortcuts, space-tool
Shell menu: app-menu, document-name, entry, files
Demo: colors, effects, helpers, section builders (components,
app-preview, effects, standalone, variables) — document.ts reduced
from 981 to 32 lines as pure orchestrator
Move app modules under src/app/ with organized domain structure:
editor, document, ai, collab, shell, automation, demo, tabs
* refactor(app): decompose UI components with provide/inject context
Split monolithic components using Reka UI-inspired namespace folders
with scoped provide/inject context — no prop drilling:
- CollabPanel/ — context, avatars, share, connected, join
- ColorPickerPanel/ — context, area, format, field groups, sliders
- MobileHud/ — context, action toast, tool badge, file menu, presence
- ProviderSettings/ — context, API key/type, endpoint, tokens, photos
- Toolbar/ — actions, types, desktop, mobile, tool button, flyout
- LayoutSection/ — types, auto-layout, flex, grid, padding, size, clip
Properties helpers: fill-okhcl adapter, fill-label, color-style-row
Menu: entry helpers, document-name rename, stale type removal
* refactor(mcp): split server into focused modules
- browser-rpc — WebSocket client management
- mcp-sessions — session lifecycle
- tool-output — response formatting
- tool-schema — Zod schema generation from ToolDefs
- jsx-preprocess — JSX source transformation
- result — result helpers
- tool-registration — MCP tool wiring
- auth — API key validation
- http-options — CORS/request handling
- stdio-bridge — stdio transport adapter
* refactor(cli): split analyze subcommands and shared helpers
- Analyze subcommands: clusters, colors, spacing, typography
- RPC data loading helper
- Migrate imports to targeted core subpath exports
* refactor(docs): split VitePress config and shared table component
Config helpers: sdk-sidebar, seo, labels, sidebars, locale-theme,
root-theme, locales
Shared SdkDataTable component replaces duplicated table markup in
SdkPropsTable, SdkEventsTable, and SdkSlotsTable
Update contributing and testing docs
* refactor(tauri): decompose desktop entrypoint
Split lib.rs into focused service modules:
- fig_container.rs — .fig archive/compression commands
- fonts.rs — font cache and system font enumeration
- menu.rs — native menu construction
- menu_events.rs — menu event dispatch and devtools toggle
- window.rs — main window show/focus lifecycle
* test: share domain test factories and migrate fixtures
New shared helpers:
- tests/helpers/scene.ts — makeSceneGraph factory
- tests/helpers/vector-network.ts — vertex/segment/network builders
- tests/helpers/fig-traversal.ts — all-node collection, type counts
- tests/helpers/undo.ts — undo test utilities
- tests/helpers/editor-history.ts — editor history test helpers
Migrate render, vector, fig-roundtrip, and undo tests to use shared
factories instead of inline fixture construction
* build: add structural lint rules, split vite config, update docs
Structural lint (oxlint.structure.json + lint/plugin.js):
- 20+ custom rules enforcing package boundaries, lifecycle patterns,
naming conventions, and import discipline
Vite config split: raw-markdown, canvaskit-assets, pwa, server,
aliases, automation plugins
Remove legacy shims and utils superseded by SDK/core modules
Update AGENTS.md, CONTRIBUTING.md, eval-command docs, tsconfig
* fix(vue): normalize canvas directory casing and remove duplicate export
- Rename Canvas/ to canvas/ in git index to match #vue/canvas/* imports
(PascalCase was correct for component primitives but canvas/ is a
non-component domain directory)
- Remove duplicate ./random subpath export in core package.json
* fix: add #vue and #core Vite resolve aliases for dev server
* refactor(core): reduce remaining large modules
Split the remaining large core hotspots into cohesive domain modules while preserving public facades and behavior.
- Extract scene graph types, variables, node defaults, and vector-network helpers
- Decompose canvas renderer orchestration, state, paints, colors, lifecycle, labels, and delegated domain methods into renderer/ and labels/ subfolders
- Split Kiwi node-change, binary variable binding, layout, RPC, vector, JSX export, clipboard, design JSX, and Figma proxy helpers
- Replace collision-driven *Fn import aliases with namespace imports and enforce the pattern in lint
Validation:
- bun run check
- bun --filter @open-pencil/vue build
- bun run test:dupes
* fix(app): forward color input attrs
* fix(app): cover section drawing errors
* fix(editor): undo option-drag duplicates
* docs: document domain subfolder convention
* fix(app): handle undo redo on keydown
* refactor(app): dispatch shortcuts from keydown
* refactor: group prefixed domain modules
* refactor(app): use tinykeys for shortcuts
* refactor(core): group symbol override modules
* refactor(core): group fig kiwi container helper
* refactor(canvas): split overlay rendering modules
* refactor(vue): remove unused internal barrels
* fix(app): lay out demo components before instancing
* fix(app): restore demo badge spacing
* perf(canvas): split scene and overlay rendering
* refactor(vue): wrap wheel gesture lifecycle
* fix(canvas): wait for fonts before hiding loader
* docs: update unreleased changelog
2026-04-30 12:14:19 +00:00
"private" : true ,
2026-03-02 05:31:54 +00:00
"license" : "MIT" ,
Sync specs & docs: variables, image export, CLI, core extraction
- Update specs: scene-graph (variables/collections/modes/bindings/.fig import),
editor-ui (VariablesPanel, ExportSection, splash), canvas-rendering
(variable resolution, image export, sceneVersion/renderVersion),
desktop-app (monorepo), tooling (Bun workspace), testing (variable tests)
- Create cli spec: info, tree, find, export commands
- Update docs: features, figma-comparison (79/150), roadmap (Phase 4 ✅,
Phase 5 🟡), keyboard-shortcuts (⇧⌘E), contributing (monorepo structure)
- Restore vitepress devDependency lost during merge
- Archive sync-variables-export-cli change
2026-02-28 23:17:48 +00:00
"workspaces" : [
2026-07-01 09:56:45 +00:00
"packages/scene-graph" ,
"packages/pen" ,
"packages/kiwi" ,
"packages/fig" ,
"packages/core" ,
"packages/dom-css" ,
"packages/vue" ,
"packages/cli" ,
"packages/mcp" ,
2026-08-19 14:41:10 +00:00
"packages/harness" ,
2026-08-13 10:50:28 +00:00
"packages/docs" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"tools" ,
"tools/checks/architecture" ,
"tools/checks/docs" ,
"tools/checks/i18n" ,
"tools/checks/lint" ,
"tools/checks/package-quality" ,
"tools/checks/secret-scan" ,
"tools/checks/test-homes" ,
"tools/checks/type-shapes" ,
"tools/ci/images" ,
"tools/ci/policy" ,
"tools/ci/pr-review-guidance" ,
"tools/dev/dev-server" ,
"tools/dev/navigation-benchmark" ,
"tools/dev/unit-tests" ,
"tools/generate/authoring-reference" ,
"tools/generate/brand" ,
"tools/generate/tauri-menu" ,
"tools/generate/visual-oracles" ,
"tools/release/package-artifacts" ,
"tools/release/release-packages"
Sync specs & docs: variables, image export, CLI, core extraction
- Update specs: scene-graph (variables/collections/modes/bindings/.fig import),
editor-ui (VariablesPanel, ExportSection, splash), canvas-rendering
(variable resolution, image export, sceneVersion/renderVersion),
desktop-app (monorepo), tooling (Bun workspace), testing (variable tests)
- Create cli spec: info, tree, find, export commands
- Update docs: features, figma-comparison (79/150), roadmap (Phase 4 ✅,
Phase 5 🟡), keyboard-shortcuts (⇧⌘E), contributing (monorepo structure)
- Restore vitepress devDependency lost during merge
- Archive sync-variables-export-cli change
2026-02-28 23:17:48 +00:00
] ,
Refactor architecture boundaries across core, app, and packages (#234)
* refactor(core): decompose editor factory and action modules
Split the monolithic editor factory and large action modules into focused
domain helpers:
- create.ts assembles context through bridge modules (clipboard,
components, structure, undo) and delegates to graph-reads, graph-events,
layout-runner, component-sync, and state factory
- structure.ts delegates to group, container-wrap, auto-layout-wrap,
reorder, and state-toggle helpers
- selection.ts delegates to hit-test, overlays, container navigation,
and read helpers
- clipboard.ts delegates to subtree-history, images, export, copy,
fonts, and placement helpers
- shapes.ts delegates to pen actions and section-adopt
- components.ts delegates to focus and instances helpers
- alignment.ts delegates to flip-rotate helper
- text.ts uses explicit TextEditSession for snapshot comparison
New focused modules: nudge, variable-bindings, layout-mode,
page-viewports, tool-registry, color-space
Undo: history/position and history/snapshot helpers, hardened
batch/rollback with nested batch support and configurable limit
* refactor(core): split tool definitions by domain
Split the monolithic tool registry into domain-specific modules:
- read/ — selection, find, pages, fonts, components, nodes, query, jsx
- create/ — basic shapes, components, vector, JSX render
- modify/ — paint, effects, geometry, layout, state, text, update
- structure/ — basic, arrange, batch, hierarchy, replace, tree
- variables/ — bindings, collections, read, values
- vector/ — boolean, path, export, viewport
- analyze/ — colors, typography, spacing, clusters, diff, eval
- describe/ — summaries, tree, roles, layout-issues
- stock-photo/ — providers, requests, apply
- codegen/ — component-map, tokens
Split registry into core/extended tiers; refine schema and AI adapter
* refactor(core): restructure kiwi codec and instance overrides
Reorganize the Kiwi .fig codec into domain subdirectories:
- binary/ — codec, schema, protocol
- fig/ — file, import, parse (core, worker, transfer)
- node-change/ — convert, export-node, serialize, plugin-data
- instance-overrides/ — constraints, dsd, populate, props, resolve,
symbol-overrides, symbol-props, sync, types
Vendored kiwi-schema/ left isolated
* refactor(core): split profiler, icons, IO, and add subpath exports
Profiler: speedscope-export, capture-session, hud-controller
Icons: api, svg, types, render, create-icons tool
IO: format registry and subpath exports
Canvas/color/text/vector: targeted cleanup
Add deliberate subpath exports: random, xpath, vector, color, canvas,
scene-graph, kiwi, design-jsx, io, tools, editor, layout, canvaskit,
profiler, text, lint, rpc, figma-api, constants
* refactor(vue): decompose canvas input, surface lifecycle, and controls
Canvas surface: gl-surface, kit-loader, render-loop, resize-observer
Canvas input handlers:
- move: drop-target, move-snap, duplicate-drag
- select: select-move, select-hover, select-hit
- resize: resize-rect, resize-vector, resize-start
- transform: rotation, marquee, pan, text-selection
- text-edit: navigation, clipboard, textarea lifecycle
- Shared: click-count, space-key, pan, pan-zoom, draw, raf-scheduler
Editor composition:
- commands split: actions, context, metadata, edit, selection, view
- menu-model split: command-groups, builders, types
- Gradient stop composable reuse in primitive root
Controls: fill, layout, typography, appearance, effects, stroke,
okhcl, prop-scrub, node-props, undo-batch, color-variable-binding
Variables/i18n/document/export helpers
Organize canvas, primitives, controls, editor, and variables into
cohesive module directories with package-local import aliases
Expose MenuActionNode/MenuSeparatorNode from public API
* refactor(app): split document IO, editor session, and automation bridge
Document IO: source-state, naming, writer, reload-source, reload-state,
imported-document, watch-targets, save-targets
Editor session: create, modules, types, accessors, computed, refs
Editor canvas: loader-overlay, collaboration-awareness,
context-selection, menu-actions, menu-model
Automation bridge: eval, tools, exports, files, selection, RPC fallback
AI/ACP: transport, map-update, permission, debug, chat effects/storage
Collab: awareness, graph-bindings, yjs-sync, follow, session, types
Shell keyboard: actions, bindings, clipboard, focus, nudging,
raw-events, registry, reserved, shortcuts, space-tool
Shell menu: app-menu, document-name, entry, files
Demo: colors, effects, helpers, section builders (components,
app-preview, effects, standalone, variables) — document.ts reduced
from 981 to 32 lines as pure orchestrator
Move app modules under src/app/ with organized domain structure:
editor, document, ai, collab, shell, automation, demo, tabs
* refactor(app): decompose UI components with provide/inject context
Split monolithic components using Reka UI-inspired namespace folders
with scoped provide/inject context — no prop drilling:
- CollabPanel/ — context, avatars, share, connected, join
- ColorPickerPanel/ — context, area, format, field groups, sliders
- MobileHud/ — context, action toast, tool badge, file menu, presence
- ProviderSettings/ — context, API key/type, endpoint, tokens, photos
- Toolbar/ — actions, types, desktop, mobile, tool button, flyout
- LayoutSection/ — types, auto-layout, flex, grid, padding, size, clip
Properties helpers: fill-okhcl adapter, fill-label, color-style-row
Menu: entry helpers, document-name rename, stale type removal
* refactor(mcp): split server into focused modules
- browser-rpc — WebSocket client management
- mcp-sessions — session lifecycle
- tool-output — response formatting
- tool-schema — Zod schema generation from ToolDefs
- jsx-preprocess — JSX source transformation
- result — result helpers
- tool-registration — MCP tool wiring
- auth — API key validation
- http-options — CORS/request handling
- stdio-bridge — stdio transport adapter
* refactor(cli): split analyze subcommands and shared helpers
- Analyze subcommands: clusters, colors, spacing, typography
- RPC data loading helper
- Migrate imports to targeted core subpath exports
* refactor(docs): split VitePress config and shared table component
Config helpers: sdk-sidebar, seo, labels, sidebars, locale-theme,
root-theme, locales
Shared SdkDataTable component replaces duplicated table markup in
SdkPropsTable, SdkEventsTable, and SdkSlotsTable
Update contributing and testing docs
* refactor(tauri): decompose desktop entrypoint
Split lib.rs into focused service modules:
- fig_container.rs — .fig archive/compression commands
- fonts.rs — font cache and system font enumeration
- menu.rs — native menu construction
- menu_events.rs — menu event dispatch and devtools toggle
- window.rs — main window show/focus lifecycle
* test: share domain test factories and migrate fixtures
New shared helpers:
- tests/helpers/scene.ts — makeSceneGraph factory
- tests/helpers/vector-network.ts — vertex/segment/network builders
- tests/helpers/fig-traversal.ts — all-node collection, type counts
- tests/helpers/undo.ts — undo test utilities
- tests/helpers/editor-history.ts — editor history test helpers
Migrate render, vector, fig-roundtrip, and undo tests to use shared
factories instead of inline fixture construction
* build: add structural lint rules, split vite config, update docs
Structural lint (oxlint.structure.json + lint/plugin.js):
- 20+ custom rules enforcing package boundaries, lifecycle patterns,
naming conventions, and import discipline
Vite config split: raw-markdown, canvaskit-assets, pwa, server,
aliases, automation plugins
Remove legacy shims and utils superseded by SDK/core modules
Update AGENTS.md, CONTRIBUTING.md, eval-command docs, tsconfig
* fix(vue): normalize canvas directory casing and remove duplicate export
- Rename Canvas/ to canvas/ in git index to match #vue/canvas/* imports
(PascalCase was correct for component primitives but canvas/ is a
non-component domain directory)
- Remove duplicate ./random subpath export in core package.json
* fix: add #vue and #core Vite resolve aliases for dev server
* refactor(core): reduce remaining large modules
Split the remaining large core hotspots into cohesive domain modules while preserving public facades and behavior.
- Extract scene graph types, variables, node defaults, and vector-network helpers
- Decompose canvas renderer orchestration, state, paints, colors, lifecycle, labels, and delegated domain methods into renderer/ and labels/ subfolders
- Split Kiwi node-change, binary variable binding, layout, RPC, vector, JSX export, clipboard, design JSX, and Figma proxy helpers
- Replace collision-driven *Fn import aliases with namespace imports and enforce the pattern in lint
Validation:
- bun run check
- bun --filter @open-pencil/vue build
- bun run test:dupes
* fix(app): forward color input attrs
* fix(app): cover section drawing errors
* fix(editor): undo option-drag duplicates
* docs: document domain subfolder convention
* fix(app): handle undo redo on keydown
* refactor(app): dispatch shortcuts from keydown
* refactor: group prefixed domain modules
* refactor(app): use tinykeys for shortcuts
* refactor(core): group symbol override modules
* refactor(core): group fig kiwi container helper
* refactor(canvas): split overlay rendering modules
* refactor(vue): remove unused internal barrels
* fix(app): lay out demo components before instancing
* fix(app): restore demo badge spacing
* perf(canvas): split scene and overlay rendering
* refactor(vue): wrap wheel gesture lifecycle
* fix(canvas): wait for fonts before hiding loader
* docs: update unreleased changelog
2026-04-30 12:14:19 +00:00
"type" : "module" ,
Initial commit: Tauri + CanvasKit + React editor scaffold
- Tauri v2 desktop shell with 1280x800 window
- CanvasKit WASM (Skia) rendering via WebGL2
- Scene graph with typed nodes (Frame, Rectangle, Ellipse, Line, etc.)
- Skia renderer with fills, strokes, rounded corners, opacity, rotation
- Selection system with resize handles
- Undo/redo manager (inverse command pattern with batching)
- Bottom toolbar (Select, Frame, Rect, Ellipse, Line) matching Figma UI3
- Left layers panel, right properties panel
- Pan (scroll), zoom (Ctrl+scroll toward cursor)
- Keyboard shortcuts: V/F/R/O/L for tools, Cmd+Z undo, Backspace delete
- 5 demo shapes rendered on canvas
2026-02-27 12:48:29 +00:00
"scripts" : {
"dev" : "vite" ,
2026-08-20 05:15:54 +00:00
"dev:portless" : "portless run vite" ,
2026-05-21 15:16:18 +00:00
"build" : "bun run build:packages && bun run lint && vite build" ,
Initial commit: Tauri + CanvasKit + React editor scaffold
- Tauri v2 desktop shell with 1280x800 window
- CanvasKit WASM (Skia) rendering via WebGL2
- Scene graph with typed nodes (Frame, Rectangle, Ellipse, Line, etc.)
- Skia renderer with fills, strokes, rounded corners, opacity, rotation
- Selection system with resize handles
- Undo/redo manager (inverse command pattern with batching)
- Bottom toolbar (Select, Frame, Rect, Ellipse, Line) matching Figma UI3
- Left layers panel, right properties panel
- Pan (scroll), zoom (Ctrl+scroll toward cursor)
- Keyboard shortcuts: V/F/R/O/L for tools, Cmd+Z undo, Backspace delete
- 5 demo shapes rendered on canvas
2026-02-27 12:48:29 +00:00
"preview" : "vite preview" ,
2026-07-10 15:16:21 +00:00
"storybook" : "storybook dev -p 6006" ,
"build-storybook" : "storybook build" ,
Add oxlint, oxfmt, typescript-go
- oxlint with react, react-hooks, typescript, import, unicorn plugins
- oxfmt (no trailing commas, single quotes, sorted imports)
- tsgo (typescript-go native preview) for fast typechecking
- Fix all lint warnings: non-null assertions, unused expressions, stale closures
- Scripts: lint, format, typecheck, check
2026-02-27 12:52:04 +00:00
"tauri" : "tauri" ,
2026-09-18 08:42:55 +00:00
"build:native-test" : "bun run generate:icons --target desktop && bun run build:packages && bun tauri build --debug --no-bundle --features native-test --config desktop/tauri.native-test.conf.json" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"benchmark:navigation" : "bun tools/dev/navigation-benchmark/src/cli.ts run" ,
2026-08-15 11:17:05 +00:00
"test:native" : "bun run build:native-test && wdio run wdio.conf.ts" ,
2026-08-19 14:41:10 +00:00
"lint" : "bun run lint:structure && oxlint -c oxlint.json --type-aware --type-check src/ packages/scene-graph/src/ packages/core/src/ packages/vue/src/ packages/cli/src/ packages/mcp/src/ packages/harness/src/ packages/dom-css/src/ packages/pen/src/ packages/kiwi/src/ packages/fig/src/" ,
2026-09-15 17:51:33 +00:00
"lint:structure" : "oxlint -c oxlint.json commitlint.config.ts vite.config.ts vite/ .storybook/ src/ packages/scene-graph/src/ packages/scene-graph/scripts/ packages/core/src/ packages/vue/src/ packages/cli/src/ packages/mcp/src/ packages/harness/src/ packages/harness/tests/ packages/dom-css/src/ packages/dom-css/tests/ packages/dom-css/scripts/ packages/pen/src/ packages/pen/scripts/ packages/kiwi/src/ packages/kiwi/tests/ packages/kiwi/scripts/ packages/fig/src/ packages/fig/tests/ packages/fig/scripts/ tests/ scripts/ tools/" ,
"format" : "oxfmt --write .oxfmtrc.json commitlint.config.ts vite.config.ts vite/ .storybook/ src/ packages/scene-graph/src/ packages/scene-graph/scripts/ packages/core/src/ packages/cli/src/ packages/mcp/src/ packages/harness/src/ packages/harness/tests/ packages/vue/src/ packages/dom-css/src/ packages/dom-css/tests/ packages/dom-css/scripts/ packages/pen/src/ packages/pen/scripts/ packages/kiwi/src/ packages/kiwi/tests/ packages/kiwi/scripts/ packages/fig/src/ packages/fig/tests/ packages/fig/scripts/ tests scripts/ tools/" ,
2026-05-24 09:15:29 +00:00
"format:check" : "bun run format && status=$(git status --porcelain -uall) && test -z \"$status\" || (echo \"$status\" && exit 1)" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"check" : "bun run check:icons && bun run build:packages && bun run lint && tsgo --noEmit && bun run check:vue && bun run check:native-test && bun run check:i18n && bun run check:docs && bun run check:changelog && bun run check:packages && bun run check:deps && bun run check:audit && bun run check:secrets && bun run check:monorepo && bun run check:arch && bun run check:test-homes && bun run test:type-shapes && bun run check:tools && bun run test:tools && bun run test:dupes" ,
2026-09-15 17:51:33 +00:00
"check:commits" : "commitlint" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"check:changelog" : "bun tools/release/release-packages/src/check-changelog.ts" ,
2026-07-01 09:56:45 +00:00
"check:deps" : "knip --include unlisted,unresolved,binaries" ,
2026-09-13 16:08:27 +00:00
"check:docs" : "bun --filter @open-pencil/docs check && bun run check:authoring-reference" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"check:authoring-reference" : "bun tools/generate/authoring-reference/src/check.ts" ,
"generate:authoring-reference" : "bun tools/generate/authoring-reference/src/generate.ts" ,
2026-07-01 09:56:45 +00:00
"check:audit" : "bun audit --audit-level=critical" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"check:secrets" : "bun tools/checks/secret-scan/src/index.ts" ,
2026-07-01 09:56:45 +00:00
"check:monorepo" : "sherif --ignore-rule root-package-dependencies" ,
2026-08-15 11:17:05 +00:00
"check:native-test" : "tsc --noEmit -p tests/e2e/native/tsconfig.json" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"check:i18n" : "bun tools/checks/i18n/src/check-locales.ts" ,
"check:packages" : "bun tools/checks/package-quality/src/cli.ts check" ,
2026-05-14 15:23:25 +00:00
"check:arch" : "steiger ." ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"check:test-homes" : "bun tools/checks/test-homes/src/index.ts" ,
2026-03-30 12:11:14 +00:00
"check:vue" : "vue-tsc --noEmit -p tsconfig.json && vue-tsc --noEmit -p packages/vue/tsconfig.json" ,
2026-09-15 19:10:56 +00:00
"test" : "OPENPENCIL_TEST_SERVER=app playwright test --project=openpencil --grep-invert @real-llm" ,
"test:storybook" : "OPENPENCIL_TEST_SERVER=storybook playwright test --project=storybook-chromium" ,
"test:real-llm" : "OPENPENCIL_TEST_SERVER=app playwright test --project=openpencil --grep @real-llm" ,
"test:update" : "OPENPENCIL_TEST_SERVER=app playwright test --project=openpencil --update-snapshots" ,
"test:figma" : "OPENPENCIL_TEST_SERVER=app playwright test --project=figma" ,
2026-02-28 04:45:50 +00:00
"figma:debug" : "open -a Figma --args --remote-debugging-port=9222" ,
2026-08-18 19:52:18 +00:00
"typecheck" : "tsgo --noEmit && bun run check:vue" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"test:unit" : "bun tools/dev/unit-tests/src/run.ts all --include-heavy" ,
"test:unit:quick" : "bun tools/dev/unit-tests/src/run.ts all -- --parallel" ,
"test:unit:isolated" : "bun tools/dev/unit-tests/src/run.ts all -- --isolate" ,
"test:unit:heavy" : "bun tools/dev/unit-tests/src/run.ts all --heavy-only -- --timeout 180000" ,
"test:coverage" : "bun tools/dev/unit-tests/src/run.ts all --include-heavy -- --coverage" ,
"test:type-shapes" : "bun tools/checks/type-shapes/src/index.ts" ,
"test:tools" : "bun --filter '@open-pencil/*-tools' test && bun --filter @open-pencil/harness test" ,
2026-06-06 19:24:31 +00:00
"test:dupes" : "jscpd packages/scene-graph/src packages/pen/src packages/core/src packages/cli/src packages/dom-css/src src --min-lines 5 --min-tokens 50 --format typescript --threshold 0" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"test:packages" : "bun tools/checks/package-quality/src/cli.ts verify" ,
"build:packages" : "bun tools/release/package-artifacts/src/build.ts" ,
Sync specs & docs: variables, image export, CLI, core extraction
- Update specs: scene-graph (variables/collections/modes/bindings/.fig import),
editor-ui (VariablesPanel, ExportSection, splash), canvas-rendering
(variable resolution, image export, sceneVersion/renderVersion),
desktop-app (monorepo), tooling (Bun workspace), testing (variable tests)
- Create cli spec: info, tree, find, export commands
- Update docs: features, figma-comparison (79/150), roadmap (Phase 4 ✅,
Phase 5 🟡), keyboard-shortcuts (⇧⌘E), contributing (monorepo structure)
- Restore vitepress devDependency lost during merge
- Archive sync-variables-export-cli change
2026-02-28 23:17:48 +00:00
"open-pencil" : "bun packages/cli/src/index.ts" ,
2026-03-01 12:16:16 +00:00
"docs:dev" : "bun --filter @open-pencil/docs dev" ,
"docs:build" : "bun --filter @open-pencil/docs build" ,
2026-08-13 10:50:28 +00:00
"docs:build:production" : "bun --filter @open-pencil/docs build:production" ,
2026-03-04 07:35:44 +00:00
"docs:preview" : "bun --filter @open-pencil/docs preview" ,
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 01:00:31 +00:00
"generate:icons" : "bun tools/generate/brand/src/cli.ts generate" ,
"check:icons" : "bun tools/generate/brand/src/cli.ts check" ,
"generate:tauri-menu" : "bun tools/generate/tauri-menu/src/generate.ts" ,
"check:tools" : "tsgo --noEmit -p tools/tsconfig.json"
Initial commit: Tauri + CanvasKit + React editor scaffold
- Tauri v2 desktop shell with 1280x800 window
- CanvasKit WASM (Skia) rendering via WebGL2
- Scene graph with typed nodes (Frame, Rectangle, Ellipse, Line, etc.)
- Skia renderer with fills, strokes, rounded corners, opacity, rotation
- Selection system with resize handles
- Undo/redo manager (inverse command pattern with batching)
- Bottom toolbar (Select, Frame, Rect, Ellipse, Line) matching Figma UI3
- Left layers panel, right properties panel
- Pan (scroll), zoom (Ctrl+scroll toward cursor)
- Keyboard shortcuts: V/F/R/O/L for tools, Cmd+Z undo, Backspace delete
- 5 demo shapes rendered on canvas
2026-02-27 12:48:29 +00:00
} ,
"dependencies" : {
2026-08-18 16:31:02 +00:00
"@ai-sdk/anthropic" : "^4.0.39" ,
"@ai-sdk/deepseek" : "^3.0.28" ,
"@ai-sdk/google" : "^4.0.44" ,
"@ai-sdk/openai" : "^4.0.42" ,
"@ai-sdk/valibot" : "^3.0.27" ,
"@ai-sdk/vue" : "^4.0.66" ,
2026-08-18 14:44:40 +00:00
"@atlaskit/pragmatic-drag-and-drop" : "^1.8.1" ,
"@atlaskit/pragmatic-drag-and-drop-hitbox" : "^1.2.0" ,
2026-05-16 15:26:24 +00:00
"@chenglou/pretext" : "^0.0.7" ,
feat(code): add live JSX and HTML/CSS editing (#525)
* feat(code): isolate Design JSX execution
- Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker
- Block ambient network capabilities and enforce source, timeout, output, depth, and element limits
- Validate that only bounded plain structured data returns to the application
* feat(code): add editable Design JSX
- Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling
- Convert validated sandbox output into trusted Design JSX helpers before rendering
- Apply or insert JSX as one undoable graph transaction while preserving dirty drafts
* feat(code): localize JSX editor actions
- Add translated-message fallbacks for editing, applying, inserting, and draft state
- Document the editable JSX workflow in the unreleased changelog
* fix(code): satisfy typed sandbox validation
- Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint
* test(code): resolve sandbox probes through app aliases
* fix(code): bound sandbox results before cloning
- Enforce string, array, object, depth, element, and byte limits inside the disposable worker
- Retain host-side validation as a second structured-data boundary
* fix(code): keep JSX and HTML editing modes separate
- Switch generated Tailwind output back to OpenPencil JSX before editing
- Close the JSX editor when opening HTML/CSS import and avoid stacking both editors
* feat(code): support authored Design JSX programs
- Allow local constants, function components, arrays, conditionals, fragments, and multiple roots
- Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections
- Cover multi-root undo, redo, and all-or-nothing rollback
* feat(code): add explicit JSX view mode
- Let authors leave CodeMirror without applying a draft
- Keep the editable surface and HTML/CSS importer mutually exclusive
* feat(code): diagnose unknown JSX vocabulary
- Warn on OpenPencil elements and properties that are absent from the canonical schema
- Surface diagnostics inline through CodeMirror lint markers
* test(code): accept WebKit isolation diagnostics
- Cover the sandbox architecture against Playwright WebKit
- Accept engine-specific wording while preserving the same unavailable-window assertion
* refactor(code): consolidate Design JSX vocabulary
- Drive renderer warnings, completion, and diagnostics from one supported-property schema
- Recognize locally declared components and add focused schema and transform tests
- Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package
* fix(code): support Design JSX variable helpers
* refactor(code): unify JSX sandbox validation
* fix(code): account for complete sandbox output
* fix(code): preserve locked JSX descendants
* fix(code): preserve JSX sibling order
* fix(code): recompute JSX parent layouts
* feat(code): add live code previews
* test(code): centralize graph assertions
* fix(code): harden live preview sessions
* docs: describe live code editing
* fix(code): update editor accessibility labels
* fix(code): use theme-aware error colors
* fix(dev): stop Vite disconnect error loops
* fix(code): clarify live preview status
* fix(ui): avoid tooltip attribute warnings
* test(code): assert semantic preview status
* refactor(code): remove obsolete editor messages
* fix(code): harden preview concurrency and isolation
* fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
"@codemirror/autocomplete" : "^6.20.3" ,
2026-08-18 14:44:40 +00:00
"@codemirror/commands" : "^6.11.0" ,
"@codemirror/lang-html" : "^6.4.12" ,
feat(code): add live JSX and HTML/CSS editing (#525)
* feat(code): isolate Design JSX execution
- Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker
- Block ambient network capabilities and enforce source, timeout, output, depth, and element limits
- Validate that only bounded plain structured data returns to the application
* feat(code): add editable Design JSX
- Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling
- Convert validated sandbox output into trusted Design JSX helpers before rendering
- Apply or insert JSX as one undoable graph transaction while preserving dirty drafts
* feat(code): localize JSX editor actions
- Add translated-message fallbacks for editing, applying, inserting, and draft state
- Document the editable JSX workflow in the unreleased changelog
* fix(code): satisfy typed sandbox validation
- Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint
* test(code): resolve sandbox probes through app aliases
* fix(code): bound sandbox results before cloning
- Enforce string, array, object, depth, element, and byte limits inside the disposable worker
- Retain host-side validation as a second structured-data boundary
* fix(code): keep JSX and HTML editing modes separate
- Switch generated Tailwind output back to OpenPencil JSX before editing
- Close the JSX editor when opening HTML/CSS import and avoid stacking both editors
* feat(code): support authored Design JSX programs
- Allow local constants, function components, arrays, conditionals, fragments, and multiple roots
- Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections
- Cover multi-root undo, redo, and all-or-nothing rollback
* feat(code): add explicit JSX view mode
- Let authors leave CodeMirror without applying a draft
- Keep the editable surface and HTML/CSS importer mutually exclusive
* feat(code): diagnose unknown JSX vocabulary
- Warn on OpenPencil elements and properties that are absent from the canonical schema
- Surface diagnostics inline through CodeMirror lint markers
* test(code): accept WebKit isolation diagnostics
- Cover the sandbox architecture against Playwright WebKit
- Accept engine-specific wording while preserving the same unavailable-window assertion
* refactor(code): consolidate Design JSX vocabulary
- Drive renderer warnings, completion, and diagnostics from one supported-property schema
- Recognize locally declared components and add focused schema and transform tests
- Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package
* fix(code): support Design JSX variable helpers
* refactor(code): unify JSX sandbox validation
* fix(code): account for complete sandbox output
* fix(code): preserve locked JSX descendants
* fix(code): preserve JSX sibling order
* fix(code): recompute JSX parent layouts
* feat(code): add live code previews
* test(code): centralize graph assertions
* fix(code): harden live preview sessions
* docs: describe live code editing
* fix(code): update editor accessibility labels
* fix(code): use theme-aware error colors
* fix(dev): stop Vite disconnect error loops
* fix(code): clarify live preview status
* fix(ui): avoid tooltip attribute warnings
* test(code): assert semantic preview status
* refactor(code): remove obsolete editor messages
* fix(code): harden preview concurrency and isolation
* fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
"@codemirror/lang-javascript" : "^6.2.5" ,
"@codemirror/language" : "^6.12.4" ,
"@codemirror/lint" : "^6.9.7" ,
"@codemirror/search" : "^6.7.1" ,
2026-08-18 14:44:40 +00:00
"@codemirror/state" : "^6.7.1" ,
"@codemirror/view" : "^6.43.9" ,
2026-09-13 13:39:32 +00:00
"@lezer/highlight" : "^1.2.3" ,
2026-08-18 15:52:19 +00:00
"@nanostores/i18n" : "^1.3.3" ,
"@nanostores/vue" : "^1.1.0" ,
2026-02-28 23:12:19 +00:00
"@open-pencil/cli" : "workspace:*" ,
"@open-pencil/core" : "workspace:*" ,
2026-06-02 11:55:14 +00:00
"@open-pencil/dom-css" : "workspace:*" ,
2026-06-06 15:38:27 +00:00
"@open-pencil/fig" : "workspace:*" ,
2026-08-19 14:41:10 +00:00
"@open-pencil/harness" : "workspace:*" ,
2026-06-06 08:48:33 +00:00
"@open-pencil/kiwi" : "workspace:*" ,
2026-07-01 07:40:29 +00:00
"@open-pencil/pen" : "workspace:*" ,
"@open-pencil/scene-graph" : "workspace:*" ,
2026-03-16 14:24:45 +00:00
"@open-pencil/vue" : "workspace:*" ,
2026-08-18 16:31:02 +00:00
"@openrouter/ai-sdk-provider" : "^3.0.0" ,
2026-09-13 18:25:08 +00:00
"@stream-markdown/code" : "2.0.0-beta.5" ,
2026-08-18 14:44:40 +00:00
"@tailwindcss/vite" : "^4.3.3" ,
2026-02-28 23:12:19 +00:00
"@tanstack/vue-table" : "^8.21.3" ,
2026-08-18 14:44:40 +00:00
"@tauri-apps/api" : "^2.11.1" ,
"@tauri-apps/plugin-clipboard-manager" : "^2.3.2" ,
"@tauri-apps/plugin-dialog" : "^2.7.2" ,
"@tauri-apps/plugin-fs" : "^2.5.1" ,
"@tauri-apps/plugin-opener" : "^2.5.4" ,
fix: explain unsupported browsers instead of a blank window (#745)
* fix: explain unsupported browsers instead of a blank window
The desktop app on macOS 13 with WebKit older than Safari 17.4 opened an
empty window because startup called Promise.withResolvers, which Vite lowers
nothing for: build.target only rewrites syntax and never polyfills APIs, and
the target itself was an implicit Vite default (#744).
Make the supported baseline explicit in src/app/shell/support/baseline.ts and
feed it to build.target, a lint rule that rejects newer static built-ins in
browser-shipped sources, and the documented system requirements. Replace
Promise.withResolvers with a createDeferred() helper.
Turn src/main.ts into a small gate that checks sentinel features before
dynamically importing the app, so an old engine still evaluates enough code
to render platform-specific update guidance: macOS/Safari via Software
Update, WebKitGTK and WebView2 on Linux and Windows, and each browser's
own update path on the web, with a prefilled bug report link. Render-blocking
errors during the first route are captured through app.config.errorHandler
and shown the same way instead of leaving the window blank.
Desktop facts come from tauri-plugin-os and a webview_version command; the
bundle now declares macOS 13 as its minimum system version.
* build: enforce the browser baseline from compatibility data
Replace the hand-maintained list of built-ins newer than the baseline with
two data-driven checks. The app and browser-shipped packages pin their
TypeScript lib to ES2023, the last edition Chrome 111, Firefox 128 and
Safari 16.4 implement in full, so a newer built-in such as
Promise.withResolvers fails type-checking. Web APIs, which lib.dom does not
version, go through eslint-plugin-compat under oxlint with the same browsers
in settings.browsers, scoped to sources that ship to a browser.
A unit test keeps the oxlint browser list and the tsconfig libs derived from
src/app/shell/support/baseline.ts, so the three cannot drift apart.
* fix: recognise production error codes in the boot observer
Vue passes the error reference URL as the errorHandler info argument in
production builds instead of the development string, so the observer never
classified a setup or render failure as fatal in the shipped app and the
boot-failure notice only appeared on the dev server. Match Vue's exported
ErrorCodes in both forms, and cover the component-setup path in the E2E
spec; the scenario was also verified against a production build.
2026-09-22 10:40:59 +00:00
"@tauri-apps/plugin-os" : "^2.3.2" ,
2026-05-01 09:18:53 +00:00
"@tauri-apps/plugin-process" : "^2.3.1" ,
2026-03-14 07:20:15 +00:00
"@tauri-apps/plugin-shell" : "^2.3.5" ,
2026-05-01 09:18:53 +00:00
"@tauri-apps/plugin-updater" : "^2.10.1" ,
2026-08-18 14:44:40 +00:00
"@unhead/vue" : "^2.1.17" ,
2026-09-13 21:54:12 +00:00
"@valibot/to-json-schema" : "^1.8.0" ,
2026-08-18 14:44:40 +00:00
"@vueuse/core" : "^14.4.0" ,
"@xmldom/xmldom" : "^0.9.11" ,
2026-08-18 16:31:02 +00:00
"ai" : "^7.0.66" ,
2026-07-26 11:26:44 +00:00
"aws4fetch" : "^1.0.20" ,
2026-08-18 20:09:45 +00:00
"canvaskit-wasm" : "^0.41.1" ,
2026-08-28 11:37:42 +00:00
"copy-to-clipboard" : "^4.0.2" ,
2026-02-28 05:08:04 +00:00
"culori" : "^4.0.2" ,
2026-08-18 14:44:40 +00:00
"dedent" : "^1.7.2" ,
"es-toolkit" : "^1.51.0" ,
"fflate" : "^0.8.3" ,
2026-09-03 17:36:47 +00:00
"fuse.js" : "^7.5.0" ,
2026-02-27 20:01:35 +00:00
"fzstd" : "^0.1.1" ,
2026-08-11 10:26:48 +00:00
"hast-util-to-html" : "^9.0.5" ,
2026-07-26 11:07:26 +00:00
"idb" : "^8.0.3" ,
refactor!: move shared primitives below dom-css and core (#771)
* refactor!: move shared primitives below dom-css and core
dom-css depended on core for color conversion, base64 helpers, text
direction, and web-font assets, so core could not use dom-css and every
caller special-cased HTML and Tailwind output.
Color conversion and management, base64 helpers, and text/layout
direction now live in scene-graph under `color`, `bytes`, and
`text-direction`. dom-css takes web-font resolution as an injected
`fonts` option and owns the font face types, so it depends only on
scene-graph and core can depend on it.
BREAKING CHANGE: `@open-pencil/core/color` and `@open-pencil/core/bytes`
are removed, and the direction helpers are no longer exported from
`@open-pencil/core/text`; import them from `@open-pencil/scene-graph`
subpaths. `exportHTMLBundle` takes a font resolver in `fonts` instead of
`'assets'`.
* fix(tools): import color parsing from scene-graph in visual bisect
* fix(mcp): declare the scene-graph dependency
MCP imports `@open-pencil/scene-graph/bytes` since base64 helpers moved
there, but only reached scene-graph through core, so isolated installs
and package checks depended on transitive resolution.
* refactor!: use js-base64 directly instead of a base64 wrapper
Base64 helpers had moved into scene-graph only to sit below dom-css,
but they are a thin wrapper over js-base64 and unrelated to the graph;
fig already called js-base64 directly.
Callers use js-base64 and check `isValid` where input comes from outside
(clipboard, imported HTML, tool arguments, the plugin API). A new
`open-pencil/no-hand-rolled-base64` lint rule rejects atob, btoa, and
Buffer Base64 conversions, and AGENTS.md records the convention.
BREAKING CHANGE: `@open-pencil/core/bytes` is removed; use `js-base64`.
* fix(dom-css): keep images with invalid Base64 inline in HTML export
`exportHTMLBundle` accepts documents parsed from outside HTML, and
js-base64 drops characters it cannot decode, so extracting an invalid
image data URL wrote different bytes. Such images now stay inline.
2026-09-26 07:39:11 +00:00
"js-base64" : "^3.9.3" ,
2026-05-03 21:18:54 +00:00
"jspdf" : "^4.2.1" ,
2026-03-01 13:44:37 +00:00
"lib0" : "^0.2.117" ,
2026-08-18 14:44:40 +00:00
"motion-v" : "^2.4.0" ,
2026-08-18 15:52:19 +00:00
"nanostores" : "^1.5.0" ,
2026-07-17 10:23:51 +00:00
"opentype.js" : "^2.0.0" ,
2026-08-18 14:44:40 +00:00
"reka-ui" : "^2.10.3" ,
2026-05-03 21:18:54 +00:00
"svg2pdf.js" : "^2.7.0" ,
2026-08-18 14:44:40 +00:00
"tailwind-merge" : "^3.6.0" ,
"tailwind-variants" : "^3.3.1" ,
"tailwindcss" : "^4.3.3" ,
"tinykeys" : "^3.1.0" ,
2026-03-01 14:25:46 +00:00
"trystero" : "^0.22.0" ,
2026-08-18 14:44:40 +00:00
"valibot" : "^1.4.2" ,
2026-09-15 13:34:05 +00:00
"vee-validate" : "5.0.0-beta.0" ,
2026-08-18 14:44:40 +00:00
"vue" : "^3.5.41" ,
"vue-router" : "^5.2.0" ,
2026-09-13 18:25:08 +00:00
"vue-stream-markdown" : "2.0.0-beta.5" ,
2026-03-01 14:25:46 +00:00
"y-indexeddb" : "^9.0.12" ,
2026-03-01 13:44:37 +00:00
"y-protocols" : "^1.0.7" ,
2026-08-18 14:44:40 +00:00
"yjs" : "^13.6.32" ,
2026-04-13 09:09:45 +00:00
"yoga-layout" : "npm:@open-pencil/yoga-layout@3.3.0-grid.3" ,
2026-08-18 14:44:40 +00:00
"zod" : "^4.4.3"
2026-05-22 12:00:44 +00:00
} ,
Initial commit: Tauri + CanvasKit + React editor scaffold
- Tauri v2 desktop shell with 1280x800 window
- CanvasKit WASM (Skia) rendering via WebGL2
- Scene graph with typed nodes (Frame, Rectangle, Ellipse, Line, etc.)
- Skia renderer with fills, strokes, rounded corners, opacity, rotation
- Selection system with resize handles
- Undo/redo manager (inverse command pattern with batching)
- Bottom toolbar (Select, Frame, Rect, Ellipse, Line) matching Figma UI3
- Left layers panel, right properties panel
- Pan (scroll), zoom (Ctrl+scroll toward cursor)
- Keyboard shortcuts: V/F/R/O/L for tools, Cmd+Z undo, Backspace delete
- 5 demo shapes rendered on canvas
2026-02-27 12:48:29 +00:00
"devDependencies" : {
2026-03-03 17:45:58 +00:00
"@agentclientprotocol/sdk" : "^0.14.1" ,
2026-07-01 09:56:45 +00:00
"@arethetypeswrong/cli" : "0.18.4" ,
2026-09-15 17:51:33 +00:00
"@commitlint/cli" : "^21.2.2" ,
"@commitlint/config-conventional" : "^21.2.2" ,
2026-09-15 20:12:44 +00:00
"@commitlint/is-ignored" : "^21.2.2" ,
2026-09-15 17:51:33 +00:00
"@commitlint/types" : "^21.2.0" ,
2026-05-14 15:23:25 +00:00
"@feature-sliced/steiger-plugin" : "^0.5.8" ,
2026-08-18 14:44:40 +00:00
"@figma/plugin-typings" : "^1.134.0" ,
"@hono/node-server" : "^1.19.17" ,
"@iconify-json/lucide" : "^1.2.123" ,
2026-09-13 21:54:12 +00:00
"@modelcontextprotocol/client" : "^2.0.0" ,
2026-09-16 08:54:07 +00:00
"@open-pencil/brand-tools" : "workspace:*" ,
2026-03-16 18:54:08 +00:00
"@open-pencil/mcp" : "workspace:*" ,
2026-09-11 08:57:28 +00:00
"@oxlint/plugins" : "1.57.0" ,
2026-08-18 14:44:40 +00:00
"@playwright/test" : "^1.62.1" ,
"@storybook/addon-a11y" : "^10.5.8" ,
"@storybook/addon-docs" : "^10.5.8" ,
"@storybook/addon-themes" : "^10.5.8" ,
"@storybook/vue3-vite" : "^10.5.8" ,
2026-09-16 08:54:07 +00:00
"@tauri-apps/cli" : "2.11.4" ,
2026-02-28 08:37:02 +00:00
"@types/culori" : "^4.0.1" ,
2026-08-18 14:44:40 +00:00
"@types/node" : "^25.9.5" ,
"@types/opentype.js" : "^1.3.10" ,
2026-03-07 11:30:12 +00:00
"@types/ws" : "^8.18.1" ,
2026-09-01 16:49:57 +00:00
"@typescript-eslint/utils" : "^8.67.0" ,
2026-08-18 14:44:40 +00:00
"@typescript/native-preview" : "^7.0.0-dev.20260707.2" ,
"@vitejs/plugin-vue" : "^6.0.8" ,
2026-09-01 16:49:57 +00:00
"@vue/compiler-core" : "^3.5.41" ,
2026-08-15 11:17:05 +00:00
"@wdio/cli" : "9.30.1" ,
"@wdio/globals" : "9.29.1" ,
"@wdio/local-runner" : "9.30.1" ,
"@wdio/mocha-framework" : "9.30.1" ,
"@wdio/spec-reporter" : "9.30.1" ,
"@wdio/tauri-service" : "1.3.0" ,
2026-08-17 08:07:13 +00:00
"changelog-parser" : "^4.1.0" ,
2026-08-13 10:50:28 +00:00
"cloudflare-redirect-parser" : "^1.0.0" ,
2026-08-18 14:44:40 +00:00
"esbuild" : "^0.27.7" ,
fix: explain unsupported browsers instead of a blank window (#745)
* fix: explain unsupported browsers instead of a blank window
The desktop app on macOS 13 with WebKit older than Safari 17.4 opened an
empty window because startup called Promise.withResolvers, which Vite lowers
nothing for: build.target only rewrites syntax and never polyfills APIs, and
the target itself was an implicit Vite default (#744).
Make the supported baseline explicit in src/app/shell/support/baseline.ts and
feed it to build.target, a lint rule that rejects newer static built-ins in
browser-shipped sources, and the documented system requirements. Replace
Promise.withResolvers with a createDeferred() helper.
Turn src/main.ts into a small gate that checks sentinel features before
dynamically importing the app, so an old engine still evaluates enough code
to render platform-specific update guidance: macOS/Safari via Software
Update, WebKitGTK and WebView2 on Linux and Windows, and each browser's
own update path on the web, with a prefilled bug report link. Render-blocking
errors during the first route are captured through app.config.errorHandler
and shown the same way instead of leaving the window blank.
Desktop facts come from tauri-plugin-os and a webview_version command; the
bundle now declares macOS 13 as its minimum system version.
* build: enforce the browser baseline from compatibility data
Replace the hand-maintained list of built-ins newer than the baseline with
two data-driven checks. The app and browser-shipped packages pin their
TypeScript lib to ES2023, the last edition Chrome 111, Firefox 128 and
Safari 16.4 implement in full, so a newer built-in such as
Promise.withResolvers fails type-checking. Web APIs, which lib.dom does not
version, go through eslint-plugin-compat under oxlint with the same browsers
in settings.browsers, scoped to sources that ship to a browser.
A unit test keeps the oxlint browser list and the tsconfig libs derived from
src/app/shell/support/baseline.ts, so the three cannot drift apart.
* fix: recognise production error codes in the boot observer
Vue passes the error reference URL as the errorHandler info argument in
production builds instead of the development string, so the observer never
classified a setup or render failure as fatal in the shipped app and the
boot-failure notice only appeared on the dev server. Match Vue's exported
ErrorCodes in both forms, and cover the component-setup path in the E2E
spec; the scenario was also verified against a production build.
2026-09-22 10:40:59 +00:00
"eslint-plugin-compat" : "^7.0.2" ,
2026-08-15 11:17:05 +00:00
"expect-webdriverio" : "5.7.0" ,
2026-07-26 11:07:26 +00:00
"fake-indexeddb" : "^6.2.5" ,
2026-08-13 17:40:35 +00:00
"franc" : "^6.2.0" ,
2026-08-18 14:44:40 +00:00
"hono" : "^4.13.2" ,
"jscpd" : "^4.3.0" ,
2026-07-01 09:56:45 +00:00
"knip" : "6.20.0" ,
2026-08-13 10:50:28 +00:00
"mdast" : "^3.0.0" ,
"mdast-util-from-markdown" : "^2.0.3" ,
2026-03-08 23:58:24 +00:00
"mitata" : "^1.0.34" ,
2026-09-09 23:45:13 +00:00
"oxfmt" : "^0.67.0" ,
2026-08-18 14:44:40 +00:00
"oxlint" : "1.57.0" ,
2026-03-08 20:02:25 +00:00
"oxlint-tsgolint" : "^0.16.0" ,
2026-08-20 05:15:54 +00:00
"portless" : "0.15.5" ,
2026-07-01 09:56:45 +00:00
"publint" : "0.3.20" ,
"sherif" : "1.12.0" ,
2026-08-18 14:44:40 +00:00
"steiger" : "^0.5.13" ,
"storybook" : "^10.5.8" ,
"tsdown" : "^0.22.14" ,
2026-03-01 08:03:51 +00:00
"tw-animate-css" : "^1.4.0" ,
Initial commit: Tauri + CanvasKit + React editor scaffold
- Tauri v2 desktop shell with 1280x800 window
- CanvasKit WASM (Skia) rendering via WebGL2
- Scene graph with typed nodes (Frame, Rectangle, Ellipse, Line, etc.)
- Skia renderer with fills, strokes, rounded corners, opacity, rotation
- Selection system with resize handles
- Undo/redo manager (inverse command pattern with batching)
- Bottom toolbar (Select, Frame, Rect, Ellipse, Line) matching Figma UI3
- Left layers panel, right properties panel
- Pan (scroll), zoom (Ctrl+scroll toward cursor)
- Keyboard shortcuts: V/F/R/O/L for tools, Cmd+Z undo, Backspace delete
- 5 demo shapes rendered on canvas
2026-02-27 12:48:29 +00:00
"typescript" : "~5.8.3" ,
2026-08-13 10:50:28 +00:00
"unist-util-visit" : "^5.1.0" ,
2026-02-28 05:24:42 +00:00
"unplugin-icons" : "^23.0.1" ,
2026-08-18 14:44:40 +00:00
"unplugin-raw" : "^0.7.0" ,
"unplugin-vue" : "^7.2.0" ,
"unplugin-vue-components" : "^31.1.0" ,
feat(code): add live JSX and HTML/CSS editing (#525)
* feat(code): isolate Design JSX execution
- Transform JSX with the existing Sucrase dependency and execute it in a disposable opaque-origin iframe worker
- Block ambient network capabilities and enforce source, timeout, output, depth, and element limits
- Validate that only bounded plain structured data returns to the application
* feat(code): add editable Design JSX
- Add a lazy CodeMirror editor with JSX syntax support, completion, diagnostics, and bounded scrolling
- Convert validated sandbox output into trusted Design JSX helpers before rendering
- Apply or insert JSX as one undoable graph transaction while preserving dirty drafts
* feat(code): localize JSX editor actions
- Add translated-message fallbacks for editing, applying, inserting, and draft state
- Document the editable JSX workflow in the unreleased changelog
* fix(code): satisfy typed sandbox validation
- Keep the sandbox document terminator literal and preserve optional selection handling under type-aware lint
* test(code): resolve sandbox probes through app aliases
* fix(code): bound sandbox results before cloning
- Enforce string, array, object, depth, element, and byte limits inside the disposable worker
- Retain host-side validation as a second structured-data boundary
* fix(code): keep JSX and HTML editing modes separate
- Switch generated Tailwind output back to OpenPencil JSX before editing
- Close the JSX editor when opening HTML/CSS import and avoid stacking both editors
* feat(code): support authored Design JSX programs
- Allow local constants, function components, arrays, conditionals, fragments, and multiple roots
- Preserve replacement positions for multiple selected roots and reject mixed-parent or locked selections
- Cover multi-root undo, redo, and all-or-nothing rollback
* feat(code): add explicit JSX view mode
- Let authors leave CodeMirror without applying a draft
- Keep the editable surface and HTML/CSS importer mutually exclusive
* feat(code): diagnose unknown JSX vocabulary
- Warn on OpenPencil elements and properties that are absent from the canonical schema
- Surface diagnostics inline through CodeMirror lint markers
* test(code): accept WebKit isolation diagnostics
- Cover the sandbox architecture against Playwright WebKit
- Accept engine-specific wording while preserving the same unavailable-window assertion
* refactor(code): consolidate Design JSX vocabulary
- Drive renderer warnings, completion, and diagnostics from one supported-property schema
- Recognize locally declared components and add focused schema and transform tests
- Replace CodeMirror basicSetup with an explicit feature set and remove the umbrella package
* fix(code): support Design JSX variable helpers
* refactor(code): unify JSX sandbox validation
* fix(code): account for complete sandbox output
* fix(code): preserve locked JSX descendants
* fix(code): preserve JSX sibling order
* fix(code): recompute JSX parent layouts
* feat(code): add live code previews
* test(code): centralize graph assertions
* fix(code): harden live preview sessions
* docs: describe live code editing
* fix(code): update editor accessibility labels
* fix(code): use theme-aware error colors
* fix(dev): stop Vite disconnect error loops
* fix(code): clarify live preview status
* fix(ui): avoid tooltip attribute warnings
* test(code): assert semantic preview status
* refactor(code): remove obsolete editor messages
* fix(code): harden preview concurrency and isolation
* fix(code): cancel stale reset previews
2026-08-15 06:48:42 +00:00
"vite" : "8.1.4" ,
2026-08-18 14:44:40 +00:00
"vite-plugin-pwa" : "^1.3.0" ,
"vue-tsc" : "^3.3.10" ,
2026-09-13 21:54:12 +00:00
"webmcp-types" : "^0.1.7" ,
2026-08-18 14:44:40 +00:00
"workbox-window" : "^7.4.1" ,
"ws" : "^8.21.3"
2026-07-01 07:40:29 +00:00
} ,
"overrides" : {
2026-09-03 10:34:55 +00:00
"@codemirror/view" : "6.43.9" ,
2026-07-17 23:49:22 +00:00
"protobufjs" : "7.5.5" ,
2026-09-03 10:34:55 +00:00
"websocket-driver" : "0.7.5"
2026-08-17 08:07:13 +00:00
} ,
2026-09-17 07:18:16 +00:00
"packageManager" : "bun@1.4.2"
2026-03-15 06:32:16 +00:00
}