openpencil/packages/fig
Danila Poyarkov 12b6662ba3
fix(fig): keep Figma's order keys on instances and untouched siblings (#819)
* fix(fig): keep Figma's order keys on instances and untouched siblings

Materialized instance occurrences were built without the record's
parentIndex position, so every imported instance lost its key and was
renumbered on save. They now carry it like other imported nodes.

Sibling keys anchored greedily on the first imported key, so a layer moved
up past its siblings kept its key and pushed every sibling after it onto a
new one. Keep the longest increasing run of imported keys instead, so only
the moved and inserted layers are re-keyed.

* fix(fig): don't anchor sibling keys on one nothing can precede

A moved layer in front of the lowest key ('!') left no room below it, so
the anchor was dropped and every sibling up to the next anchor re-keyed.
Such a key no longer starts the kept run when a sibling precedes it.
2026-10-04 10:16:01 +00:00
..
docs fix(fig): read, render, and write Figma slots (#850) 2026-10-04 00:45:10 +04:00
scripts feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
src fix(fig): keep Figma's order keys on instances and untouched siblings (#819) 2026-10-04 10:16:01 +00:00
tests fix(fig): keep Figma's order keys on instances and untouched siblings (#819) 2026-10-04 10:16:01 +00:00
AGENTS.md feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
package.json feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
README.md feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
tsconfig.json fix: explain unsupported browsers instead of a blank window (#745) 2026-09-22 14:40:59 +04:00
tsconfig.test.json feat(fig): scaffold package shell 2026-06-30 10:51:36 +03:00
tsdown.config.ts refactor(fig): own Figma clipboard encoding and conversion 2026-09-11 00:36:03 +03:00

@open-pencil/fig

.fig file-format package for OpenPencil.

The package owns the outer .fig archive boundary and is the staged home for Figma-specific SceneGraph conversion policy. Production SceneGraph read/write remains available through @open-pencil/core/io while conversion modules move behind this package's public API.

Current ownership:

  • Complete .fig archive parsing through parseFigBuffer()
  • .fig archive assembly through writeFigArchive()
  • Canvas payload and image resource handling
  • readFigContainer() / writeFigContainer() helpers for raw fig-kiwi payloads
  • .fig source and archive result types
  • NodeChange-to-SceneGraph property conversion, including styles, plugin metadata, text, paint, vector, and font policy, through @open-pencil/fig/node-change
  • Component-property, symbol-override, derived-symbol-data, and instance synchronization policy through @open-pencil/fig/instance-overrides
  • Effective raw-metadata precedence and invalidation over SceneGraph's format-neutral edited-field tracking
  • SceneGraph-to-NodeChange export conversion with an explicit glyph-outline runtime service
  • Package-local archive, conversion, instance, export, and dist smoke tests

Architecture documentation

Start with the package docs for the source model, instance evaluation, materialization, document sessions, export, and validation contracts.

Planned ownership:

  • Oracle-backed .fig fixtures

Non-goals:

  • Generic Kiwi schema/runtime internals — use @open-pencil/kiwi
  • Format-neutral IO registration, export targeting, CanvasKit thumbnails, or browser workers — use @open-pencil/core/io
  • Editor actions, renderer behavior, Vue/app UI, CLI formatting, or MCP transport

This follows the existing @open-pencil/pen pattern: a format package owns its source model/parser and SceneGraph policy, while core registers it in the shared IO system.

Checks

cd packages/fig
bun run check