openpencil/packages/docs/reference/file-format.md
Danila Poyarkov d91e6a36d9 Fix code formatting across all docs
- Wrap all enum values in backticks (FRAME, SOLID, ROUND, etc.)
- Fix single-backtick code blocks → triple backticks in node-types, scene-graph
- Replace ASCII diagrams with mermaid in file-format
- Delete stale mcp-tools.md and eval-command.md from all locales
- Update dead links: /reference/mcp-tools → /programmable/mcp-server,
  /eval-command → /programmable/cli/scripting
2026-03-08 13:53:33 +03:00

95 lines
2.8 KiB
Markdown

# File Format
## .fig File Structure
A `.fig` file is a ZIP archive containing a Kiwi-encoded binary message:
```mermaid
block-beta
columns 1
A["Magic header: <code>fig-kiwi</code> (8 bytes)"]
B["Version (4 bytes, uint32 LE)"]
C["Schema length (4 bytes, uint32 LE)"]
D["Compressed Kiwi schema"]
E["Message length (4 bytes, uint32 LE)"]
F["Compressed Kiwi message — NodeChange[]"]
G["Blob data — images, vector networks, fonts"]
```
## Import Pipeline
```mermaid
flowchart LR
A[".fig file"] --> B["Parse header"]
B --> C["Decompress Zstd"]
C --> D["Decode Kiwi schema"]
D --> E["Decode message"]
E --> F["NodeChange[]"]
F --> G["Build SceneGraph"]
G --> H["Resolve blob refs"]
H --> I["Render"]
```
## Export Pipeline
```mermaid
flowchart LR
A["SceneGraph"] --> B["NodeChange[]"]
B --> C["Kiwi encode"]
C --> D["Compress"]
D --> E["Build ZIP"]
E --> F[".fig file"]
```
Export uses <kbd>⌘</kbd><kbd>S</kbd> (Save) and <kbd>⇧</kbd><kbd>⌘</kbd><kbd>S</kbd> (Save As) with native OS dialogs on the desktop app. The exported file includes a `thumbnail.png` required by Figma for file preview.
Compression uses Zstd via Tauri Rust command on desktop, with deflate fallback in the browser.
## Kiwi Binary Codec
The codec handles Figma's 194-definition Kiwi schema with `NodeChange` as the central type (~390 fields). Key components:
| Module | Purpose |
|--------|---------|
| `kiwi-schema` | Kiwi parser (from [evanw/kiwi](https://github.com/nicolo-ribaudo/kiwi)), patched for ESM and sparse field IDs |
| `codec.ts` | Encode/decode messages using the Kiwi schema |
| `protocol.ts` | Wire format parsing and message type detection |
| `schema.ts` | 194 message/enum/struct definitions |
### Sparse Field IDs
Figma's schema uses non-contiguous field IDs (e.g. 1, 2, 5, 10 with gaps). The kiwi-schema parser handles this correctly.
### Compression
`.fig` files use Zstd compression for both the schema and message payloads. Decompression uses the `fzstd` library. For export, Zstd compression is offloaded to a Tauri Rust command on the desktop app (better performance, correct frame headers). In the browser, deflate via `fflate` is used as a fallback.
## Supported Formats
| Format | Import | Export |
|--------|--------|--------|
| `.fig` (Figma) | ✅ | ✅ |
| `.svg` | Planned | Planned |
| `.png` | Planned | Planned |
| `.pdf` | — | Planned |
## Clipboard Format
Copy/paste uses the same Kiwi binary encoding:
```mermaid
flowchart LR
subgraph Copy
A["Selected nodes"] --> B["Encode NodeChange[]"]
B --> C["Compress"]
C --> D["Clipboard<br/><code>application/x-figma-design</code>"]
end
subgraph Paste
D --> E["Decompress"]
E --> F["Decode Kiwi"]
F --> G["Create nodes"]
end
```
This enables bidirectional clipboard between OpenPencil and Figma.