@grida/refig 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +333 -0
- package/dist/browser.d.mts +94 -0
- package/dist/browser.mjs +15 -0
- package/dist/chunk-DAHUXARL.mjs +16057 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +239 -0
- package/dist/index.d.mts +17 -0
- package/dist/index.mjs +30 -0
- package/package.json +71 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Grida
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# `@grida/refig`
|
|
2
|
+
|
|
3
|
+
> **re**nder **fig**ma — headless Figma renderer in the spirit of [`resvg`](https://github.com/nicolo-ribaudo/resvg-js)
|
|
4
|
+
|
|
5
|
+
Render Figma documents to **PNG, JPEG, WebP, PDF, and SVG** without Figma Desktop and without a browser.
|
|
6
|
+
|
|
7
|
+
Pass a `.fig` file or a Figma REST API JSON response, pick a node, get pixels.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pnpm add @grida/refig
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Entrypoints
|
|
16
|
+
|
|
17
|
+
| Import | Environment | Notes |
|
|
18
|
+
| ---------------------- | ----------- | ------------------------------------------------------------------------- |
|
|
19
|
+
| `@grida/refig` | **Node.js** | Default. Includes `fs` helpers for reading `.fig` / JSON files from disk. |
|
|
20
|
+
| `@grida/refig/browser` | **Browser** | No `node:fs` dependency. Accepts `Uint8Array` and JSON objects only. |
|
|
21
|
+
|
|
22
|
+
Both entrypoints export the same core API (`FigmaDocument`, `FigmaRenderer`, types). The only difference is that the Node entrypoint adds a convenience `FigmaDocument.fromFile(path)` static method.
|
|
23
|
+
|
|
24
|
+
## Quick start (Node)
|
|
25
|
+
|
|
26
|
+
### Render from a `.fig` file
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
30
|
+
import { FigmaDocument, FigmaRenderer } from "@grida/refig";
|
|
31
|
+
|
|
32
|
+
const doc = FigmaDocument.fromFile("path/to/file.fig");
|
|
33
|
+
const renderer = new FigmaRenderer(doc);
|
|
34
|
+
|
|
35
|
+
const { data } = await renderer.render("<node-id>", {
|
|
36
|
+
format: "png",
|
|
37
|
+
width: 1024,
|
|
38
|
+
height: 1024,
|
|
39
|
+
scale: 2,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
writeFileSync("out.png", data);
|
|
43
|
+
renderer.dispose();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Render from Figma REST API JSON
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
50
|
+
import { FigmaDocument, FigmaRenderer } from "@grida/refig";
|
|
51
|
+
|
|
52
|
+
// GET /v1/files/:key — fetched by your own client
|
|
53
|
+
const json = JSON.parse(readFileSync("figma-response.json", "utf-8"));
|
|
54
|
+
|
|
55
|
+
const renderer = new FigmaRenderer(new FigmaDocument(json));
|
|
56
|
+
|
|
57
|
+
const { data } = await renderer.render("<node-id>", {
|
|
58
|
+
format: "svg",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
writeFileSync("out.svg", data);
|
|
62
|
+
renderer.dispose();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
> Fetching / authentication is intentionally out of scope. Provide the document data from your own API layer.
|
|
66
|
+
|
|
67
|
+
### Render from REST JSON with custom images
|
|
68
|
+
|
|
69
|
+
When your document has IMAGE fills, pass image bytes keyed by the Figma image ref (hash):
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
73
|
+
import path from "node:path";
|
|
74
|
+
import { FigmaDocument, FigmaRenderer } from "@grida/refig";
|
|
75
|
+
|
|
76
|
+
const json = JSON.parse(readFileSync("figma-response.json", "utf-8"));
|
|
77
|
+
const imagesDir = "./downloaded-images";
|
|
78
|
+
const images: Record<string, Uint8Array> = {};
|
|
79
|
+
for (const file of readdirSync(imagesDir)) {
|
|
80
|
+
const ref = path.basename(file).replace(/\.[^.]+$/, "");
|
|
81
|
+
images[ref] = new Uint8Array(readFileSync(path.join(imagesDir, file)));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const renderer = new FigmaRenderer(new FigmaDocument(json), { images });
|
|
85
|
+
const { data } = await renderer.render("<node-id>", { format: "png" });
|
|
86
|
+
// ...
|
|
87
|
+
renderer.dispose();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Quick start (Browser)
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { FigmaDocument, FigmaRenderer } from "@grida/refig/browser";
|
|
94
|
+
|
|
95
|
+
// Uint8Array from a File input, fetch(), or drag-and-drop
|
|
96
|
+
const figBytes: Uint8Array = await file
|
|
97
|
+
.arrayBuffer()
|
|
98
|
+
.then((b) => new Uint8Array(b));
|
|
99
|
+
|
|
100
|
+
const renderer = new FigmaRenderer(new FigmaDocument(figBytes));
|
|
101
|
+
|
|
102
|
+
const { data } = await renderer.render("<node-id>", {
|
|
103
|
+
format: "png",
|
|
104
|
+
width: 512,
|
|
105
|
+
height: 512,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// data is a Uint8Array — display it, upload it, etc.
|
|
109
|
+
const blob = new Blob([data], { type: "image/png" });
|
|
110
|
+
renderer.dispose();
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## API
|
|
114
|
+
|
|
115
|
+
### `FigmaDocument`
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
// From raw .fig bytes (Node + Browser)
|
|
119
|
+
new FigmaDocument(figBytes: Uint8Array)
|
|
120
|
+
|
|
121
|
+
// From Figma REST API JSON (Node + Browser)
|
|
122
|
+
new FigmaDocument(json: Record<string, unknown>)
|
|
123
|
+
|
|
124
|
+
// From a file path (Node only — @grida/refig)
|
|
125
|
+
FigmaDocument.fromFile("path/to/file.fig") // .fig binary
|
|
126
|
+
FigmaDocument.fromFile("path/to/doc.json") // REST API JSON
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### `FigmaRenderer`
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const renderer = new FigmaRenderer(document: FigmaDocument, options?: {
|
|
133
|
+
useEmbeddedFonts?: boolean; // default: true
|
|
134
|
+
images?: Record<string, Uint8Array>; // image ref → bytes; used for REST API IMAGE fills
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const result = await renderer.render(nodeId: string, {
|
|
138
|
+
format: "png" | "jpeg" | "webp" | "pdf" | "svg";
|
|
139
|
+
width?: number; // default: 1024
|
|
140
|
+
height?: number; // default: 1024
|
|
141
|
+
scale?: number; // default: 1
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// result.data — Uint8Array (encoded image / document bytes)
|
|
145
|
+
// result.format
|
|
146
|
+
// result.mimeType
|
|
147
|
+
// result.nodeId
|
|
148
|
+
// result.width
|
|
149
|
+
// result.height
|
|
150
|
+
|
|
151
|
+
renderer.dispose(); // release WASM resources
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### `RefigRenderResult`
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
interface RefigRenderResult {
|
|
158
|
+
data: Uint8Array;
|
|
159
|
+
format: "png" | "jpeg" | "webp" | "pdf" | "svg";
|
|
160
|
+
mimeType: string;
|
|
161
|
+
nodeId: string;
|
|
162
|
+
width: number;
|
|
163
|
+
height: number;
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## CLI
|
|
168
|
+
|
|
169
|
+
### Install
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
pnpm add -g @grida/refig
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Usage
|
|
176
|
+
|
|
177
|
+
**`<input>`** can be:
|
|
178
|
+
|
|
179
|
+
- A **file**: path to a `.fig` file or a JSON file (Figma REST API response).
|
|
180
|
+
- A **directory**: path to a folder that contains:
|
|
181
|
+
- **`document.json`** — the REST API response (required),
|
|
182
|
+
- **`images/`** — directory of image assets (optional; used for REST API IMAGE fills).
|
|
183
|
+
|
|
184
|
+
Using a directory avoids passing the document and images separately.
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
# Single node (default)
|
|
188
|
+
refig <input> --node <node-id> --out <path> [options]
|
|
189
|
+
|
|
190
|
+
# With images directory (REST JSON only; IMAGE fills rendered from local files)
|
|
191
|
+
refig <input> --images <dir> --node <node-id> --out <path>
|
|
192
|
+
|
|
193
|
+
# Directory input: document.json + images/ under one folder
|
|
194
|
+
refig ./my-figma-export --node "1:23" --out ./out.png
|
|
195
|
+
|
|
196
|
+
# Export all nodes that have exportSettings (REST JSON or .fig)
|
|
197
|
+
refig <input> --export-all --out <output-dir>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Examples
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
# Render a node from a .fig file
|
|
204
|
+
refig ./design.fig --node "1:23" --out ./out.png
|
|
205
|
+
|
|
206
|
+
# Render from REST API JSON
|
|
207
|
+
refig ./figma-response.json --node "1:23" --out ./out.svg
|
|
208
|
+
|
|
209
|
+
# Directory with document.json (and optionally images/): one path instead of response + --images
|
|
210
|
+
refig ./my-figma-export --node "1:23" --out ./out.png
|
|
211
|
+
# (my-figma-export/document.json, my-figma-export/images/)
|
|
212
|
+
|
|
213
|
+
# Explicit images directory (when not using a project directory)
|
|
214
|
+
refig ./figma-response.json --images ./downloaded-images --node "1:23" --out ./out.png
|
|
215
|
+
|
|
216
|
+
# Export all: render every node that has export settings (see below)
|
|
217
|
+
refig ./figma-response.json --export-all --out ./exports
|
|
218
|
+
refig ./design.fig --export-all --out ./exports
|
|
219
|
+
|
|
220
|
+
# Scale 2x, custom dimensions
|
|
221
|
+
refig ./design.fig --node "1:23" --out ./out.png --width 512 --height 512 --scale 2
|
|
222
|
+
|
|
223
|
+
# No-install (CI one-liner)
|
|
224
|
+
pnpm dlx @grida/refig ./design.fig --node "1:23" --out ./out.png
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Export all (`--export-all`)
|
|
228
|
+
|
|
229
|
+
With **`--export-all`**, refig walks the document and renders every node that has [Figma export settings](https://www.figma.com/developers/api#exportsetting-type) — one file per (node, setting), using that setting’s format, suffix, and constraint. Both **REST API JSON** (e.g. `GET /v1/files/:key`) and **`.fig` files** are supported when the file includes export settings.
|
|
230
|
+
|
|
231
|
+
**When it’s useful:** You choose in Figma exactly what to export: select a node, click **Export +** in the right panel, add one or more presets (e.g. PNG @2x, SVG). Add exports on as many nodes as you want. Then run the CLI with `--export-all` and the path to your REST JSON; refig renders all of those with the same config, without long or repeated `--node` / `--format` / `--scale` options. Same idea for testing the renderer: add export presets on the nodes you care about in Figma, run `refig … --export-all --out ./out`, and compare outputs.
|
|
232
|
+
|
|
233
|
+
**REST API note:** The Figma REST API (`GET /v1/files/:key`) does not include `exportSettings` for SECTION nodes, even when those sections have export presets in Figma. FRAME, COMPONENT, INSTANCE, etc. correctly include them. As a result, `--export-all` on REST JSON will not discover SECTION exports; use a `.fig` file input if you need to export nodes that are sections. See [figma/rest-api-spec#87](https://github.com/figma/rest-api-spec/issues/87).
|
|
234
|
+
|
|
235
|
+
### Flags
|
|
236
|
+
|
|
237
|
+
| Flag | Required | Default | Description |
|
|
238
|
+
| ---------------- | -------- | ------------------------------- | --------------------------------------------------------------------------------------------- |
|
|
239
|
+
| `<input>` | yes | | Path to `.fig`, JSON file, or directory containing `document.json` (and optionally `images/`) |
|
|
240
|
+
| `--images <dir>` | no | | Directory of image assets for REST document (ignored if `<input>` is a dir with `images/`) |
|
|
241
|
+
| `--node <id>` | yes\* | | Figma node ID to render (\*omit when using `--export-all`) |
|
|
242
|
+
| `--out <path>` | yes | | Output file path (single node) or output directory (`--export-all`) |
|
|
243
|
+
| `--export-all` | no | | Export every node with exportSettings (REST JSON or .fig); `--out` is a directory |
|
|
244
|
+
| `--format <fmt>` | no | inferred from `--out` extension | `png`, `jpeg`, `webp`, `pdf`, `svg` (single-node only) |
|
|
245
|
+
| `--width <px>` | no | `1024` | Viewport width (single-node only) |
|
|
246
|
+
| `--height <px>` | no | `1024` | Viewport height (single-node only) |
|
|
247
|
+
| `--scale <n>` | no | `1` | Raster scale factor (single-node only) |
|
|
248
|
+
|
|
249
|
+
## Architecture
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
Input Conversion Rendering
|
|
253
|
+
───── ────────── ─────────
|
|
254
|
+
.fig bytes ──┐
|
|
255
|
+
├──→ @grida/io-figma ──→ Grida IR ──→ @grida/canvas-wasm ──→ PNG/JPEG/WebP/PDF/SVG
|
|
256
|
+
REST JSON ───┘
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
- **`@grida/io-figma`** converts Figma data (`.fig` Kiwi binary or REST API JSON) into Grida's intermediate representation
|
|
260
|
+
- **`@grida/canvas-wasm`** renders the IR via Skia (raster backend for headless, WebGL for browser)
|
|
261
|
+
- **`@grida/refig`** ties them together behind a simple `render(nodeId, options)` call
|
|
262
|
+
|
|
263
|
+
## Images
|
|
264
|
+
|
|
265
|
+
**`.fig` input** — Image fills used in the design are stored inside the `.fig` file. No extra step is required; refig uses them when rendering.
|
|
266
|
+
|
|
267
|
+
**REST API input** — The file JSON does not contain image bytes; it references image fills by hash. To render with correct bitmaps you must supply the image assets:
|
|
268
|
+
|
|
269
|
+
1. **Fetch image fills** — Call `GET /v1/files/:key/images` (Figma REST API). This returns the list of **image fills** used in the file (i.e. which bitmap images are used as fills), not “export node as image.” The response includes a mapping of image hash → URL (signed) for each fill.
|
|
270
|
+
|
|
271
|
+
2. **Download and pass an images directory (recommended)** — Download each image from the returned URLs and save them under a directory using the `<hash>.<ext>` naming (e.g. `a1b2c3d4....png`). Pass that directory to refig as the **images directory**. We recommend this because the URLs from the API are **signed and expire**; downloading once and reusing the files avoids expiry and keeps rendering repeatable (e.g. in CI or offline).
|
|
272
|
+
|
|
273
|
+
**API** — `FigmaRenderer` accepts an optional **`images`** option: `Record<string, Uint8Array>` (image ref → bytes). Supply image assets when using REST document input; IMAGE fills will render using these bytes. Refs must match the Figma image fill hashes in the document.
|
|
274
|
+
|
|
275
|
+
**CLI** — You can pass images in two ways:
|
|
276
|
+
|
|
277
|
+
- **`--images <dir>`** — Explicit images directory. Files are keyed by filename without extension (e.g. `a1b2c3d4.png` → ref `a1b2c3d4`). Use when the document is a separate file:
|
|
278
|
+
`refig ./figma-response.json --images ./downloaded-images --node "1:23" --out ./out.png`
|
|
279
|
+
- **Directory input** — Pass a single directory that contains **`document.json`** (REST response) and optionally **`images/`**. No need to pass `--images` separately:
|
|
280
|
+
`refig ./my-figma-export --node "1:23" --out ./out.png`
|
|
281
|
+
(expects `my-figma-export/document.json` and, if present, `my-figma-export/images/`.)
|
|
282
|
+
|
|
283
|
+
For **`.fig`** input, images are embedded in the file; no extra images directory is needed. For **REST** input, use `--images` or a project directory with `images/` to render IMAGE fills correctly.
|
|
284
|
+
|
|
285
|
+
## Features
|
|
286
|
+
|
|
287
|
+
- **Multiple output formats** — `png`, `jpeg`, `webp`, `pdf`, `svg`
|
|
288
|
+
- **`.fig` file input** — render from exported `.fig` without API calls
|
|
289
|
+
- **REST API JSON input** — render from document JSON you already have
|
|
290
|
+
- **CI-friendly** — headless, deterministic, no browser required
|
|
291
|
+
- **Browser-compatible** — `@grida/refig/browser` works in any modern browser
|
|
292
|
+
- **WASM-powered** — Skia-backed rendering for pixel-accurate output
|
|
293
|
+
|
|
294
|
+
## Not planned
|
|
295
|
+
|
|
296
|
+
- **Figma API fetching / auth** — bring your own tokens and HTTP client
|
|
297
|
+
- **Design-to-code** — this renders pixels, not HTML/CSS/Flutter
|
|
298
|
+
- **Authoring / editing** — read + render only
|
|
299
|
+
|
|
300
|
+
## FAQ
|
|
301
|
+
|
|
302
|
+
### Why not just use the Figma Images API?
|
|
303
|
+
|
|
304
|
+
If you have API access, the Images API is usually simplest. This package is for when you need:
|
|
305
|
+
|
|
306
|
+
- Offline / air-gapped rendering
|
|
307
|
+
- Deterministic output in CI without network calls
|
|
308
|
+
- Custom viewport sizes or scale factors
|
|
309
|
+
- Rendering from `.fig` files without API access
|
|
310
|
+
- High-throughput or random access where the API is too slow or rate-limited (e.g. low Figma tier)
|
|
311
|
+
- Avoiding Figma access token lifecycle (refresh, storage, rotation)
|
|
312
|
+
|
|
313
|
+
### Does this work in the browser?
|
|
314
|
+
|
|
315
|
+
Yes. Import from `@grida/refig/browser`. The core renderer uses `@grida/canvas-wasm` which supports both Node (raster) and browser (WebGL) backends.
|
|
316
|
+
|
|
317
|
+
### What about fonts?
|
|
318
|
+
|
|
319
|
+
The WASM runtime ships with embedded fallback fonts. Custom font loading (Google Fonts, local directories) is planned but not yet available.
|
|
320
|
+
|
|
321
|
+
## Contributing
|
|
322
|
+
|
|
323
|
+
From the package root:
|
|
324
|
+
|
|
325
|
+
1. Install dependencies and build: `pnpm install && pnpm build`
|
|
326
|
+
2. Link the package so the `refig` CLI is available: `pnpm link --global`
|
|
327
|
+
3. Run the `refig` command from anywhere to test (e.g. `refig ./fixture.json --node "1:1" --out ./out.png`)
|
|
328
|
+
|
|
329
|
+
To unlink: `pnpm unlink --global`.
|
|
330
|
+
|
|
331
|
+
## License
|
|
332
|
+
|
|
333
|
+
See [`LICENSE`](./LICENSE).
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { ExportSetting } from '@figma/rest-api-spec';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @grida/refig — shared core (no node:fs, no DOM)
|
|
5
|
+
*
|
|
6
|
+
* This module is environment-agnostic. Both the Node and browser entrypoints
|
|
7
|
+
* re-export everything from here.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
type RefigRenderFormat = "png" | "jpeg" | "webp" | "pdf" | "svg";
|
|
11
|
+
interface RefigRendererOptions {
|
|
12
|
+
/**
|
|
13
|
+
* When enabled, the renderer loads the embedded default fonts.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
useEmbeddedFonts?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Map of Figma image ref (hash) to image bytes.
|
|
19
|
+
* Used for REST API and .fig input so IMAGE fills render correctly.
|
|
20
|
+
* Ref must match document references (e.g. 40-char hex for .fig, Figma image fill hash for REST).
|
|
21
|
+
*/
|
|
22
|
+
images?: Record<string, Uint8Array>;
|
|
23
|
+
}
|
|
24
|
+
interface RefigRenderOptions {
|
|
25
|
+
format: RefigRenderFormat;
|
|
26
|
+
width?: number;
|
|
27
|
+
height?: number;
|
|
28
|
+
scale?: number;
|
|
29
|
+
}
|
|
30
|
+
interface RefigRenderResult {
|
|
31
|
+
data: Uint8Array;
|
|
32
|
+
format: RefigRenderFormat;
|
|
33
|
+
mimeType: string;
|
|
34
|
+
nodeId: string;
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
}
|
|
38
|
+
type FigmaJsonDocument = Record<string, unknown>;
|
|
39
|
+
declare class FigmaDocument {
|
|
40
|
+
readonly sourceType: "fig-file" | "rest-api-json";
|
|
41
|
+
/**
|
|
42
|
+
* For "fig-file" this is the raw bytes of the .fig file.
|
|
43
|
+
* For "rest-api-json" this is the parsed REST API document JSON.
|
|
44
|
+
*/
|
|
45
|
+
readonly payload: Uint8Array | FigmaJsonDocument;
|
|
46
|
+
/**
|
|
47
|
+
* @param input Raw `.fig` bytes (Uint8Array) or a parsed Figma REST API
|
|
48
|
+
* document JSON object.
|
|
49
|
+
*
|
|
50
|
+
* For file-path convenience in Node, use `FigmaDocument.fromFile()` from
|
|
51
|
+
* the `@grida/refig` entrypoint.
|
|
52
|
+
*/
|
|
53
|
+
constructor(input: Uint8Array | FigmaJsonDocument);
|
|
54
|
+
}
|
|
55
|
+
declare function resolveMimeType(format: RefigRenderFormat): string;
|
|
56
|
+
type RestNode = Record<string, unknown> & {
|
|
57
|
+
id?: string;
|
|
58
|
+
children?: RestNode[];
|
|
59
|
+
};
|
|
60
|
+
/** One export to perform: a node and one of its Figma export settings. */
|
|
61
|
+
interface ExportItem {
|
|
62
|
+
nodeId: string;
|
|
63
|
+
node: RestNode;
|
|
64
|
+
setting: ExportSetting;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Walk the REST document and collect every (node, exportSetting) for nodes that have exportSettings.
|
|
68
|
+
* Follows Figma HasExportSettingsTrait; one ExportItem per setting per node.
|
|
69
|
+
*/
|
|
70
|
+
declare function collectExportsFromDocument(json: FigmaJsonDocument): ExportItem[];
|
|
71
|
+
/**
|
|
72
|
+
* Map a Figma ExportSetting and node bounds to RefigRenderOptions.
|
|
73
|
+
* Constraint SCALE → scale; WIDTH/HEIGHT → width/height from constraint value and node aspect ratio.
|
|
74
|
+
*/
|
|
75
|
+
declare function exportSettingToRenderOptions(node: RestNode, setting: ExportSetting): RefigRenderOptions;
|
|
76
|
+
declare class FigmaRenderer {
|
|
77
|
+
readonly document: FigmaDocument;
|
|
78
|
+
readonly options: RefigRendererOptions;
|
|
79
|
+
private _canvas;
|
|
80
|
+
private _sceneLoaded;
|
|
81
|
+
/** When set, scene is built with this node as root (REST only). Cleared when nodeId changes. */
|
|
82
|
+
private _requestedNodeId;
|
|
83
|
+
constructor(document: FigmaDocument | FigmaJsonDocument, options?: RefigRendererOptions);
|
|
84
|
+
private ensureCanvas;
|
|
85
|
+
private loadScene;
|
|
86
|
+
render(nodeId: string, renderOptions: RefigRenderOptions): Promise<RefigRenderResult>;
|
|
87
|
+
/**
|
|
88
|
+
* Release the underlying WASM canvas.
|
|
89
|
+
* After calling this the renderer must not be used again.
|
|
90
|
+
*/
|
|
91
|
+
dispose(): void;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { type ExportItem, FigmaDocument, FigmaRenderer, type RefigRenderFormat, type RefigRenderOptions, type RefigRenderResult, type RefigRendererOptions, collectExportsFromDocument, FigmaRenderer as default, exportSettingToRenderOptions, resolveMimeType };
|
package/dist/browser.mjs
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FigmaDocument,
|
|
3
|
+
FigmaRenderer,
|
|
4
|
+
collectExportsFromDocument,
|
|
5
|
+
exportSettingToRenderOptions,
|
|
6
|
+
resolveMimeType
|
|
7
|
+
} from "./chunk-DAHUXARL.mjs";
|
|
8
|
+
export {
|
|
9
|
+
FigmaDocument,
|
|
10
|
+
FigmaRenderer,
|
|
11
|
+
collectExportsFromDocument,
|
|
12
|
+
FigmaRenderer as default,
|
|
13
|
+
exportSettingToRenderOptions,
|
|
14
|
+
resolveMimeType
|
|
15
|
+
};
|