Commit graph

630 commits

Author SHA1 Message Date
Danila Poyarkov e6984629fd Fix MCP publish: pre-build then publish with --ignore-scripts 2026-03-08 01:07:32 +03:00
Danila Poyarkov be7150b616 Move open-pencil skill to dedicated repo
Install via: npx skills add open-pencil/skills@open-pencil
Repo: https://github.com/open-pencil/skills
2026-03-08 01:03:25 +03:00
Danila Poyarkov 97a3af26a7 Add open-pencil skill for CLI and MCP usage
Installable via: npx skills add open-pencil/open-pencil --skill open-pencil

Covers both app mode (running editor) and headless mode (.fig files):
CLI commands, MCP server setup, JSX rendering, eval, analyze tools.
2026-03-08 00:56:01 +03:00
Danila Poyarkov a6ea74014a Fix publish: resolve workspace deps then npm publish with provenance 2026-03-08 00:54:22 +03:00
Danila Poyarkov 65e40a2570 Fix pnpm publish auth: write .npmrc in project root 2026-03-08 00:37:24 +03:00
Danila Poyarkov 5c68ab0dee Fix npm publish auth: write .npmrc for pnpm 2026-03-08 00:34:19 +03:00
Danila Poyarkov 5ac70a5976 Update docs: tool counts 75/78 → 87/90, schema.ts → tools/ directory, add RPC bridge 2026-03-08 00:28:11 +03:00
Danila Poyarkov 9882375b4f Release v0.8.0 2026-03-08 00:20:47 +03:00
Danila Poyarkov c2710d11fb Fix roadmap: individual strokes already shipped, restore skewing/OkHCL 2026-03-08 00:07:39 +03:00
Danila Poyarkov d84f165a27 Update README roadmap, features, tool counts, and project structure 2026-03-08 00:04:22 +03:00
Danila Poyarkov 01c8753f6e Merge PR #70: E2E test coverage + mutation unit tests
48 new E2E tests across 9 spec files, 26 mutation unit tests,
store/canvas test helpers, data-test-id attributes.

Fixes: explicit error in canvasBounds(), remove any casts,
trim trailing blank line, condense changelog entries.
2026-03-07 23:47:00 +03:00
Danila Poyarkov 6eb206a451 Merge docs PR, fix all lint/typecheck errors, update changelog
- Merge add-vitepress-docs: docs site with 6 locales, SEO, user guide
- Remove VitePress cache files that slipped into git
- Fix all 11 oxlint warnings: replace non-null assertions in
  use-collab.ts with local const captures inside closures
- Update changelog with docs and lint fix entries
2026-03-07 23:19:19 +03:00
Danila Poyarkov cbff284e78 Merge branch 'add-vitepress-docs' 2026-03-07 23:14:25 +03:00
Anton A S a40c535a4d Update CHANGELOG for e2e-coverage 2026-03-07 23:13:08 +03:00
Anton A S 6f93173256 Add mutation unit tests: toggleBoldInRange, vectorNetworkBlob precision, SceneGraph+UndoManager integration 2026-03-07 23:11:03 +03:00
Anton A S d7dc55264b Improve E2E test quality: stronger assertions, fix bold button test, improve snap guide comparison 2026-03-07 23:06:51 +03:00
Anton A S c3c49fcb2f Fix E2E tests: waitForInit loading guard, selector fixes, bold/italic via node-level toggle 2026-03-07 22:48:33 +03:00
Anton A S 83c72b94a0 Add E2E test coverage for canvas, toolbar, panels, properties, auto-layout, variables, export 2026-03-07 22:11:25 +03:00
Anton A S 4315237399 Ignore VitePress build artifacts under docs/ 2026-03-07 21:45:32 +03:00
Danila Poyarkov 2b525b816b Fix eval response unwrapping and export_jsx page selection
- eval CLI was typing rpc result as {ok, result} but the bridge
  already unwraps to the inner value — use rpc<unknown> directly
- export_jsx defaults to current page children, not first page
- Fix import ordering in server.ts (doc comment above imports)
2026-03-07 20:51:53 +03:00
Danila Poyarkov b6c922e335 Fix all code review issues in RPC bridge
Bugs fixed:
- Export response now wrapped in {ok, result} like all other commands
- btoa(String.fromCharCode(...data)) replaced with loop to avoid
  RangeError on large images
- JSX export uses dedicated export_jsx RPC command instead of eval
  with undefined selectionToJSX reference

Issues fixed:
- connectAutomation cleanup on component unmount via onUnmounted
- Bridge state encapsulated in startAutomationBridge closure instead
  of module-level lets
- Previous browser WS closed on new connection to prevent leaks
- walkNodes returns boolean for early termination, find stops at limit
- Unused imports removed from node.ts (fmtList, nodeToData)
- Hand-rolled hex in node.ts replaced with colorToHex from core
- makeFigmaFromStore extracted to shared figma-factory.ts, used by
  both ai/tools.ts and automation/server.ts
- Unused limit param removed from AnalyzeColorsArgs
- Unused groupBy param removed from AnalyzeTypographyArgs
2026-03-07 20:42:37 +03:00
Danila Poyarkov c9e755a181 Fix RPC bridge response unwrapping and export
- Bridge was double-wrapping responses ({ok, result: {ok, base64}}) — now
  forwards the server's payload directly, stripping only type/id fields
- Compute layouts after mutations so auto-layout frames position correctly
- Export createElement and resolveToTree from core for bridge JSX transform
- Fix package.json exports: remove node condition that pointed to non-existent
  dist/, use publishConfig.exports for npm consumers
2026-03-07 20:27:57 +03:00
Danila Poyarkov 1f04926166 Compute layouts after mutating automation commands
renderTreeNode and mutating tools create auto-layout frames but didn't
trigger Yoga layout computation, leaving children stacked at (0,0).
Call computeAllLayouts after mutations so frames size and position correctly.
2026-03-07 20:18:59 +03:00
Danila Poyarkov 70c25cddf5 Fix render tool in automation: use ssrLoadModule for JSX transform
The render tool needs esbuild to transform JSX → createElement calls, but
esbuild only runs in Node, not in the browser where the automation server
executes commands. The bridge now:

1. Intercepts render tool calls with JSX
2. Uses Vite's ssrLoadModule to import @open-pencil/core (handles TS source)
3. Transforms JSX → tree on the Node side via buildComponent + resolveToTree
4. Sends the tree to the browser which calls renderTreeNode directly

Also fixes @open-pencil/core exports: remove "node" condition that pointed
to non-existent dist/ during development. Published consumers get dist/ via
publishConfig.exports override.
2026-03-07 20:16:52 +03:00
Danila Poyarkov 39af21ff06 Pre-process render JSX in bridge where esbuild is available
The render tool needs esbuild to transform JSX, but esbuild only runs in
Node — not in the browser where the automation server executes. The bridge
now intercepts render tool calls, converts JSX to a tree on the Node side
using buildComponent + resolveToTree from core, and sends the tree to the
browser which calls renderTreeNode directly.

Also exports createElement and resolveToTree from core for bridge use.
2026-03-07 20:10:48 +03:00
Anton A S 513e0b6f4a Add SEO: OG tags, Twitter Card, hreflang, JSON-LD, sitemap
- config.ts: og:site_name, og:image (+w/h/alt), twitter:card/site/image
- config.ts: transformPageData — per-page canonical, og:url, og:locale,
  og:locale:alternate, hreflang for all 6 locales + x-default,
  og:title/description and twitter:title/description from frontmatter
- config.ts: sitemap with xhtml:link alternates for all 174 pages × 6 locales
- SchemaOrg.vue: SoftwareApplication JSON-LD on EN homepage only
- HomeLayout.vue: render SchemaOrg in home-features-after slot
- index.md + de/fr/es/it/pl index.md: add translated title to frontmatter
2026-03-07 19:49:24 +03:00
Danila Poyarkov 2a9d47a761 Fix Vite build: import constants via relative path for esbuild compat
bridge.ts is bundled by esbuild as a Vite plugin — it can't resolve
workspace package entries (@open-pencil/core) at config time because
dist/ is not built yet. Use relative import to the source file instead.
2026-03-07 19:49:09 +03:00
Anton A S 940d0de5b6 Sync docs with v0.7.0 and unreleased features
- Update comparison tables: 78 tools (was 75), SVG export no longer a Penpot advantage,
  renderer LOC updated to ~3,200 after split into 10 files
- Update figma-comparison: Rename layers , SVG export , +Copy/Paste as, +Tailwind export,
  +Stroke align, +per-side stroke weights; coverage 88/152 → 94/158
- Add What's Next roadmap to architecture.md: AI providers, figma-use tool set,
  CI tooling, prototyping, CSS Grid, PDF export, .fig fidelity
- Update user-guide: SVG in export format table, Copy/Paste as submenu,
  stroke align + per-side weights, layer inline rename, mobile drawer, Code tab format toggle
- Fix keyboard shortcuts: ⌘N/⌘T/⌘W , ⌘\ , add ⇧⌘C 
- Expand MCP tools reference from ~25 to all 78 tools in full category tables
- Add Homebrew tap install to Getting Started
- Add new features.md sections: SVG export, Copy/Paste as, stroke align, mobile/PWA,
  Tailwind JSX export, Google Fonts fallback, auto-save toggle, Homebrew tap,
  layer rename, renderer profiler
- Full locale sync for DE, ES, FR, IT, PL: all 7 files updated in each locale
2026-03-07 19:25:41 +03:00
Anton A S e828185d9e Merge branch 'master' into add-vitepress-docs 2026-03-07 19:01:09 +03:00
Danila Poyarkov 2ec382fc9d Fix RPC bridge review issues: centralize colors, ports, remove non-null assertions
- Use colorToHex/colorDistance from color.ts instead of hand-rolled hex math
  in rpc/commands.ts (removes toHex, hexToRgb, colorDistance duplicates)
- Extract AUTOMATION_HTTP_PORT/AUTOMATION_WS_PORT to core constants, import
  in bridge.ts, server.ts, app-client.ts instead of duplicating magic numbers
- Add requireFile() helper in app-client.ts, replace all file! non-null
  assertions across 12 CLI command files
- Document same-machine trust security model in bridge.ts header comment
- Replace (globalThis as any).Bun with typed isBunRuntime() helper
- Add changelog entry for CLI-to-app RPC bridge feature
2026-03-07 15:11:31 +03:00
Danila Poyarkov 99365384df Merge remote-tracking branch 'origin/master' into fix-cli-rpc
# Conflicts:
#	packages/core/src/index.ts
2026-03-07 15:03:40 +03:00
Danila Poyarkov 72cbd195ac Trim internal refactor details from changelog 2026-03-07 14:56:35 +03:00
Danila Poyarkov 898932d5d7 Update changelog with reka-vueuse refactor 2026-03-07 14:55:24 +03:00
Danila Poyarkov 97baef474d Merge branch 'reka-vueuse-refactor' 2026-03-07 14:46:40 +03:00
Danila Poyarkov 7cdb1d1eaa Replace Bun.serve with Hono + ws for Node.js compatibility
Bridge now uses Hono for the HTTP server and ws for WebSocket —
works on both Bun and Node.js. Uses @hono/node-server as fallback
when Bun runtime is not available.
2026-03-07 14:30:12 +03:00
Danila Poyarkov 3684caea87 Fix duplicate :class, rename race, useFileDialog leak, restore clip/wrap 2026-03-07 14:27:17 +03:00
Danila Poyarkov 19fb22c267 Update changelog with refactor batch 1 2026-03-07 13:48:25 +03:00
Danila Poyarkov 14b796a40d Add 8 E2E test suites for release sanity coverage
83 new tests across 8 files:
- design-panel: selection → properties panel, fill/stroke/effect add, visibility toggle, multi-select
- code-panel: JSX output, OpenPencil/Tailwind toggle, copy button, empty state
- components: create component (⌘⌥K), create instance, propagation, detach
- copy-paste: store copy/paste, ⌘D duplicate, cut, multi-select duplicate
- multi-page: add/switch/delete pages, rename, last-page protection
- text-editing: text tool, text node creation, typography section, frame tool
- keyboard-shortcuts: all 9 tool keys, ⌘A/Escape/Backspace, ]/[, ⌘G/⌘⇧G, ⌘\, ⌘Z/⌘⇧Z
- context-menu: right-click items, duplicate/visibility/lock/delete/group/component, Copy as submenu
2026-03-07 13:23:32 +03:00
Danila Poyarkov 7fbe21c8e1 Fix flaky E2E tests: layers panel, zoom-to-fit, snapshot stability
- layers-panel: navigate to /demo so demo layers exist
- app-menu zoom-to-fit: zoom in first so zoom-to-fit has something to change
- playwright.config: force workers=1 and colorScheme=dark for consistent
  WebGL/SwiftShader snapshot rendering across runs
- Update empty-canvas snapshot for current dark-mode canvas appearance
2026-03-07 11:08:22 +03:00
Danila Poyarkov bd5cdc8eee Centralize all color utilities in color.ts
- Add colorToHex8 (hex with alpha via culori formatHex8)
- Add colorToCSSCompact (no-space rgba for Tailwind shadow classes)
- Add normalizeColor (partial Color → full Color with defaults)
- Add colorDistance (Euclidean RGB via culori differenceEuclidean)
- Replace colorToCSS body with culori formatRgb
- Change rgba255ToColor to positional args (r, g, b, a)
- Remove duplicate formatColor from svg-export.ts and export-jsx.ts
- Remove duplicate colorDistance from tools/analyze.ts
- Remove duplicate convertColor from kiwi/kiwi-convert.ts
- Replace hand-rolled hex+alpha in HsvColorArea.vue with colorToHex8
- Replace hand-rolled rgba255→Color in HsvColorArea.vue with rgba255ToColor
- Expand color.test.ts from 16 to 34 tests
2026-03-07 10:02:11 +03:00
Danila Poyarkov 9784544f1f Clean up tools/schema, add geometry.ts, isMixed helper, fix imports, add tests
- Strip tools/schema.ts from 1831 to 65 lines (remove duplicate tool defs)
- Fix tools/index.ts to export ALL_TOOLS from registry instead of schema
- Fix renderJsx → renderJSX typo in tools/create.ts and structure.ts
- Add geometry.ts with shared rotation/coordinate math utilities
- Add isArrayMixed() helper to use-multi-props.ts, deduplicate FillSection/StrokeSection/EffectsSection
- Fix broken test imports: use @open-pencil/core instead of relative paths into packages/core/src/
- Merge duplicate import statements across all test files
- Export profiler internals and style-run helpers from core index.ts
- Add 6 new test files: color, undo, snap, vector, style-runs, text-editor (98 new tests)
- Update renderer-effects test for renderer/ directory split
2026-03-06 22:33:10 +03:00
Danila Poyarkov e7e5f53b57 Add CLI-to-app RPC bridge for live document access
- Extract shared RPC command handlers into packages/core/src/rpc/
  (info, pages, tree, find, node, variables, analyze colors/typography/spacing/clusters)
- Add automation bridge (src/automation/bridge.ts) that runs in Vite/Bun process,
  listens on localhost:7600 (HTTP) and :7601 (WebSocket)
- Add browser-side handler (src/automation/server.ts) that connects via WebSocket,
  executes commands against live EditorStore with requestRender()/flashNodes()
- Supports eval, tool execution, and image export via RPC
- Refactor all CLI commands: file arg is now optional — omit it to connect
  to the running app instead of loading a .fig file
- Bearer token auth generated per session, exposed via /health endpoint
- Vite plugin starts the bridge automatically during dev
2026-03-06 22:29:49 +03:00
Danila Poyarkov 859143149e Split renderer.ts into renderer/ directory 2026-03-06 22:25:59 +03:00
Danila Poyarkov 31326e8e5e Eliminate as Record<string, unknown> casts
- Add index signature to NodeChange for Kiwi codec fields
- Add blobs field to FigmaMessage
- Use 'in' type guards instead of Record casts in ai-adapter
- Use Object.fromEntries for Partial<SceneNode> property copying
- Use satisfies instead of as for handle position map
- Type node() to accept { children?: unknown; [key: string]: unknown }
- Remove ext() helper in kiwi-convert (direct property access)

37 occurrences → 1 (Kiwi codec boundary only).
2026-03-06 21:43:32 +03:00
Danila Poyarkov 4dc127f2d2 Configure oxfmt import sorting with proper groups
Replace experimentalSortImports with sortImports.
Groups: builtin → external → internal (@open-pencil/, @/).
Newlines between groups, alphabetical within.
2026-03-06 21:43:23 +03:00
Danila Poyarkov c33e4152df Fix PWA manifest error in dev, handle invalid font data
Remove hardcoded manifest link from index.html (VitePWA injects
it in production builds). Catch FontFace.load() rejections from
invalid font data with a warning.
2026-03-06 21:43:16 +03:00
Danila Poyarkov 07e9182b4c Move collab routing logic into CollabPanel
CollabPanel now uses injected collab + useRouter() directly.
No more emit relay through EditorView.
2026-03-06 21:43:10 +03:00
Danila Poyarkov b4698d7a63 Use colorToCSS() instead of hand-rolled rgba conversions
Fix colorToCSS to include alpha channel. Replace all manual
Math.round(c.r * 255) patterns with colorToCSS() from core.
2026-03-06 21:43:03 +03:00
Danila Poyarkov 9d73297040 Delete re-export shims, import from @open-pencil/core directly
Remove 14 src/engine/ shims and entire src/kiwi/ directory.
Only src/engine/fonts.ts remains (has real Tauri font logic).
Replace isTauri() with IS_TAURI constant.
2026-03-06 21:42:56 +03:00
Danila Poyarkov 6ec8fc518b Move demo to /demo route, add @unhead/vue for title management
- / shows empty canvas
- /demo loads demo content (for app.openpencil.dev landing link)
- Title template: '{page} — OpenPencil' via useHead
- 'Try it online' links in README and docs point to /demo
2026-03-06 20:54:48 +03:00