openfig-cli 0.3.11 → 0.3.13

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/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  <img src="assets/logo.webp" alt="OpenFig" width="320" />
2
2
 
3
+ <a href="https://www.buymeacoffee.com/coenenrob9"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="40" /></a>
4
+
3
5
  Open tools for Figma files.
4
6
 
5
7
  Parse, inspect, and render `.deck` and `.fig` files without the Figma application — including PNG export.
@@ -46,7 +48,7 @@ Plug in Claude Cowork or any coding agent and you have an AI that can read and e
46
48
  ## Install
47
49
 
48
50
  ```bash
49
- npm install -g openfig
51
+ npm install -g openfig-cli
50
52
  ```
51
53
 
52
54
  Node 18+. No build step. Pure ESM.
package/bin/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * OpenFig — Open-source tools for Figma .deck / .fig files.
3
+ * OpenFig — Open-source tools for Figma file parsing and rendering.
4
4
  *
5
5
  * Usage: openfig <command> [args...]
6
6
  *
@@ -36,7 +36,7 @@ const arg2 = process.argv[2];
36
36
  let command, rawArgs;
37
37
 
38
38
  if (!arg2 || arg2 === '--help' || arg2 === '-h') {
39
- console.log(`OpenFig — Open-source tools for Figma .deck / .fig files\n`);
39
+ console.log(`OpenFig — Open-source tools for Figma file parsing and rendering\n`);
40
40
  console.log('Usage: openfig <command> [args...]\n');
41
41
  console.log('Commands:');
42
42
  console.log(' export Export slides as images (PNG/JPG/WEBP)');
@@ -5,14 +5,14 @@
5
5
  * --template <slideId|name> --name <newName>
6
6
  * [--after <slideId>] [--set key=value ...] [--set-image key=path ...]
7
7
  */
8
- import { FigDeck } from '../lib/core/fig-deck.mjs';
9
- import { nid, parseId, positionChar } from '../lib/core/node-helpers.mjs';
10
- import { imageOv } from '../lib/core/image-helpers.mjs';
11
- import { deepClone } from '../lib/core/deep-clone.mjs';
8
+ import { FigDeck } from '../../lib/core/fig-deck.mjs';
9
+ import { nid, parseId, positionChar } from '../../lib/core/node-helpers.mjs';
10
+ import { imageOv } from '../../lib/core/image-helpers.mjs';
11
+ import { deepClone } from '../../lib/core/deep-clone.mjs';
12
12
  import { readFileSync, copyFileSync, existsSync, mkdirSync } from 'fs';
13
13
  import { createHash } from 'crypto';
14
14
  import { join, resolve } from 'path';
15
- import { getImageDimensions, generateThumbnail } from '../lib/core/image-utils.mjs';
15
+ import { getImageDimensions, generateThumbnail } from '../../lib/core/image-utils.mjs';
16
16
 
17
17
  function sha1Hex(buf) {
18
18
  return createHash('sha1').update(buf).digest('hex');
@@ -16,9 +16,9 @@
16
16
  import { existsSync, mkdirSync, rmSync, writeFileSync } from 'fs';
17
17
  import { join, parse, resolve } from 'path';
18
18
  import { createInterface } from 'readline';
19
- import { FigDeck } from '../lib/core/fig-deck.mjs';
20
- import { renderDeck, registerFontDir } from '../lib/rasterizer/deck-rasterizer.mjs';
21
- import { resolveFonts } from '../lib/rasterizer/font-resolver.mjs';
19
+ import { FigDeck } from '../../lib/core/fig-deck.mjs';
20
+ import { renderDeck, registerFontDir } from '../../lib/rasterizer/deck-rasterizer.mjs';
21
+ import { resolveFonts } from '../../lib/rasterizer/font-resolver.mjs';
22
22
 
23
23
  async function confirmOverwrite(dir) {
24
24
  const rl = createInterface({ input: process.stdin, output: process.stdout });
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * Usage: node cli.mjs insert-image <file.deck> -o <output.deck> --slide <id|name> --key <overrideKey> --image <path.png> [--thumb <thumb.png>]
5
5
  */
6
- import { FigDeck } from '../lib/core/fig-deck.mjs';
7
- import { nid, parseId } from '../lib/core/node-helpers.mjs';
8
- import { imageOv } from '../lib/core/image-helpers.mjs';
6
+ import { FigDeck } from '../../lib/core/fig-deck.mjs';
7
+ import { nid, parseId } from '../../lib/core/node-helpers.mjs';
8
+ import { imageOv } from '../../lib/core/image-helpers.mjs';
9
9
  import { readFileSync, copyFileSync, existsSync, mkdirSync } from 'fs';
10
10
  import { createHash } from 'crypto';
11
11
  import { join, resolve } from 'path';
12
- import { getImageDimensions, generateThumbnail } from '../lib/core/image-utils.mjs';
12
+ import { getImageDimensions, generateThumbnail } from '../../lib/core/image-utils.mjs';
13
13
 
14
14
  function sha1Hex(buf) {
15
15
  return createHash('sha1').update(buf).digest('hex');
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Usage: node cli.mjs inspect <file.deck|file.fig> [--depth N] [--type TYPE] [--json]
5
5
  */
6
- import { FigDeck } from '../lib/core/fig-deck.mjs';
7
- import { nid } from '../lib/core/node-helpers.mjs';
6
+ import { FigDeck } from '../../lib/core/fig-deck.mjs';
7
+ import { nid } from '../../lib/core/node-helpers.mjs';
8
8
 
9
9
  export async function run(args, flags) {
10
10
  const file = args[0];
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Usage: node cli.mjs list-overrides <file.deck> [--symbol NAME|ID]
5
5
  */
6
- import { FigDeck } from '../lib/core/fig-deck.mjs';
7
- import { nid } from '../lib/core/node-helpers.mjs';
6
+ import { FigDeck } from '../../lib/core/fig-deck.mjs';
7
+ import { nid } from '../../lib/core/node-helpers.mjs';
8
8
 
9
9
  export async function run(args, flags) {
10
10
  const file = args[0];
@@ -3,9 +3,9 @@
3
3
  *
4
4
  * Usage: node cli.mjs list-text <file.deck>
5
5
  */
6
- import { FigDeck } from '../lib/core/fig-deck.mjs';
7
- import { nid } from '../lib/core/node-helpers.mjs';
8
- import { hashToHex } from '../lib/core/image-helpers.mjs';
6
+ import { FigDeck } from '../../lib/core/fig-deck.mjs';
7
+ import { nid } from '../../lib/core/node-helpers.mjs';
8
+ import { hashToHex } from '../../lib/core/image-helpers.mjs';
9
9
 
10
10
  export async function run(args) {
11
11
  const file = args[0];
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Usage: node cli.mjs remove-slide <file.deck> -o <output.deck> --slide <id|name> [--slide ...]
5
5
  */
6
- import { FigDeck } from '../lib/core/fig-deck.mjs';
7
- import { nid, removeNode } from '../lib/core/node-helpers.mjs';
6
+ import { FigDeck } from '../../lib/core/fig-deck.mjs';
7
+ import { nid, removeNode } from '../../lib/core/node-helpers.mjs';
8
8
 
9
9
  export async function run(args, flags) {
10
10
  const file = args[0];
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Usage: node cli.mjs roundtrip <file.deck> -o <output.deck>
5
5
  */
6
- import { FigDeck } from '../lib/core/fig-deck.mjs';
6
+ import { FigDeck } from '../../lib/core/fig-deck.mjs';
7
7
 
8
8
  export async function run(args, flags) {
9
9
  const file = args[0];
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Usage: node cli.mjs update-text <file.deck> -o <output.deck> --slide <id|name> --set key=value [--set key=value ...]
5
5
  */
6
- import { FigDeck } from '../lib/core/fig-deck.mjs';
7
- import { nid, parseId } from '../lib/core/node-helpers.mjs';
6
+ import { FigDeck } from '../../lib/core/fig-deck.mjs';
7
+ import { nid, parseId } from '../../lib/core/node-helpers.mjs';
8
8
 
9
9
  export async function run(args, flags) {
10
10
  const file = args[0];
@@ -13,8 +13,8 @@ import { decodeBinarySchema, compileSchema, encodeBinarySchema } from 'kiwi-sche
13
13
  import { decompress } from 'fzstd';
14
14
  import { inflateRaw, deflateRaw } from 'pako';
15
15
  import { ZstdCodec } from 'zstd-codec';
16
- import archiver from 'archiver';
17
- import { readFileSync, createWriteStream, existsSync, mkdtempSync } from 'fs';
16
+ import yazl from 'yazl';
17
+ import { readFileSync, createWriteStream, existsSync, mkdtempSync, readdirSync } from 'fs';
18
18
  import { execSync } from 'child_process';
19
19
  import { join, resolve } from 'path';
20
20
  import { tmpdir } from 'os';
@@ -288,36 +288,37 @@ export class FigDeck {
288
288
  const absOut = resolve(outPath);
289
289
 
290
290
  return new Promise((resolveP, reject) => {
291
- const output = createWriteStream(absOut);
292
- const archive = archiver('zip', { store: true });
293
-
294
- archive.on('error', reject);
295
- output.on('close', () => resolveP(archive.pointer()));
296
-
297
- archive.pipe(output);
291
+ const zipfile = new yazl.ZipFile();
298
292
 
299
293
  // canvas.fig
300
- archive.append(Buffer.from(figBuf), { name: 'canvas.fig' });
294
+ const figBytes = Buffer.from(figBuf);
295
+ zipfile.addBuffer(figBytes, 'canvas.fig');
301
296
 
302
297
  // thumbnail.png
303
298
  const thumb = opts.thumbnail || this.deckThumbnail;
304
- if (thumb) {
305
- archive.append(Buffer.from(thumb), { name: 'thumbnail.png' });
306
- }
299
+ if (thumb) zipfile.addBuffer(Buffer.from(thumb), 'thumbnail.png');
307
300
 
308
301
  // meta.json
309
302
  const meta = opts.meta || this.deckMeta;
310
- if (meta) {
311
- archive.append(JSON.stringify(meta), { name: 'meta.json' });
312
- }
303
+ if (meta) zipfile.addBuffer(Buffer.from(JSON.stringify(meta)), 'meta.json');
313
304
 
314
305
  // images/
315
306
  const imgDir = opts.imagesDir || this.imagesDir;
316
307
  if (imgDir && existsSync(imgDir)) {
317
- archive.directory(imgDir, 'images');
308
+ for (const entry of readdirSync(imgDir, { withFileTypes: true, recursive: true })) {
309
+ if (entry.isFile()) {
310
+ const fullPath = join(entry.parentPath ?? entry.path, entry.name);
311
+ const rel = fullPath.slice(imgDir.length + 1).replace(/\\/g, '/');
312
+ zipfile.addBuffer(readFileSync(fullPath), `images/${rel}`);
313
+ }
314
+ }
318
315
  }
319
316
 
320
- archive.finalize();
317
+ zipfile.end();
318
+ const output = createWriteStream(absOut);
319
+ output.on('close', resolveP);
320
+ output.on('error', reject);
321
+ zipfile.outputStream.pipe(output);
321
322
  });
322
323
  }
323
324
 
package/manifest.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "manifest_version": "0.2",
3
3
  "name": "openfig",
4
4
  "version": "0.3.11",
5
- "description": "Open-source tools for parsing and rendering Figma design files",
5
+ "description": "Open-source tools for Figma file parsing and rendering",
6
6
  "author": {
7
7
  "name": "OpenFig Contributors"
8
8
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "openfig-cli",
3
- "version": "0.3.11",
4
- "description": "OpenFig — Open-source tools for parsing and rendering Figma design files",
3
+ "version": "0.3.13",
4
+ "description": "OpenFig — Open-source tools for Figma file parsing and rendering",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "openfig": "bin/cli.mjs",
@@ -45,12 +45,12 @@
45
45
  "dependencies": {
46
46
  "@modelcontextprotocol/sdk": "^1.27.1",
47
47
  "@resvg/resvg-wasm": "^2.6.2",
48
- "archiver": "^7.0.1",
49
48
  "fzstd": "^0.1.1",
50
49
  "kiwi-schema": "^0.5.0",
51
50
  "pako": "^2.1.0",
52
51
  "sharp": "^0.34.5",
53
52
  "ssim.js": "^3.5.0",
53
+ "yazl": "^3.3.1",
54
54
  "zstd-codec": "^0.1.5"
55
55
  },
56
56
  "devDependencies": {