60 lines
2.2 KiB
Markdown
60 lines
2.2 KiB
Markdown
# File Format
|
|
|
|
## .fig File Structure
|
|
|
|
```
|
|
┌─────────────────────────────────┐
|
|
│ Magic header: "fig-kiwi" (8B) │
|
|
│ Version (4B uint32 LE) │
|
|
│ Schema length (4B uint32 LE) │
|
|
│ Compressed Kiwi schema │
|
|
│ Message length (4B uint32 LE) │
|
|
│ Compressed Kiwi message │ ← NodeChange[] (entire document)
|
|
│ Blob data │ ← Images, vector networks, fonts
|
|
└─────────────────────────────────┘
|
|
```
|
|
|
|
## Import Pipeline
|
|
|
|
```
|
|
.fig file → Parse header → Decompress Zstd → Decode Kiwi schema
|
|
→ Decode Message → NodeChange[] → Build SceneGraph
|
|
→ Resolve blob refs → Render on canvas
|
|
```
|
|
|
|
## Kiwi Binary Codec
|
|
|
|
The codec handles Figma's 194-definition Kiwi schema with NodeChange as the central type (~390 fields). Key components:
|
|
|
|
- **kiwi-schema** — vendored from evanw/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 vendored kiwi-schema parser is patched to handle this correctly.
|
|
|
|
### Compression
|
|
|
|
.fig files use Zstd compression for both the schema and message payloads. The `fzstd` library handles decompression. For clipboard encoding, `fflate` provides lightweight compression.
|
|
|
|
## Supported Formats
|
|
|
|
| Format | Import | Export |
|
|
|--------|--------|--------|
|
|
| .fig (Figma) | ✅ | — |
|
|
| .svg | Planned | Planned |
|
|
| .png | Planned | Planned |
|
|
| .pdf | — | Planned |
|
|
|
|
## Clipboard Format
|
|
|
|
Copy/paste uses the same fig-kiwi binary encoding:
|
|
|
|
1. **Copy** — encode selected NodeChange[] to Kiwi binary, compress, write to clipboard as `application/x-figma-design` MIME type
|
|
2. **Paste** — read clipboard, decompress, decode Kiwi binary, create nodes in scene graph
|
|
3. **Synchronous** — encoding happens in the copy event handler (not async Clipboard API) to ensure browser compatibility
|
|
|
|
This enables bidirectional clipboard between OpenPencil and Figma.
|