Commit graph

65 commits

Author SHA1 Message Date
Danila Poyarkov 5190a64017
fix(tauri): transfer FIG exports over binary IPC (#509)
- Return native FIG archives as raw IPC responses instead of JSON byte arrays

- Decode the response as an ArrayBuffer and cover the binary contract

- Prevent large desktop exports from multiplying memory use during save
2026-08-13 22:23:37 +03:00
Danila Poyarkov c7b944d103 fix(kiwi): harden FIG containers and DOM imports
- Decode zstd FIG data and reject invalid compressed payloads

- Compose caller CSS with Tailwind defaults during DOM import

- Slice pooled fixture buffers to their exact byte range

Co-authored-by: Joseph Cumines <joeycumines@gmail.com>
2026-08-13 20:33:10 +03:00
Danila Poyarkov 7f91594d0c refactor: standardize acronym casing
- Rename first-party API, RPC, JSON, CORS, SVG, JSX, and related identifiers to preserve acronym casing
- Keep upstream and serialized boundary names unchanged
- Add a lint guardrail and migration notes for exported APIs
2026-08-10 15:48:16 +03:00
Danila Poyarkov 9c9e4fae08 refactor(mcp): align transport domain structure
- Group server, stdio, and transport implementation by ownership

- Mirror those domains in engine tests and centralize shared MCP fixtures
2026-07-25 22:59:59 +03:00
Danila Poyarkov 2b32a8c7d3 feat(mcp): add local transport discovery
- Prefer private Unix sockets with TCP fallback for local MCP clients

- Unify HTTP and WebSocket lifecycle, authentication, and cleanup

- Discover transport details from an owner-only runtime file
2026-07-25 21:29:03 +03:00
Danila Poyarkov f3fbc94abf feat(text): create text boxes by dragging 2026-07-20 21:22:30 +03:00
Danila Poyarkov 86d6a63d0f fix(fig): restore strict parse validation
- Reject corrupt compressed Kiwi chunks instead of accepting raw garbage\n- Tolerate legacy source metadata without editedFields in renderer fallbacks\n- Align font, derived glyph, shared style, renderer mock, and ownership tests with current contracts\n- Restore clean quick and heavy unit quality gates
2026-07-18 03:58:18 +03:00
Danila Poyarkov 8b9be17a56 perf(fig): remove large fixture bottlenecks
- Index component property definitions and variable asset references once per export or override context\n- Skip converged instance fill and text propagation and use native binary hex encoding\n- Add a non-populating parse mode for raw fixture validation\n- Reduce the Material 3 round trip from minutes to about twenty seconds
2026-07-18 03:37:58 +03:00
Danila Poyarkov 5371ed11b8 feat(app): migrate paint effect and export panels
- Share compact item-row and paint-field anatomy across Fill, Stroke, Effects, and Export
- Add COLOR binding transactions with picker rollback and one-step undo
- Replace bespoke panel test hooks with semantic selectors and visual coverage
2026-07-14 17:06:28 +03:00
Danila Poyarkov fcdf7f1d4c feat(app): migrate layout size controls
- Replace duplicated width and height binding branches with shared semantic fields

- Switch edited Hug and Fill dimensions to Fixed in one reversible transaction

- Add typed LayoutControls actions, documentation, and visual coverage
2026-07-13 15:34:25 +03:00
Danila Poyarkov 1d60d3a407 feat(ui): add binding field skins
- Show one variable picker affordance with a quiet identity pill and accessible combobox

- Keep bound NumberField focus non-destructive until the first value mutation

- Prefer accessible and semantic test selectors over compound test IDs
2026-07-13 14:04:13 +03:00
Danila Poyarkov 5d9730ae04 feat(vue): finalize NumberField API and docs
- Remove ScrubInput aliases, app wrappers, test hooks, and translated legacy references

- Share a Tailwind NumberField demo between Storybook and VitePress

- Generate component API tables from Vue metadata and type-check examples with Twoslash

- Upgrade the docs stack to VitePress 2
2026-07-13 10:19:24 +03:00
Danila Poyarkov 8b1c452cc3 refactor(cli): replace DOM command with import and HTML export 2026-07-04 13:34:24 +03:00
rcoenen d2d816b688
fix(collab): replicate document content to joiners
Squashed PR #340 with maintainer follow-up fixes and local validation.
2026-06-30 11:56:58 +03:00
Danila Poyarkov 3a5b6a5c37 test: share scene variable helper 2026-06-30 10:55:05 +03:00
Danila Poyarkov 898431e646 feat: split SceneGraph and Pen packages 2026-06-30 10:54:32 +03:00
Danila Poyarkov 346d13c405 feat(dom-css): map image aspect styles 2026-06-30 10:51:37 +03:00
Danila Poyarkov 3f1a5ce779 feat(dom-css): map browser text casing 2026-06-30 10:51:05 +03:00
Danila Poyarkov 5b61c1bf46 test(dom-css): expand fixture matrix 2026-06-30 10:47:26 +03:00
Danila Poyarkov 101a047e4d test(dom-css): share CSS fixture suite 2026-06-30 10:47:25 +03:00
Danila Poyarkov 568cdf91ef Merge remote-tracking branch 'joey/feature-overlapping-element-analysis-tool' into pr352-local-merge
# Conflicts:
#	tests/engine/clipboard/fixtures/gold-preview-roundtrip.test.ts
#	tests/engine/io/fig/import/group-reclassify.test.ts
#	tests/engine/io/fig/roundtrip/glyph-blob.test.ts
#	tests/engine/layout/auto-layout/text/measurement.test.ts
2026-06-30 09:47:07 +03:00
Joseph Cumines dc9638ac3e
fix(export): prevent GUID collisions and file corruption on .fig round-trip (#333)
* fix(export): prevent GUID collisions and file corruption on .fig round-trip

Nodes sharing the same imported source.id (component instance children,
cloned subtrees) silently overwrote each other on export because the
GUID assignment reused imported GUID values without checking for
duplicates.  This caused data loss on reimport — only the last node
with a given GUID survived.

- Track all assigned GUID values in a Set for O(1) collision detection.
- Scan imported source.ids for both sessionID 0 and 1 before assigning
  any new GUIDs, so the counter starts past every imported value.
- Fall back to counter-based GUIDs when source.id collides with an
  already-assigned value.

Additional fixes in the same change set:

- cloneTree now deep-copies source.fig via structuredClone, preventing
  mutations on a clone from corrupting the original node's kiwi payload.
- Removed decompressFigKiwiData sync wrapper (zero callers) and the
  silent try/catch fallback in parseFigKiwiContainer that masked
  corrupt data as raw bytes.
- buildFigKiwi uses Bun.zstdCompressSync when available, matching the
  zstd decompression path already used on import.
- Fixed setSavedVersion ordering in read.ts — must run after
  requestRender to capture the post-bump version, preventing spurious
  dirty-state immediately after file reload.

Tests: GUID collision (2 and 3 node), clone isolation, parse failure,
text export zstd compatibility, gold-preview round-trip.

* fix(export): handle EXCLUDE boolean operation and BOOLEAN_OPERATION node type

The internal representation uses EXCLUDE for exclude boolean operations,
but Figma's kiwi schema uses XOR. Map EXCLUDE back to XOR on export so
round-trips through .fig files don't fail. Also add BOOLEAN_OPERATION to
VALID_NODE_TYPES and increase timeout for heavy material3 fixture test.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* style: format export-node.ts

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test: add type guard after null assertion in guid-collision test

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(clipboard): detect zstd-compressed data before zlib inflate

fflate's inflateSync silently accepts zstd-compressed data and returns
garbage instead of throwing. Check for the zstd magic bytes (28 b5 2f
fd) before attempting zlib decompression. Also revert the EXCLUDE enum
addition to the kiwi schema since the export-node.ts mapping is
sufficient.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(clipboard): add length guard before zstd magic byte check

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(scene-graph): group clone regression coverage

* ci: retrigger CI checks

* test: increase timeouts for heavy .fig fixture tests on slow CI runners

Gold-preview.fig and material3.fig parsing/export tests consistently
exceed the 5s bun:test default timeout on GitHub Actions runners.
Increase to 30s for: beforeAll codec init, clipboard roundtrip,
glyph blob roundtrip, group reclassification, and text measurement.

* test: add individual test timeouts for heavy .fig fixture tests

The beforeAll timeout helped but individual test() calls also need
explicit 30s timeouts since bun:test applies the 5s default per-test.
Fixes remaining CI flakes in glyph-blob roundtrip and clipboard
roundtrip tests.

* test: increase beforeAll timeout for render cache test

The canvas/render cache test loads gold-preview.fig AND initializes
CanvasKit (Skia WASM), which is much slower than the other fixture
tests. Use 60s timeout to account for slow CI runners.

* fix(export): reserve document GUID to prevent 0:0 namespace collision

- Add docGuid (0:0) to assignedGuidValues before processing imported
  node source.ids, preventing an imported node with source.id "0:0"
  from reusing the document's GUID slot
- Add regression test using session-0 source.ids to verify nodes
  survive roundtrip without document GUID collision
- Remove unnecessary async keyword from synchronous component
  metadata test

* fix(export): guard canvas GUID reuse with assignedGuidValues check

- Mirror getOrCreateNodeGuid() collision logic in buildCanvasEntries():
  if an imported page's source.id maps to a GUID already in
  assignedGuidValues, generate a fresh counter-based GUID instead
- Prevents canvas-level last-write-wins when multiple pages share
  the same source.id or a page uses 0:0

* fix(test): use explicit little-endian writes and fix misleading test title

- Replace host-endian Uint32Array writes with DataView.setUint32(offset, value, true) in parse-failures.test.ts to ensure platform-independent fig-kiwi container assembly
- Rename test title from "clone clears source.id from the original" to "clone clears source.id from the clone" to accurately reflect what the assertions verify

* test(io): use file-level timeout for heavy fixture

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Danila Poyarkov <dev@dannote.net>
2026-06-23 18:05:23 +03:00
Joseph Cumines fa5c072cad test: extend timeout for slow gold-preview fixture tests
Port the timeout fixes from PR #351 that resolved the unit-test CI
timeouts. Add HEAVY_TEST_TIMEOUT_MS (30s) in tests/helpers/test-utils.ts
and apply it to the slow gold-preview.fig fixture tests/hooks:
- clipboard roundtrip
- group reclassification
- glyph blob preservation
- auto-layout text measurement
- render/canvas/cache
2026-06-19 11:05:25 +10:00
Joseph Cumines f862beb08d Add heuristic overlap detection tool and CLI
Implement the analyze overlaps CLI command, RPC endpoint, and ToolDef
to enable heuristic detection of visual overlaps, parent overflows, and
overlay patterns. Geometry computation now uses world-matrix visual
bounds to handle nested ancestor rotations and clipping frames correctly.

Update file-backed CLI commands to use Node fs/promises instead of Bun
runtime file APIs. This is required for the published CLI to function
when installed and executed in a standard Node environment. Add the
package.json subpath export to the core package for metadata consumers.
2026-06-19 09:54:27 +10:00
Danila Poyarkov abd795bd9a chore: format codebase 2026-05-24 12:15:29 +03:00
Danila Poyarkov a48b23129f fix(fig): stabilize engine test suite 2026-05-21 14:54:17 +03:00
Danila Poyarkov f3649550f2 chore: enable stricter oxlint rules 2026-05-18 18:58:30 +03:00
Danila Poyarkov 11e38b626a test(e2e): extract shared editor setup fixture
- useEditorSetup() / useEditorSetupWithClear() in tests/e2e/fixtures.ts
- Migrated 17 specs to shared fixture, removing ~300 lines of boilerplate
- Moved getSelectedNode/getSelectedNodes to shared store helpers
- Replaced inline getSelectedNode in 4 specs with shared import
- Test duplication: 329 → 308 clones (10.12% → 9.08%)
2026-05-16 16:19:03 +03:00
Danila Poyarkov cb51fc73fc test(tauri): clean up font cache mocks 2026-05-16 13:55:09 +03:00
Danila Poyarkov 692ddf9a3f refactor(toolbar): reuse test id helpers 2026-05-15 13:13:24 +03:00
Danila Poyarkov 698bcde00b refactor(vue): share generated test id helpers 2026-05-15 13:10:44 +03:00
Danila Poyarkov 6b406002dd test(e2e): remove remaining raw test id strings 2026-05-15 13:02:41 +03:00
Danila Poyarkov 2f94ce6510 test(e2e): use Playwright test id locators 2026-05-15 12:49:49 +03:00
Danila Poyarkov 541c9bd13c test: move tauri helpers into domain folder
- Move tests/helpers/tauri-mocks.ts → tests/helpers/tauri/mocks.ts
- Move tests/helpers/tauri-fig-export-fixture.ts → tests/helpers/tauri/fig-export-fixture.ts
- Update all imports
2026-05-06 16:16:08 +03:00
Danila Poyarkov 432f945da6 chore(tests): narrow no-empty-function exceptions
- Replace simple no-op test callbacks with explicit undefined returns
- Remove no-empty-function exceptions for autosave, stroke picker, font settings, pen, tauri, AI adapter, and undo helper tests
- Validate check plus affected engine and E2E tests
2026-05-06 12:32:54 +03:00
Danila Poyarkov bbf122a5c5 chore(tests): route store access through browser bridge
- Expose window.openPencil.getStore() instead of a direct store property
- Update E2E helpers and specs to use the bridge getter
- Add lint coverage preventing direct window.openPencil.store access
2026-05-06 12:19:39 +03:00
Danila Poyarkov 8ec70330b4 chore(lint): centralize OpenPencil window API
- Route browser globals through src/app/window-api.ts instead of private __OPEN_PENCIL fields
- Move E2E tests to the public window.openPencil test API
- Add an oxlint rule banning direct window.__OPEN_PENCIL* access
2026-05-06 10:38:03 +03:00
Danila Poyarkov 39675b2969 chore(tests): remove easy non-null assertions
- Replace browser store non-null assertions with explicit initialization guards
- Use expectDefined for optional test resources and tool results
- Clean low-count non-null assertions in font, icon, snap, OKHCL, and visual tests
2026-05-06 02:59:56 +03:00
Danila Poyarkov a63ac93a3d chore(lint): enforce type imports in tests
- Remove the broad test exception for consistent type imports
- Mark test-only core and helper imports as type imports where appropriate
- Keep targeted validation for affected engine tests
2026-05-06 02:35:57 +03:00
Danila Poyarkov c3f5189f8f style: tighten import grouping
- Configure oxfmt custom import groups for workspace, app, package, and test aliases
- Keep type imports grouped with their matching source category instead of one global tail group
- Expand the format script to cover formatter config, Vite files, and scripts
2026-05-06 02:22:08 +03:00
Danila Poyarkov e42dffa003 chore(lint): consolidate oxlint config
- Merge structural lint rules into oxlint.json and remove the second config file
- Add #tests/* path aliases and rewrite deep test helper imports
- Ban new deep parent-relative imports through the shared lint config
2026-05-06 02:05:02 +03:00
Danila Poyarkov c31e7ae7d4 test(selection): split multi-selection coverage
- Move multi-selection.test.ts into focused flip, alignment, and property files
- Reuse scene and assertion helpers for selection tests
- Preserve all 22 multi-selection tests and enforce non-null assertion cleanup on the new folder
2026-05-06 01:56:27 +03:00
Danila Poyarkov c47f8a0359 test(layout): split auto and grid coverage
- Move layout.test.ts into auto-layout and grid-layout files
- Add shared layout helpers for test graph setup and fixture loading
- Preserve all 95 layout tests after the split
2026-05-06 01:54:56 +03:00
Danila Poyarkov 0532dfc697 test(clipboard): split editor clipboard coverage
- Move clipboard.test.ts into focused import, bounds, HTML encoding, and fixture roundtrip files
- Add a shared clipboard graph helper for import tests
- Preserve all 29 clipboard tests after the split
2026-05-06 01:53:10 +03:00
Danila Poyarkov 2aecb2df85 test(tools): split tool registry coverage
- Move tools.test.ts into focused registry, create, modify, read, and structure files
- Add shared tool test helpers for graph setup and tool lookup
- Preserve all 38 tool tests after the split
2026-05-06 01:51:19 +03:00
Danila Poyarkov 75e62507a5 test(fig): split import and roundtrip coverage
- Move fig-roundtrip.test.ts into focused import, export, roundtrip, and heavy fixture files
- Add shared fig fixture helpers for fixture parsing and valid node type checks
- Preserve the original 51 passing and 8 skipped fig tests under BUN_HEAVY_TESTS=false
- Extend scoped non-null assertion enforcement to the fig test folder
2026-05-06 01:49:25 +03:00
Danila Poyarkov 51eae14e4b chore(tests): remove targeted non-null assertions
- Add shared test helpers for required nodes and child ids
- Clean non-null assertions from noisy render, nudge, text undo, and fig roundtrip tests
- Enforce the non-null assertion ban for the cleaned test files
- Remove stale eslint disables around empty functions and broad mock transport typing
2026-05-06 01:14:50 +03:00
Danila Poyarkov fae190a673 chore(lint): remove unsafe test casts
- Enforce explicit-any and TypeScript suppression bans in tests
- Remove remaining broad any casts from engine and e2e coverage
- Split markdown ambient declarations from typed browser globals
2026-05-06 00:42:45 +03:00
Danila Poyarkov 3bd01095eb test(app): cover remaining Tauri integrations 2026-05-05 22:45:14 +03:00
Danila Poyarkov 0f9b69d051 test(app): expand Tauri helper coverage 2026-05-05 22:07:02 +03:00