5.5 KiB
open-pencil eval — Figma-ähnliche Plugin-API für Headless-Skripting
Übersicht
bun open-pencil eval <file> --code '<js>' führt JavaScript gegen eine .fig-Datei mit einem Figma-kompatiblen figma-Globalobjekt aus. Dies ermöglicht Headless-Skripting, Batch-Operationen, KI-Werkzeug-Ausführung und Tests — alles ohne die GUI.
Das figma-Objekt spiegelt Figmas Plugin-API-Oberfläche so nah wie möglich, sodass vorhandenes Figma-Plugin-Wissen und Code-Snippets direkt übertragbar sind.
# Frame erstellen, Auto-Layout setzen, Kinder hinzufügen
bun open-pencil eval design.fig --code '
const frame = figma.createFrame()
frame.name = "Card"
frame.resize(300, 200)
frame.layoutMode = "VERTICAL"
frame.itemSpacing = 12
frame.paddingTop = frame.paddingBottom = 16
frame.paddingLeft = frame.paddingRight = 16
frame.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]
const title = figma.createText()
title.characters = "Hello World"
title.fontSize = 24
frame.appendChild(title)
return { id: frame.id, name: frame.name }
'
# Knoten abfragen
bun open-pencil eval design.fig --code '
const buttons = figma.currentPage.findAll(n => n.type === "FRAME" && n.name.includes("Button"))
return buttons.map(b => ({ id: b.id, name: b.name, w: b.width, h: b.height }))
'
# Von stdin lesen (für mehrzeilige Skripte / Piping)
cat transform.js | bun open-pencil eval design.fig --stdin
# Änderungen zurückschreiben
bun open-pencil eval design.fig --code '...' --write
bun open-pencil eval design.fig --code '...' -o modified.fig
Architektur
┌──────────────────────────────────────────────────────┐
│ CLI: `open-pencil eval <file> --code '...'` │
│ ↓ │
│ loadDocument(file) → SceneGraph │
│ ↓ │
│ FigmaAPI(sceneGraph) → `figma` Proxy-Objekt │
│ ↓ │
│ AsyncFunction('figma', wrappedCode)(figmaProxy) │
│ ↓ │
│ Ergebnis als JSON / agentfmt ausgeben │
│ optional: saveDocument(file) bei --write │
└──────────────────────────────────────────────────────┘
Schlüsselklassen
| Klasse | Ort | Rolle |
|---|---|---|
FigmaAPI |
packages/core/src/figma-api.ts |
Proxy-Objekt, das figma.*-Methoden gegen SceneGraph implementiert |
FigmaNode |
packages/core/src/figma-api.ts |
Proxy, der SceneNode mit Figma-ähnlichem Eigenschaftszugriff umhüllt |
eval-Befehl |
packages/cli/src/commands/eval.ts |
CLI-Befehl: Dokument laden, API erstellen, Code ausführen |
Warum in @open-pencil/core?
Die FigmaAPI-Klasse lebt in core (nicht CLI), weil:
- KI-Werkzeuge nutzen sie wieder — das Chat-Panels
render-Werkzeug kann JSX über dieselbe API ausführen - Testskripte — Unit-Tests können die API für Fixture-Setup verwenden
- Keine DOM-Abhängigkeiten — läuft headless in Bun
CLI-Befehl
bun open-pencil eval <file> [optionen]
Argumente:
file .fig-Datei zum Bearbeiten
Optionen:
--code, -c Auszuführender JavaScript-Code (hat Zugriff auf `figma`-Global)
--stdin Code von stdin statt --code lesen
--write, -w Änderungen in die Eingabedatei zurückschreiben
-o, --output In eine andere Datei schreiben
--json Ergebnis als JSON ausgeben (Standard für Nicht-TTY)
--quiet, -q Ausgabe unterdrücken, nur Datei schreiben
Ausführungsmodell
.figladen →SceneGraphFigmaAPI(graph)erstellen →figma-Proxy- Benutzercode in async-Funktion verpacken:
return (async () => { <code> })() - Mit
figmaals einzigem Argument ausführen - Rückgabewert ausgeben (JSON oder agentfmt)
- Bei
--writeoder-o:SceneGraphzurück in.figserialisieren
Rückgabewert-Formatierung
undefined/void→ keine Ausgabe- Primitive → direkt ausgeben
- Objekte/Arrays →
JSON.stringify(result, null, 2)oder agentfmt-Tabellen FigmaNode→ serialisiert als{ id, type, name, x, y, width, height, fills, ... }- Arrays von
FigmaNode→ als Liste serialisiert
FigmaAPI — Phasenweise Implementierung
Die vollständige API-Referenz mit Phasen (Core, Komponenten, Variablen, Stile) und Eigenschafts-Mapping finden Sie in der englischen Version.
Phase 1: Core
Deckt ~80% realer Plugin-Skripte ab. Enthält: Dokument & Seite, Knotenerstellung, Knoteneigenschaften, Baumoperationen, Auto-Layout, Text, Kontur und Export.
Phase 2: Komponenten & Instanzen
figma.createComponent(), combineAsVariants(), createInstance(), detachInstance(), mainComponent.
Phase 3: Variablen
figma.variables.getLocalVariables(), createVariable(), createVariableCollection(), setBoundVariable().
Phase 4: Stile & Erweitert
Paint/Text/Effekt-Stile, Boolesche Operationen, JSX-Renderer.
Gemeinsam mit KI-Werkzeugen
Die FigmaAPI-Klasse ist dieselbe API-Oberfläche, die KI-Werkzeuge verwenden. Dies stellt sicher, dass CLI-Skripte und KI-Werkzeuge identisch funktionieren.
Dateilayout
packages/core/src/
figma-api.ts # FigmaAPI-Klasse + FigmaNode-Proxy
packages/cli/src/commands/
eval.ts # CLI-Befehl