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 +3 -1
- package/bin/cli.mjs +2 -2
- package/bin/commands/clone-slide.mjs +5 -5
- package/bin/commands/export.mjs +3 -3
- package/bin/commands/insert-image.mjs +4 -4
- package/bin/commands/inspect.mjs +2 -2
- package/bin/commands/list-overrides.mjs +2 -2
- package/bin/commands/list-text.mjs +3 -3
- package/bin/commands/remove-slide.mjs +2 -2
- package/bin/commands/roundtrip.mjs +1 -1
- package/bin/commands/update-text.mjs +2 -2
- package/lib/core/fig-deck.mjs +19 -18
- package/manifest.json +1 -1
- package/package.json +3 -3
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
|
|
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
|
|
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 '
|
|
9
|
-
import { nid, parseId, positionChar } from '
|
|
10
|
-
import { imageOv } from '
|
|
11
|
-
import { deepClone } from '
|
|
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 '
|
|
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');
|
package/bin/commands/export.mjs
CHANGED
|
@@ -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 '
|
|
20
|
-
import { renderDeck, registerFontDir } from '
|
|
21
|
-
import { resolveFonts } from '
|
|
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 '
|
|
7
|
-
import { nid, parseId } from '
|
|
8
|
-
import { imageOv } from '
|
|
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 '
|
|
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');
|
package/bin/commands/inspect.mjs
CHANGED
|
@@ -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 '
|
|
7
|
-
import { nid } from '
|
|
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 '
|
|
7
|
-
import { nid } from '
|
|
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 '
|
|
7
|
-
import { nid } from '
|
|
8
|
-
import { hashToHex } from '
|
|
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 '
|
|
7
|
-
import { nid, removeNode } from '
|
|
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,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 '
|
|
7
|
-
import { nid, parseId } from '
|
|
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];
|
package/lib/core/fig-deck.mjs
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
4
|
-
"description": "OpenFig — Open-source tools for parsing and rendering
|
|
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": {
|