figmatk 0.0.7 → 0.0.8
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/lib/api.mjs +7 -4
- package/package.json +1 -1
- package/skills/figmatk/SKILL.md +83 -67
package/lib/api.mjs
CHANGED
|
@@ -1667,12 +1667,15 @@ function parseColor(fd, color) {
|
|
|
1667
1667
|
if (typeof color === 'string') {
|
|
1668
1668
|
// Hex string
|
|
1669
1669
|
if (/^#?[0-9a-fA-F]{6}$/.test(color)) return _hexToRgb(color);
|
|
1670
|
-
//
|
|
1670
|
+
// Figma theme variable first (exact match, preserves colorVar binding for slides)
|
|
1671
|
+
try {
|
|
1672
|
+
const variable = resolveColorVariable(fd, color);
|
|
1673
|
+
return { r: variable.r, g: variable.g, b: variable.b, _guid: variable.guid };
|
|
1674
|
+
} catch (_) {}
|
|
1675
|
+
// Designer alias fallback (case-insensitive)
|
|
1671
1676
|
const alias = DESIGNER_COLORS[color.toLowerCase()];
|
|
1672
1677
|
if (alias) return _hexToRgb(alias);
|
|
1673
|
-
|
|
1674
|
-
const variable = resolveColorVariable(fd, color);
|
|
1675
|
-
return { r: variable.r, g: variable.g, b: variable.b, _guid: variable.guid };
|
|
1678
|
+
throw new Error(`Unknown color: "${color}". Use a Light Slides name ('Black', 'Teal'), a designer alias ('navy', 'coral'), or a hex string ('#E63946').`);
|
|
1676
1679
|
}
|
|
1677
1680
|
throw new Error(`Invalid color: ${JSON.stringify(color)}`);
|
|
1678
1681
|
}
|
package/package.json
CHANGED
package/skills/figmatk/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: >
|
|
|
5
5
|
create a presentation, build a slide deck, edit slides, update text or images,
|
|
6
6
|
clone or remove slides, or produce a .deck file for Figma Slides.
|
|
7
7
|
metadata:
|
|
8
|
-
version: "0.0.
|
|
8
|
+
version: "0.0.7"
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# FigmaTK Skill
|
|
@@ -25,19 +25,50 @@ metadata:
|
|
|
25
25
|
|
|
26
26
|
Use this when the user wants a new presentation. Write a Node.js script and execute it.
|
|
27
27
|
|
|
28
|
+
> **Import path:** `figmatk` is an npm package. Import from the installed package:
|
|
29
|
+
> ```javascript
|
|
30
|
+
> import { Deck } from 'figmatk';
|
|
31
|
+
> ```
|
|
32
|
+
|
|
28
33
|
```javascript
|
|
29
34
|
import { Deck } from 'figmatk';
|
|
30
35
|
|
|
31
36
|
const deck = await Deck.create('My Presentation');
|
|
32
|
-
const slide = deck.addBlankSlide();
|
|
33
37
|
|
|
34
|
-
slide.
|
|
35
|
-
slide.
|
|
36
|
-
slide.addText('
|
|
38
|
+
const slide = deck.addBlankSlide(); // template blank slide auto-removed
|
|
39
|
+
slide.setBackground('Black'); // named color — see list below
|
|
40
|
+
slide.addText('Slide Title', {
|
|
41
|
+
style: 'Title', color: 'White',
|
|
42
|
+
x: 64, y: 80, width: 1792, align: 'LEFT'
|
|
43
|
+
});
|
|
44
|
+
slide.addText('Subtitle', {
|
|
45
|
+
style: 'Body 1', color: 'Grey',
|
|
46
|
+
x: 64, y: 240, width: 1200, align: 'LEFT'
|
|
47
|
+
});
|
|
37
48
|
|
|
38
49
|
await deck.save('/path/to/output.deck');
|
|
39
50
|
```
|
|
40
51
|
|
|
52
|
+
### ⚠️ Critical gotchas
|
|
53
|
+
|
|
54
|
+
| Issue | Wrong | Right |
|
|
55
|
+
|-------|-------|-------|
|
|
56
|
+
| `setBackground` with hex | `s.setBackground('#1A1A1A')` | `s.setBackground('Black')` |
|
|
57
|
+
| `setBackground` with raw RGB | `s.setBackground({ r:0.1, g:0.1, b:0.1 })` | `s.setBackground('Black')` — raw RGB silently renders white |
|
|
58
|
+
| Shape method signature | `s.addRectangle({ x:0, y:0, width:100 })` | `s.addRectangle(0, 0, 100, 100, opts)` |
|
|
59
|
+
| Shape fill color | `{ fill: '#F4900C' }` | `{ fill: hex('#F4900C') }` — use the hex() helper |
|
|
60
|
+
| `addLine` options | `{ strokeColor: ..., strokeWeight: 2 }` | `{ color: 'Black', weight: 2 }` |
|
|
61
|
+
| `align` value | `align: 'left'` | `align: 'LEFT'` (uppercase) |
|
|
62
|
+
|
|
63
|
+
### Hex color helper (for shape fills)
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
function hex(h) {
|
|
67
|
+
return { r: parseInt(h.slice(1,3),16)/255, g: parseInt(h.slice(3,5),16)/255, b: parseInt(h.slice(5,7),16)/255 };
|
|
68
|
+
}
|
|
69
|
+
// Usage: s.addRectangle(0, 0, 200, 50, { fill: hex('#F4900C') })
|
|
70
|
+
```
|
|
71
|
+
|
|
41
72
|
### Text styles
|
|
42
73
|
|
|
43
74
|
| Style | Size | Weight | Use for |
|
|
@@ -51,37 +82,33 @@ await deck.save('/path/to/output.deck');
|
|
|
51
82
|
| `Body 3` | 24pt | Regular | Captions, labels |
|
|
52
83
|
| `Note` | 20pt | Regular | Footnotes, sources |
|
|
53
84
|
|
|
54
|
-
###
|
|
85
|
+
### Named colors for `setBackground()`
|
|
55
86
|
|
|
56
|
-
|
|
87
|
+
> **Case-sensitive.** `'Black'` works, `'black'` does not.
|
|
57
88
|
|
|
58
|
-
|
|
59
|
-
|------|---------|
|
|
60
|
-
| Designer name | `'teal'`, `'coral'`, `'navy'`, `'midnight'`, `'forest'`, `'charcoal'`, `'cream'`, `'gold'`, `'terracotta'`, `'sage'`, `'cobalt'`, `'rose'`, `'indigo'`, `'burgundy'`, `'sand'`... |
|
|
61
|
-
| Hex string | `'#E63946'` |
|
|
62
|
-
| Light Slides theme | `'Blue'`, `'Red'`, `'Green'`, `'Yellow'`, `'Orange'`, `'Pink'`, `'Purple'`, `'Slate'`, `'White'`, `'Black'` |
|
|
89
|
+
`'Black'`, `'White'`, `'Grey'`, `'Blue'`, `'Red'`, `'Yellow'`, `'Green'`, `'Orange'`, `'Pink'`, `'Purple'`, `'Teal'`, `'Violet'`, `'Persimmon'`, `'Pale Pink'`, `'Pale Blue'`, `'Pale Green'`, `'Pale Teal'`, `'Pale Purple'`, `'Pale Persimmon'`, `'Pale Violet'`, `'Pale Red'`, `'Pale Yellow'`
|
|
63
90
|
|
|
64
|
-
|
|
91
|
+
Use `'Black'` for dark backgrounds, `'White'` for light. For custom slide backgrounds, use the closest named color — **not hex**.
|
|
65
92
|
|
|
66
93
|
### Slide dimensions
|
|
67
94
|
|
|
68
|
-
1920 × 1080px.
|
|
95
|
+
1920 × 1080px. All positions and sizes in pixels.
|
|
69
96
|
|
|
70
|
-
###
|
|
97
|
+
### Slide methods (correct signatures)
|
|
71
98
|
|
|
72
99
|
```javascript
|
|
73
|
-
slide.setBackground(
|
|
74
|
-
slide.addText(text, opts) // opts: style, color, x, y, width, align, bold, italic, fontSize
|
|
75
|
-
slide.addFrame(opts) // auto-layout
|
|
76
|
-
slide.addRectangle(
|
|
77
|
-
slide.addEllipse(
|
|
78
|
-
slide.addDiamond(opts)
|
|
79
|
-
slide.addTriangle(opts)
|
|
80
|
-
slide.addStar(opts)
|
|
81
|
-
slide.addLine(x1, y1, x2, y2, opts) //
|
|
82
|
-
slide.addImage(path, opts) //
|
|
83
|
-
slide.addTable(data, opts) // 2D array
|
|
84
|
-
slide.addSVG(x, y, width, svgPathOrBuf, opts)
|
|
100
|
+
slide.setBackground(namedColor) // named color only — hex/raw RGB render white
|
|
101
|
+
slide.addText(text, opts) // opts: style, color (named or hex('#...')), x, y, width, align, bold, italic, fontSize
|
|
102
|
+
slide.addFrame(opts) // auto-layout: stackMode, spacing, x, y, width, height
|
|
103
|
+
slide.addRectangle(x, y, width, height, opts) // opts: fill (named or {r,g,b}), opacity, cornerRadius
|
|
104
|
+
slide.addEllipse(x, y, width, height, opts) // opts: fill, opacity
|
|
105
|
+
slide.addDiamond(x, y, width, height, opts)
|
|
106
|
+
slide.addTriangle(x, y, width, height, opts)
|
|
107
|
+
slide.addStar(x, y, width, height, opts)
|
|
108
|
+
slide.addLine(x1, y1, x2, y2, opts) // opts: color, weight
|
|
109
|
+
slide.addImage(path, opts) // opts: x, y, width, height
|
|
110
|
+
slide.addTable(data, opts) // 2D string array; opts: x, y, width, colWidths, rowHeight
|
|
111
|
+
slide.addSVG(x, y, width, svgPathOrBuf, opts)
|
|
85
112
|
```
|
|
86
113
|
|
|
87
114
|
---
|
|
@@ -118,71 +145,60 @@ Use this when the user provides a `.deck` file to modify.
|
|
|
118
145
|
|
|
119
146
|
## Design Philosophy
|
|
120
147
|
|
|
121
|
-
Every deck must look **intentionally designed**, not AI-generated.
|
|
148
|
+
Every deck must look **intentionally designed**, not AI-generated.
|
|
122
149
|
|
|
123
150
|
### Colour
|
|
124
151
|
|
|
125
|
-
- Pick a bold palette
|
|
126
|
-
-
|
|
127
|
-
-
|
|
152
|
+
- Pick a bold palette for the **specific topic** — not a generic one.
|
|
153
|
+
- One dominant colour (60–70%) + 1–2 supporting tones + one sharp accent.
|
|
154
|
+
- Dark backgrounds on title/conclusion slides, light on content ("sandwich") — or fully dark for premium feel.
|
|
128
155
|
|
|
129
|
-
**Starter palettes
|
|
156
|
+
**Starter palettes** (use nearest named color for `setBackground`, hex helper for shapes):
|
|
130
157
|
|
|
131
|
-
| Theme | Background |
|
|
132
|
-
|
|
133
|
-
| Midnight | `
|
|
134
|
-
| Forest | `
|
|
135
|
-
| Coral | `
|
|
136
|
-
| Terracotta | `
|
|
137
|
-
| Ocean | `
|
|
138
|
-
| Minimal | `
|
|
158
|
+
| Theme | Background | Shape accent | Text |
|
|
159
|
+
|-------|-----------|-------------|------|
|
|
160
|
+
| Midnight | `'Black'` | `hex('#CADCFC')` | `'White'` |
|
|
161
|
+
| Forest | `'Green'` | `hex('#97BC62')` | `'White'` |
|
|
162
|
+
| Coral | `'Persimmon'` | `hex('#2F3C7E')` | `'White'` |
|
|
163
|
+
| Terracotta | `'Persimmon'` | `hex('#E7E8D1')` | `'White'` |
|
|
164
|
+
| Ocean | `'Blue'` | `hex('#21295C')` | `'White'` |
|
|
165
|
+
| Minimal | `'White'` | `hex('#36454F')` | `'Black'` |
|
|
139
166
|
|
|
140
167
|
### Layout
|
|
141
168
|
|
|
142
|
-
- Every slide needs at least **one visual element** — shape, image, SVG
|
|
143
|
-
- **Vary layouts** — never
|
|
144
|
-
-
|
|
169
|
+
- Every slide needs at least **one visual element** — shape, image, SVG, or table.
|
|
170
|
+
- **Vary layouts** — never repeat the same structure slide after slide.
|
|
171
|
+
- Carry one visual motif through every slide (coloured accent bar, icon circles, etc.).
|
|
145
172
|
|
|
146
|
-
**Layout options
|
|
147
|
-
|
|
148
|
-
- Two-column (text left, visual right)
|
|
149
|
-
- Icon + text rows (icon in coloured circle, bold header, description)
|
|
150
|
-
- 2×2 or 2×3 grid of cards
|
|
151
|
-
- Large stat callout (big number + small label)
|
|
152
|
-
- Half-background image with text overlay
|
|
153
|
-
- Timeline / numbered steps
|
|
173
|
+
**Layout options:** two-column, icon+text rows, 2×2/2×3 grid, large stat callout, half-background image, timeline/steps.
|
|
154
174
|
|
|
155
175
|
### Typography
|
|
156
176
|
|
|
157
177
|
- Left-align body text. Centre only titles.
|
|
158
|
-
-
|
|
159
|
-
- Minimum 64px margin from slide edges. 24–48px gap between content blocks.
|
|
178
|
+
- Minimum 64px margin from slide edges. 24–48px between content blocks.
|
|
160
179
|
|
|
161
|
-
###
|
|
180
|
+
### Never do
|
|
162
181
|
|
|
163
182
|
- Repeat the same layout slide after slide
|
|
164
183
|
- Centre body text
|
|
165
|
-
- Use accent lines under slide titles (hallmark of AI-generated slides
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
- Default to generic blue — pick colours that reflect the topic
|
|
184
|
+
- Use accent lines under slide titles (hallmark of AI-generated slides)
|
|
185
|
+
- Text-only slides
|
|
186
|
+
- Low-contrast text against background
|
|
169
187
|
|
|
170
188
|
---
|
|
171
189
|
|
|
172
190
|
## QA
|
|
173
191
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
2. **Tell the user** to upload the `.deck` to Figma Slides and review visually — this is the only way to catch rendering issues
|
|
178
|
-
3. **Offer to fix** any issues the user reports after upload
|
|
192
|
+
1. Self-check: no placeholder text (`lorem ipsum`, `[title here]`) remains
|
|
193
|
+
2. Tell the user to open the `.deck` in Figma Desktop to catch rendering issues
|
|
194
|
+
3. Offer to fix anything they report
|
|
179
195
|
|
|
180
196
|
---
|
|
181
197
|
|
|
182
198
|
## Critical Format Rules
|
|
183
199
|
|
|
184
|
-
- Blank text
|
|
185
|
-
- Image overrides
|
|
186
|
-
- Removed nodes
|
|
187
|
-
- Chunk 1 of `canvas.fig` must be zstd-compressed
|
|
200
|
+
- Blank text must be `" "` (space), never `""` — empty string crashes Figma
|
|
201
|
+
- Image overrides need both a full-image hash and thumbnail hash (40-char hex SHA-1)
|
|
202
|
+
- Removed nodes: set `phase: 'REMOVED'`, never delete from `nodeChanges`
|
|
203
|
+
- Chunk 1 of `canvas.fig` must be zstd-compressed
|
|
188
204
|
- `thumbHash` must be `new Uint8Array(0)`, never `{}`
|