* feat(design-jsx): export every property the renderer accepts JSX export wrote only part of a layer: one solid fill, one stroke without its alignment, shadows as repeated attributes, background blurs as layer blurs, and nothing for hidden children, constraints, size limits, absolute positioning, vertical text alignment, masks, or variable bindings. Rendering an export lost those properties, and JSX diffs could not see changes to them. The export now writes them, using paint and effect helper calls when a shorthand cannot express a value exactly, and leaves out values the renderer would infer, so ordinary output stays as it was. Prop values can now hold objects, arrays, and helper calls, printed through @open-pencil/codegen's builders, which gain a call expression. The language gains `visible`, `locked`, `constraints` (Figma's constraints object with lowercase values, as `blendMode` uses), `italic`, `strokes`, `strokeWeights`, `strokeCap`, and `strokeJoin`, and now applies `strokeAlign`, `strokeDash`, and the size limits, which it accepted but ignored. Per-corner radii are written even when the uniform radius is 0. A round-trip test renders each case's export and checks the fields and that exporting again changes nothing. * docs(fig): name the saved-glyph fixture by its repository path The observation note linked the fixture with a relative path climbing four directories. Other notes name fixtures by their repository path, which reads the same from anywhere. * fix(design-jsx): export the node-level dash pattern A node's own dashPattern was not written, so a node dashed at node level came back solid and the DOM/CSS export chose a solid border. It now round-trips as a separate dashPattern prop; strokeDash stays the stroke-local dash. |
||
|---|---|---|
| .. | ||
| docs | ||
| scripts | ||
| src | ||
| tests | ||
| AGENTS.md | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| tsconfig.test.json | ||
| tsdown.config.ts | ||
@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
.figarchive parsing throughparseFigBuffer() .figarchive assembly throughwriteFigArchive()- Canvas payload and image resource handling
readFigContainer()/writeFigContainer()helpers for rawfig-kiwipayloads.figsource 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-
NodeChangeexport 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
.figfixtures
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