@grida/refig 0.0.2 → 0.0.3

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.
Files changed (3) hide show
  1. package/README.md +41 -34
  2. package/dist/cli.mjs +40 -18
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -194,8 +194,9 @@ pnpm add -g @grida/refig
194
194
  Or run without installing:
195
195
 
196
196
  ```sh
197
- npx @grida/refig <input> --node <node-id> --out <path>
198
- pnpm dlx @grida/refig <input> --node <node-id> --out <path>
197
+ # Instant usage (writes to OS temp dir; output path printed)
198
+ npx @grida/refig <input> --node <node-id> --format png
199
+ pnpm dlx @grida/refig <input> --export-all
199
200
  ```
200
201
 
201
202
  ### Usage
@@ -211,44 +212,50 @@ Using a directory avoids passing the document and images separately.
211
212
 
212
213
  ```sh
213
214
  # Single node (default)
214
- refig <input> --node <node-id> --out <path> [options]
215
+ # - Without --out: writes to OS temp dir (requires --format)
216
+ # - With --out: format inferred from file extension unless --format is provided
217
+ refig <input> --node <node-id> --format <fmt> [options]
218
+ refig <input> --node <node-id> --out <path> [--format <fmt>] [options]
215
219
 
216
220
  # With images directory (REST JSON only; IMAGE fills rendered from local files)
217
- refig <input> --images <dir> --node <node-id> --out <path>
221
+ refig <input> --images <dir> --node <node-id> --format <fmt> [options]
222
+ refig <input> --images <dir> --node <node-id> --out <path> [--format <fmt>] [options]
218
223
 
219
224
  # Directory input: document.json + images/ under one folder
220
- refig ./my-figma-export --node "1:23" --out ./out.png
225
+ refig ./my-figma-export --node "1:23" --format png
221
226
 
222
227
  # Export all nodes that have exportSettings (REST JSON or .fig)
223
- refig <input> --export-all --out <output-dir>
228
+ refig <input> --export-all [--out <output-dir>]
224
229
  ```
225
230
 
226
231
  ### Examples
227
232
 
228
233
  ```sh
229
- # Render a node from a .fig file
230
- refig ./design.fig --node "1:23" --out ./out.png
231
-
232
- # Render from REST API JSON
233
- refig ./figma-response.json --node "1:23" --out ./out.svg
234
+ # Instant usage: omit --out to write to OS temp directory (output path printed)
235
+ refig ./design.fig --node "1:23" --format png
236
+ refig ./figma-response.json --node "1:23" --format svg
234
237
 
235
238
  # Directory with document.json (and optionally images/): one path instead of response + --images
236
- refig ./my-figma-export --node "1:23" --out ./out.png
239
+ refig ./my-figma-export --node "1:23" --format png
237
240
  # (my-figma-export/document.json, my-figma-export/images/)
238
241
 
239
242
  # Explicit images directory (when not using a project directory)
240
- refig ./figma-response.json --images ./downloaded-images --node "1:23" --out ./out.png
243
+ refig ./figma-response.json --images ./downloaded-images --node "1:23" --format png
241
244
 
242
245
  # Export all: render every node that has export settings (see below)
243
- refig ./figma-response.json --export-all --out ./exports
244
- refig ./design.fig --export-all --out ./exports
246
+ refig ./figma-response.json --export-all
247
+ refig ./design.fig --export-all
245
248
 
246
249
  # Scale 2x, custom dimensions
247
- refig ./design.fig --node "1:23" --out ./out.png --width 512 --height 512 --scale 2
250
+ refig ./design.fig --node "1:23" --format png --width 512 --height 512 --scale 2
251
+
252
+ # Deterministic output: provide --out (useful for CI or saving into a known path)
253
+ refig ./design.fig --node "1:23" --out ./out.png
254
+ refig ./figma-response.json --export-all --out ./exports
248
255
 
249
256
  # No-install (run without installing)
250
- npx @grida/refig ./design.fig --node "1:23" --out ./out.png
251
- pnpm dlx @grida/refig ./design.fig --node "1:23" --out ./out.png
257
+ npx @grida/refig ./design.fig --node "1:23" --format png
258
+ pnpm dlx @grida/refig ./design.fig --export-all
252
259
  ```
253
260
 
254
261
  ### Quick test via `figma_archive.py` (REST API → `document.json` + `images/`)
@@ -275,10 +282,10 @@ This writes:
275
282
 
276
283
  ```sh
277
284
  # Single node
278
- refig ./my-figma-export --node "1:23" --out ./out.png
285
+ refig ./my-figma-export --node "1:23" --format png
279
286
 
280
287
  # Or export everything with Figma export presets
281
- refig ./my-figma-export --export-all --out ./exports
288
+ refig ./my-figma-export --export-all
282
289
  ```
283
290
 
284
291
  ### Export all (`--export-all`)
@@ -291,17 +298,17 @@ With **`--export-all`**, refig walks the document and renders every node that ha
291
298
 
292
299
  ### Flags
293
300
 
294
- | Flag | Required | Default | Description |
295
- | ---------------- | -------- | ------------------------------- | --------------------------------------------------------------------------------------------- |
296
- | `<input>` | yes | | Path to `.fig`, JSON file, or directory containing `document.json` (and optionally `images/`) |
297
- | `--images <dir>` | no | | Directory of image assets for REST document (ignored if `<input>` is a dir with `images/`) |
298
- | `--node <id>` | yes\* | | Figma node ID to render (\*omit when using `--export-all`) |
299
- | `--out <path>` | yes | | Output file path (single node) or output directory (`--export-all`) |
300
- | `--export-all` | no | | Export every node with exportSettings (REST JSON or .fig); `--out` is a directory |
301
- | `--format <fmt>` | no | inferred from `--out` extension | `png`, `jpeg`, `webp`, `pdf`, `svg` (single-node only) |
302
- | `--width <px>` | no | `1024` | Viewport width (single-node only) |
303
- | `--height <px>` | no | `1024` | Viewport height (single-node only) |
304
- | `--scale <n>` | no | `1` | Raster scale factor (single-node only) |
301
+ | Flag | Required | Default | Description |
302
+ | ---------------- | -------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
303
+ | `<input>` | yes | | Path to `.fig`, JSON file, or directory containing `document.json` (and optionally `images/`) |
304
+ | `--images <dir>` | no | | Directory of image assets for REST document (ignored if `<input>` is a dir with `images/`) |
305
+ | `--node <id>` | yes\* | | Figma node ID to render (\*omit when using `--export-all`) |
306
+ | `--out <path>` | no | OS temp dir when omitted | Output file path (single node) or output directory (`--export-all`). When omitted, writes to the OS temp directory (valid with `--export-all` or with both `--format` and `--node`). |
307
+ | `--export-all` | no | | Export every node with exportSettings (REST JSON or .fig); `--out` is a directory |
308
+ | `--format <fmt>` | no | inferred from `--out` extension | `png`, `jpeg`, `webp`, `pdf`, `svg` (single-node only; required when `--out` is omitted) |
309
+ | `--width <px>` | no | `1024` | Viewport width (single-node only) |
310
+ | `--height <px>` | no | `1024` | Viewport height (single-node only) |
311
+ | `--scale <n>` | no | `1` | Raster scale factor (single-node only) |
305
312
 
306
313
  ## Architecture
307
314
 
@@ -332,9 +339,9 @@ REST JSON ───┘
332
339
  **CLI** — You can pass images in two ways:
333
340
 
334
341
  - **`--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:
335
- `refig ./figma-response.json --images ./downloaded-images --node "1:23" --out ./out.png`
342
+ `refig ./figma-response.json --images ./downloaded-images --node "1:23" --format png`
336
343
  - **Directory input** — Pass a single directory that contains **`document.json`** (REST response) and optionally **`images/`**. No need to pass `--images` separately:
337
- `refig ./my-figma-export --node "1:23" --out ./out.png`
344
+ `refig ./my-figma-export --node "1:23" --format png`
338
345
  (expects `my-figma-export/document.json` and, if present, `my-figma-export/images/`.)
339
346
 
340
347
  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.
@@ -372,7 +379,7 @@ From the package root:
372
379
 
373
380
  1. Install dependencies and build: `pnpm install && pnpm build`
374
381
  2. Link the package so the `refig` CLI is available: `pnpm link --global`
375
- 3. Run the `refig` command from anywhere to test (e.g. `refig ./fixture.json --node "1:1" --out ./out.png`)
382
+ 3. Run the `refig` command from anywhere to test (e.g. `refig ./fixture.json --node "1:1" --format png`)
376
383
 
377
384
  To unlink: `pnpm unlink --global`.
378
385
 
package/dist/cli.mjs CHANGED
@@ -15,9 +15,11 @@ import {
15
15
  mkdirSync,
16
16
  writeFileSync,
17
17
  existsSync,
18
- statSync
18
+ statSync,
19
+ mkdtempSync
19
20
  } from "fs";
20
21
  import path from "path";
22
+ import { tmpdir } from "os";
21
23
  import { program } from "commander";
22
24
  var FORMAT_SET = /* @__PURE__ */ new Set(["png", "jpeg", "webp", "pdf", "svg"]);
23
25
  var DOCUMENT_JSON = "document.json";
@@ -175,9 +177,9 @@ async function main() {
175
177
  ).argument(
176
178
  "<input>",
177
179
  "Path to .fig, JSON file (REST API response), or directory containing document.json (and optionally images/)"
178
- ).requiredOption(
180
+ ).option(
179
181
  "--out <path>",
180
- "Output file path (single node) or output directory (--export-all)"
182
+ "Output file path (single node) or output directory (--export-all); when omitted, uses OS temp directory (valid with --export-all or with both --format and --node)"
181
183
  ).option(
182
184
  "--images <dir>",
183
185
  "Directory of image files for REST API document (optional; not used if <input> is a dir with images/)"
@@ -199,9 +201,6 @@ async function main() {
199
201
  const exportAll = options.exportAll === true;
200
202
  const nodeId = String(options.node ?? "").trim();
201
203
  const explicitImagesDir = typeof options.images === "string" ? options.images : void 0;
202
- if (!outPath) {
203
- program.error("--out is required");
204
- }
205
204
  const { documentPath, imagesDir, isRestJson } = resolveInput(
206
205
  input.trim(),
207
206
  explicitImagesDir
@@ -210,17 +209,20 @@ async function main() {
210
209
  if (nodeId) {
211
210
  program.error("--node must not be used with --export-all");
212
211
  }
213
- const outDir = path.resolve(outPath);
214
- if (existsSync(outDir)) {
215
- const stat = statSync(outDir);
216
- if (!stat.isDirectory()) {
217
- program.error(
218
- "--out must be a directory when using --export-all"
219
- );
212
+ const outDir = outPath ? (() => {
213
+ const resolved = path.resolve(outPath);
214
+ if (existsSync(resolved)) {
215
+ const stat = statSync(resolved);
216
+ if (!stat.isDirectory()) {
217
+ program.error(
218
+ "--out must be a directory when using --export-all"
219
+ );
220
+ }
221
+ } else {
222
+ mkdirSync(resolved, { recursive: true });
220
223
  }
221
- } else {
222
- mkdirSync(outDir, { recursive: true });
223
- }
224
+ return resolved;
225
+ })() : mkdtempSync(path.join(tmpdir(), "refig-export-"));
224
226
  await runExportAll(
225
227
  documentPath,
226
228
  outDir,
@@ -235,8 +237,28 @@ async function main() {
235
237
  const width = Number(options.width ?? 1024);
236
238
  const height = Number(options.height ?? 1024);
237
239
  const scale = Number(options.scale ?? 1);
238
- await runSingleNode(documentPath, nodeId, path.resolve(outPath), {
239
- format: typeof options.format === "string" ? options.format : void 0,
240
+ const formatOption = typeof options.format === "string" ? options.format : void 0;
241
+ let singleOutPath;
242
+ if (outPath) {
243
+ singleOutPath = path.resolve(outPath);
244
+ } else {
245
+ if (!formatOption) {
246
+ program.error(
247
+ "When --out is omitted, both --node and --format are required"
248
+ );
249
+ }
250
+ const format = formatOption.toLowerCase();
251
+ if (!FORMAT_SET.has(format)) {
252
+ program.error(`Unsupported --format "${format}"`);
253
+ }
254
+ const ext = EXT_BY_FORMAT[format] ?? "png";
255
+ singleOutPath = path.join(
256
+ tmpdir(),
257
+ `refig-${sanitizeForFilename(nodeId)}.${ext}`
258
+ );
259
+ }
260
+ await runSingleNode(documentPath, nodeId, singleOutPath, {
261
+ format: formatOption,
240
262
  width,
241
263
  height,
242
264
  scale,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grida/refig",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "private": false,
5
5
  "description": "Headless Figma renderer — render .fig and REST API JSON to PNG/JPEG/WebP/PDF/SVG",
6
6
  "keywords": [