@dannote/figma-use 0.1.0 → 0.1.1
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 +50 -8
- package/bin/figma-use.js +3 -14
- package/dist/cli/index.js +266 -6
- package/package.json +1 -1
- package/packages/plugin/dist/main.js +11 -0
package/README.md
CHANGED
|
@@ -4,6 +4,20 @@ Control Figma from the command line. Like [browser-use](https://github.com/brows
|
|
|
4
4
|
|
|
5
5
|
Built for AI agents to create and manipulate Figma designs programmatically.
|
|
6
6
|
|
|
7
|
+
## How it works
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
11
|
+
│ │ │ │ │ │
|
|
12
|
+
│ AI Agent / │────▶│ figma-use │────▶│ Figma │
|
|
13
|
+
│ CLI │ HTTP│ proxy │ WS │ Plugin │
|
|
14
|
+
│ │◀────│ :38451 │◀────│ │
|
|
15
|
+
│ │ │ │ │ │
|
|
16
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The CLI sends commands to a local proxy server, which forwards them via WebSocket to a Figma plugin. The plugin executes commands using the Figma API and returns results.
|
|
20
|
+
|
|
7
21
|
## Installation
|
|
8
22
|
|
|
9
23
|
```bash
|
|
@@ -18,20 +32,24 @@ bun install -g @dannote/figma-use
|
|
|
18
32
|
figma-use proxy
|
|
19
33
|
```
|
|
20
34
|
|
|
21
|
-
### 2.
|
|
35
|
+
### 2. Install the Figma plugin
|
|
22
36
|
|
|
23
|
-
|
|
37
|
+
```bash
|
|
38
|
+
# Quit Figma first, then:
|
|
39
|
+
figma-use plugin
|
|
24
40
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
```
|
|
41
|
+
# Or force install while Figma is running (restart required):
|
|
42
|
+
figma-use plugin --force
|
|
28
43
|
|
|
29
|
-
|
|
44
|
+
# Show plugin path only:
|
|
45
|
+
figma-use plugin --path
|
|
30
46
|
|
|
31
|
-
|
|
32
|
-
figma-use plugin
|
|
47
|
+
# Uninstall:
|
|
48
|
+
figma-use plugin --uninstall
|
|
33
49
|
```
|
|
34
50
|
|
|
51
|
+
Start Figma and find the plugin in **Plugins → Development → Figma Use**.
|
|
52
|
+
|
|
35
53
|
### 3. Run commands
|
|
36
54
|
|
|
37
55
|
```bash
|
|
@@ -171,6 +189,30 @@ $ figma-use get-node --id "1:2" --json
|
|
|
171
189
|
| `zoom-to-fit` | Zoom to fit nodes |
|
|
172
190
|
| `set-viewport` | Set viewport position and zoom |
|
|
173
191
|
|
|
192
|
+
### Advanced
|
|
193
|
+
|
|
194
|
+
| Command | Description |
|
|
195
|
+
|---------|-------------|
|
|
196
|
+
| `eval` | Execute arbitrary JavaScript in Figma |
|
|
197
|
+
|
|
198
|
+
#### eval
|
|
199
|
+
|
|
200
|
+
Run any JavaScript code in the Figma plugin context:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Simple expression
|
|
204
|
+
figma-use eval "return 2 + 2"
|
|
205
|
+
|
|
206
|
+
# Access Figma API
|
|
207
|
+
figma-use eval "return figma.currentPage.name"
|
|
208
|
+
|
|
209
|
+
# Create nodes
|
|
210
|
+
figma-use eval "const r = figma.createRectangle(); r.resize(100, 100); return r.id"
|
|
211
|
+
|
|
212
|
+
# Async code (top-level await supported)
|
|
213
|
+
figma-use eval "const node = await figma.getNodeByIdAsync('1:2'); return node.name"
|
|
214
|
+
```
|
|
215
|
+
|
|
174
216
|
## Environment Variables
|
|
175
217
|
|
|
176
218
|
| Variable | Default | Description |
|
package/bin/figma-use.js
CHANGED
|
@@ -4,18 +4,7 @@ import { fileURLToPath } from 'url'
|
|
|
4
4
|
import { dirname, join } from 'path'
|
|
5
5
|
|
|
6
6
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
7
|
-
const
|
|
7
|
+
const cliPath = join(__dirname, '..', 'dist', 'cli', 'index.js')
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const proxyPath = join(__dirname, '..', 'dist', 'proxy', 'index.js')
|
|
12
|
-
spawn('bun', ['run', proxyPath], { stdio: 'inherit' })
|
|
13
|
-
} else if (args[0] === 'plugin') {
|
|
14
|
-
const pluginPath = join(__dirname, '..', 'packages', 'plugin', 'dist')
|
|
15
|
-
console.log(`Plugin files at: ${pluginPath}`)
|
|
16
|
-
console.log('Import manifest.json into Figma via Plugins > Development > Import plugin from manifest')
|
|
17
|
-
} else {
|
|
18
|
-
// CLI command
|
|
19
|
-
const cliPath = join(__dirname, '..', 'dist', 'cli', 'index.js')
|
|
20
|
-
spawn('bun', ['run', cliPath, ...args], { stdio: 'inherit' })
|
|
21
|
-
}
|
|
9
|
+
const child = spawn('bun', ['run', cliPath, ...process.argv.slice(2)], { stdio: 'inherit' })
|
|
10
|
+
child.on('exit', (code) => process.exit(code || 0))
|
package/dist/cli/index.js
CHANGED
|
@@ -27,6 +27,7 @@ var __export = (target, all) => {
|
|
|
27
27
|
});
|
|
28
28
|
};
|
|
29
29
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
30
|
+
var __require = import.meta.require;
|
|
30
31
|
|
|
31
32
|
// node_modules/.bun/consola@3.4.2/node_modules/consola/dist/chunks/prompt.mjs
|
|
32
33
|
var exports_prompt = {};
|
|
@@ -2450,6 +2451,8 @@ __export(exports_commands, {
|
|
|
2450
2451
|
screenshot: () => screenshot_default,
|
|
2451
2452
|
"resize-node": () => resize_node_default,
|
|
2452
2453
|
"rename-node": () => rename_node_default,
|
|
2454
|
+
proxy: () => proxy_default,
|
|
2455
|
+
plugin: () => plugin_default,
|
|
2453
2456
|
"move-node": () => move_node_default,
|
|
2454
2457
|
"intersect-nodes": () => intersect_nodes_default,
|
|
2455
2458
|
"import-svg": () => import_svg_default,
|
|
@@ -2466,6 +2469,7 @@ __export(exports_commands, {
|
|
|
2466
2469
|
"export-selection": () => export_selection_default,
|
|
2467
2470
|
"export-node": () => export_node_default,
|
|
2468
2471
|
"exclude-nodes": () => exclude_nodes_default,
|
|
2472
|
+
eval: () => eval_default,
|
|
2469
2473
|
"edit-component-property": () => edit_component_property_default,
|
|
2470
2474
|
"delete-node": () => delete_node_default,
|
|
2471
2475
|
"delete-component-property": () => delete_component_property_default,
|
|
@@ -2489,6 +2493,249 @@ __export(exports_commands, {
|
|
|
2489
2493
|
"add-component-property": () => add_component_property_default
|
|
2490
2494
|
});
|
|
2491
2495
|
|
|
2496
|
+
// packages/cli/src/commands/proxy.ts
|
|
2497
|
+
import { spawn } from "child_process";
|
|
2498
|
+
import { resolve, dirname } from "path";
|
|
2499
|
+
function getPackageRoot() {
|
|
2500
|
+
const currentFile = import.meta.path || import.meta.url.replace("file://", "");
|
|
2501
|
+
let dir = dirname(currentFile);
|
|
2502
|
+
for (let i2 = 0;i2 < 10; i2++) {
|
|
2503
|
+
try {
|
|
2504
|
+
const pkg = __require(resolve(dir, "package.json"));
|
|
2505
|
+
if (pkg.name === "@dannote/figma-use") {
|
|
2506
|
+
return dir;
|
|
2507
|
+
}
|
|
2508
|
+
} catch {}
|
|
2509
|
+
dir = dirname(dir);
|
|
2510
|
+
}
|
|
2511
|
+
return dirname(dirname(dirname(currentFile)));
|
|
2512
|
+
}
|
|
2513
|
+
var proxy_default = defineCommand({
|
|
2514
|
+
meta: { description: "Start the WebSocket proxy server" },
|
|
2515
|
+
args: {
|
|
2516
|
+
port: { type: "string", description: "Port to listen on", default: "38451" }
|
|
2517
|
+
},
|
|
2518
|
+
run({ args }) {
|
|
2519
|
+
process.env.PORT = args.port;
|
|
2520
|
+
const root = getPackageRoot();
|
|
2521
|
+
const proxyPath = resolve(root, "dist", "proxy", "index.js");
|
|
2522
|
+
const child = spawn("bun", ["run", proxyPath], { stdio: "inherit" });
|
|
2523
|
+
child.on("exit", (code) => process.exit(code || 0));
|
|
2524
|
+
}
|
|
2525
|
+
});
|
|
2526
|
+
// packages/cli/src/commands/plugin.ts
|
|
2527
|
+
import { resolve as resolve2, dirname as dirname2, join } from "path";
|
|
2528
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
2529
|
+
import { execSync } from "child_process";
|
|
2530
|
+
function getPackageRoot2() {
|
|
2531
|
+
const currentFile = import.meta.path || import.meta.url.replace("file://", "");
|
|
2532
|
+
let dir = dirname2(currentFile);
|
|
2533
|
+
for (let i2 = 0;i2 < 10; i2++) {
|
|
2534
|
+
try {
|
|
2535
|
+
const pkg = __require(resolve2(dir, "package.json"));
|
|
2536
|
+
if (pkg.name === "@dannote/figma-use") {
|
|
2537
|
+
return dir;
|
|
2538
|
+
}
|
|
2539
|
+
} catch {}
|
|
2540
|
+
dir = dirname2(dir);
|
|
2541
|
+
}
|
|
2542
|
+
return dirname2(dirname2(dirname2(currentFile)));
|
|
2543
|
+
}
|
|
2544
|
+
function getFigmaSettingsPath() {
|
|
2545
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
2546
|
+
if (process.platform === "darwin") {
|
|
2547
|
+
return join(home, "Library", "Application Support", "Figma", "settings.json");
|
|
2548
|
+
} else if (process.platform === "win32") {
|
|
2549
|
+
const appData = process.env.APPDATA || join(home, "AppData", "Roaming");
|
|
2550
|
+
return join(appData, "Figma", "settings.json");
|
|
2551
|
+
} else {
|
|
2552
|
+
return join(home, ".config", "Figma", "settings.json");
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
function isFigmaRunning() {
|
|
2556
|
+
try {
|
|
2557
|
+
if (process.platform === "darwin") {
|
|
2558
|
+
execSync("pgrep -x Figma", { stdio: "pipe" });
|
|
2559
|
+
return true;
|
|
2560
|
+
} else if (process.platform === "win32") {
|
|
2561
|
+
execSync('tasklist /FI "IMAGENAME eq Figma.exe" | find "Figma.exe"', { stdio: "pipe" });
|
|
2562
|
+
return true;
|
|
2563
|
+
} else {
|
|
2564
|
+
execSync("pgrep -x figma", { stdio: "pipe" });
|
|
2565
|
+
return true;
|
|
2566
|
+
}
|
|
2567
|
+
} catch {
|
|
2568
|
+
return false;
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
function getNextId(extensions) {
|
|
2572
|
+
if (!extensions || extensions.length === 0)
|
|
2573
|
+
return 1;
|
|
2574
|
+
return Math.max(...extensions.map((e2) => e2.id)) + 1;
|
|
2575
|
+
}
|
|
2576
|
+
function installPlugin(manifestPath) {
|
|
2577
|
+
const settingsPath = getFigmaSettingsPath();
|
|
2578
|
+
if (!settingsPath || !existsSync(settingsPath)) {
|
|
2579
|
+
return {
|
|
2580
|
+
success: false,
|
|
2581
|
+
message: "Figma settings not found. Please install Figma Desktop first."
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
if (isFigmaRunning()) {
|
|
2585
|
+
return {
|
|
2586
|
+
success: false,
|
|
2587
|
+
message: "Figma is running. Please quit Figma first, then run this command again."
|
|
2588
|
+
};
|
|
2589
|
+
}
|
|
2590
|
+
try {
|
|
2591
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
2592
|
+
const extensions = settings.localFileExtensions || [];
|
|
2593
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
2594
|
+
const pluginId = manifest.id || "figma-use-plugin";
|
|
2595
|
+
const existing = extensions.find((e2) => e2.lastKnownPluginId === pluginId && e2.fileMetadata?.type === "manifest");
|
|
2596
|
+
if (existing) {
|
|
2597
|
+
if (existing.manifestPath !== manifestPath) {
|
|
2598
|
+
existing.manifestPath = manifestPath;
|
|
2599
|
+
const pluginDir2 = dirname2(manifestPath);
|
|
2600
|
+
for (const ext of extensions) {
|
|
2601
|
+
if (ext.fileMetadata?.manifestFileId === existing.id) {
|
|
2602
|
+
if (ext.fileMetadata.type === "code") {
|
|
2603
|
+
ext.manifestPath = join(pluginDir2, manifest.main || "main.js");
|
|
2604
|
+
} else if (ext.fileMetadata.type === "ui") {
|
|
2605
|
+
ext.manifestPath = join(pluginDir2, manifest.ui || "ui.html");
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
settings.localFileExtensions = extensions;
|
|
2610
|
+
writeFileSync(settingsPath, JSON.stringify(settings));
|
|
2611
|
+
return { success: true, message: "Plugin path updated" };
|
|
2612
|
+
}
|
|
2613
|
+
return { success: true, message: "Plugin already installed" };
|
|
2614
|
+
}
|
|
2615
|
+
const pluginDir = dirname2(manifestPath);
|
|
2616
|
+
const manifestId = getNextId(extensions);
|
|
2617
|
+
const codeId = manifestId + 1;
|
|
2618
|
+
const uiId = manifestId + 2;
|
|
2619
|
+
extensions.push({
|
|
2620
|
+
id: manifestId,
|
|
2621
|
+
manifestPath,
|
|
2622
|
+
lastKnownName: manifest.name || "Figma Use",
|
|
2623
|
+
lastKnownPluginId: pluginId,
|
|
2624
|
+
fileMetadata: {
|
|
2625
|
+
type: "manifest",
|
|
2626
|
+
codeFileId: codeId,
|
|
2627
|
+
uiFileIds: [uiId]
|
|
2628
|
+
},
|
|
2629
|
+
cachedContainsWidget: false
|
|
2630
|
+
});
|
|
2631
|
+
extensions.push({
|
|
2632
|
+
id: codeId,
|
|
2633
|
+
manifestPath: join(pluginDir, manifest.main || "main.js"),
|
|
2634
|
+
fileMetadata: {
|
|
2635
|
+
type: "code",
|
|
2636
|
+
manifestFileId: manifestId
|
|
2637
|
+
}
|
|
2638
|
+
});
|
|
2639
|
+
extensions.push({
|
|
2640
|
+
id: uiId,
|
|
2641
|
+
manifestPath: join(pluginDir, manifest.ui || "ui.html"),
|
|
2642
|
+
fileMetadata: {
|
|
2643
|
+
type: "ui",
|
|
2644
|
+
manifestFileId: manifestId
|
|
2645
|
+
}
|
|
2646
|
+
});
|
|
2647
|
+
settings.localFileExtensions = extensions;
|
|
2648
|
+
writeFileSync(settingsPath, JSON.stringify(settings));
|
|
2649
|
+
return { success: true, message: "Plugin installed successfully" };
|
|
2650
|
+
} catch (error) {
|
|
2651
|
+
return {
|
|
2652
|
+
success: false,
|
|
2653
|
+
message: `Failed to install: ${error instanceof Error ? error.message : error}`
|
|
2654
|
+
};
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
function uninstallPlugin(manifestPath) {
|
|
2658
|
+
const settingsPath = getFigmaSettingsPath();
|
|
2659
|
+
if (!settingsPath || !existsSync(settingsPath)) {
|
|
2660
|
+
return { success: false, message: "Figma settings not found" };
|
|
2661
|
+
}
|
|
2662
|
+
if (isFigmaRunning()) {
|
|
2663
|
+
return {
|
|
2664
|
+
success: false,
|
|
2665
|
+
message: "Figma is running. Please quit Figma first."
|
|
2666
|
+
};
|
|
2667
|
+
}
|
|
2668
|
+
try {
|
|
2669
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
2670
|
+
const extensions = settings.localFileExtensions || [];
|
|
2671
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
2672
|
+
const pluginId = manifest.id || "figma-use-plugin";
|
|
2673
|
+
const manifestEntry = extensions.find((e2) => e2.lastKnownPluginId === pluginId && e2.fileMetadata?.type === "manifest");
|
|
2674
|
+
if (!manifestEntry) {
|
|
2675
|
+
return { success: true, message: "Plugin not installed" };
|
|
2676
|
+
}
|
|
2677
|
+
const manifestId = manifestEntry.id;
|
|
2678
|
+
settings.localFileExtensions = extensions.filter((e2) => e2.id !== manifestId && e2.fileMetadata?.manifestFileId !== manifestId);
|
|
2679
|
+
writeFileSync(settingsPath, JSON.stringify(settings));
|
|
2680
|
+
return { success: true, message: "Plugin uninstalled successfully" };
|
|
2681
|
+
} catch (error) {
|
|
2682
|
+
return {
|
|
2683
|
+
success: false,
|
|
2684
|
+
message: `Failed to uninstall: ${error instanceof Error ? error.message : error}`
|
|
2685
|
+
};
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
var plugin_default = defineCommand({
|
|
2689
|
+
meta: { description: "Install/uninstall Figma plugin" },
|
|
2690
|
+
args: {
|
|
2691
|
+
uninstall: { type: "boolean", description: "Uninstall the plugin" },
|
|
2692
|
+
path: { type: "boolean", description: "Show plugin path only" },
|
|
2693
|
+
force: { type: "boolean", description: "Force install even if Figma is running (not recommended)" }
|
|
2694
|
+
},
|
|
2695
|
+
async run({ args }) {
|
|
2696
|
+
const root = getPackageRoot2();
|
|
2697
|
+
const pluginPath = resolve2(root, "packages", "plugin", "dist", "manifest.json");
|
|
2698
|
+
if (args.path) {
|
|
2699
|
+
console.log(pluginPath);
|
|
2700
|
+
return;
|
|
2701
|
+
}
|
|
2702
|
+
if (args.uninstall) {
|
|
2703
|
+
const result2 = uninstallPlugin(pluginPath);
|
|
2704
|
+
if (result2.success) {
|
|
2705
|
+
consola.success(result2.message);
|
|
2706
|
+
} else {
|
|
2707
|
+
consola.error(result2.message);
|
|
2708
|
+
}
|
|
2709
|
+
return;
|
|
2710
|
+
}
|
|
2711
|
+
if (!args.force && isFigmaRunning()) {
|
|
2712
|
+
consola.error("Figma is running");
|
|
2713
|
+
consola.info("Please quit Figma, then run: figma-use plugin");
|
|
2714
|
+
consola.info("Or use --force to install anyway (changes will apply on restart)");
|
|
2715
|
+
return;
|
|
2716
|
+
}
|
|
2717
|
+
const result = installPlugin(pluginPath);
|
|
2718
|
+
if (result.success) {
|
|
2719
|
+
consola.success(result.message);
|
|
2720
|
+
if (result.message !== "Plugin already installed") {
|
|
2721
|
+
consola.box(`Next steps:
|
|
2722
|
+
|
|
2723
|
+
1. Start Figma
|
|
2724
|
+
2. Open any Figma file
|
|
2725
|
+
3. Run: figma-use proxy
|
|
2726
|
+
4. In Figma: Plugins \u2192 Development \u2192 Figma Use`);
|
|
2727
|
+
}
|
|
2728
|
+
} else {
|
|
2729
|
+
consola.error(result.message);
|
|
2730
|
+
consola.box({
|
|
2731
|
+
title: "Manual Installation",
|
|
2732
|
+
message: `1. Open Figma Desktop
|
|
2733
|
+
2. Go to: Plugins \u2192 Development \u2192 Import plugin from manifest
|
|
2734
|
+
3. Select: ${pluginPath}`
|
|
2735
|
+
});
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
});
|
|
2492
2739
|
// packages/cli/src/client.ts
|
|
2493
2740
|
init_output();
|
|
2494
2741
|
var PROXY_URL = process.env.FIGMA_PROXY_URL || "http://localhost:38451";
|
|
@@ -2514,6 +2761,19 @@ function handleError(error) {
|
|
|
2514
2761
|
process.exit(1);
|
|
2515
2762
|
}
|
|
2516
2763
|
|
|
2764
|
+
// packages/cli/src/commands/eval.ts
|
|
2765
|
+
init_output();
|
|
2766
|
+
var eval_default = defineCommand({
|
|
2767
|
+
meta: { description: "Execute arbitrary code in Figma plugin context" },
|
|
2768
|
+
args: {
|
|
2769
|
+
code: { type: "positional", description: "JavaScript code to execute", required: true },
|
|
2770
|
+
json: { type: "boolean", description: "Output raw JSON" }
|
|
2771
|
+
},
|
|
2772
|
+
async run({ args }) {
|
|
2773
|
+
const result = await sendCommand("eval", { code: args.code });
|
|
2774
|
+
printResult(result, args.json);
|
|
2775
|
+
}
|
|
2776
|
+
});
|
|
2517
2777
|
// packages/cli/src/commands/status.ts
|
|
2518
2778
|
var status_default = defineCommand({
|
|
2519
2779
|
meta: { description: "Check if plugin is connected" },
|
|
@@ -3627,7 +3887,7 @@ var zoom_to_fit_default = defineCommand({
|
|
|
3627
3887
|
}
|
|
3628
3888
|
});
|
|
3629
3889
|
// packages/cli/src/commands/export-node.ts
|
|
3630
|
-
import { writeFileSync } from "fs";
|
|
3890
|
+
import { writeFileSync as writeFileSync2 } from "fs";
|
|
3631
3891
|
var export_node_default = defineCommand({
|
|
3632
3892
|
meta: { description: "Export node as image" },
|
|
3633
3893
|
args: {
|
|
@@ -3646,7 +3906,7 @@ var export_node_default = defineCommand({
|
|
|
3646
3906
|
});
|
|
3647
3907
|
if (args.output) {
|
|
3648
3908
|
const buffer = Buffer.from(result.data, "base64");
|
|
3649
|
-
|
|
3909
|
+
writeFileSync2(args.output, buffer);
|
|
3650
3910
|
console.log(`Exported to ${args.output}`);
|
|
3651
3911
|
} else {
|
|
3652
3912
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -3673,7 +3933,7 @@ var delete_node_default = defineCommand({
|
|
|
3673
3933
|
}
|
|
3674
3934
|
});
|
|
3675
3935
|
// packages/cli/src/commands/screenshot.ts
|
|
3676
|
-
import { writeFileSync as
|
|
3936
|
+
import { writeFileSync as writeFileSync3 } from "fs";
|
|
3677
3937
|
var screenshot_default = defineCommand({
|
|
3678
3938
|
meta: { description: "Take a screenshot of current viewport" },
|
|
3679
3939
|
args: {
|
|
@@ -3687,7 +3947,7 @@ var screenshot_default = defineCommand({
|
|
|
3687
3947
|
scale: Number(args.scale)
|
|
3688
3948
|
});
|
|
3689
3949
|
const buffer = Buffer.from(result.data, "base64");
|
|
3690
|
-
|
|
3950
|
+
writeFileSync3(args.output, buffer);
|
|
3691
3951
|
console.log(args.output);
|
|
3692
3952
|
} catch (e2) {
|
|
3693
3953
|
handleError(e2);
|
|
@@ -3695,7 +3955,7 @@ var screenshot_default = defineCommand({
|
|
|
3695
3955
|
}
|
|
3696
3956
|
});
|
|
3697
3957
|
// packages/cli/src/commands/export-selection.ts
|
|
3698
|
-
import { writeFileSync as
|
|
3958
|
+
import { writeFileSync as writeFileSync4 } from "fs";
|
|
3699
3959
|
var export_selection_default = defineCommand({
|
|
3700
3960
|
meta: { description: "Export current selection as image" },
|
|
3701
3961
|
args: {
|
|
@@ -3713,7 +3973,7 @@ var export_selection_default = defineCommand({
|
|
|
3713
3973
|
padding: Number(args.padding)
|
|
3714
3974
|
});
|
|
3715
3975
|
const buffer = Buffer.from(result.data, "base64");
|
|
3716
|
-
|
|
3976
|
+
writeFileSync4(args.output, buffer);
|
|
3717
3977
|
console.log(args.output);
|
|
3718
3978
|
} catch (e2) {
|
|
3719
3979
|
handleError(e2);
|
package/package.json
CHANGED
|
@@ -877,6 +877,17 @@
|
|
|
877
877
|
node.remove();
|
|
878
878
|
return { deleted: true };
|
|
879
879
|
}
|
|
880
|
+
// ==================== EVAL ====================
|
|
881
|
+
case "eval": {
|
|
882
|
+
const { code } = args;
|
|
883
|
+
const AsyncFunction = Object.getPrototypeOf(function() {
|
|
884
|
+
return __async(this, null, function* () {
|
|
885
|
+
});
|
|
886
|
+
}).constructor;
|
|
887
|
+
const wrappedCode = code.trim().startsWith("return") ? code : `return (async () => { ${code} })()`;
|
|
888
|
+
const fn = new AsyncFunction("figma", wrappedCode);
|
|
889
|
+
return yield fn(figma);
|
|
890
|
+
}
|
|
880
891
|
default:
|
|
881
892
|
throw new Error(`Unknown command: ${command}`);
|
|
882
893
|
}
|