@atezer/figma-mcp-bridge 1.7.29 → 1.9.0
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/CHANGELOG.md +403 -0
- package/README.md +4 -3
- package/agents/_orchestrator-protocol.md +185 -0
- package/agents/ds-auditor.md +73 -22
- package/agents/screen-builder.md +60 -22
- package/agents/token-syncer.md +63 -19
- package/dist/core/code-warnings.d.ts +38 -0
- package/dist/core/code-warnings.d.ts.map +1 -0
- package/dist/core/code-warnings.js +191 -0
- package/dist/core/code-warnings.js.map +1 -0
- package/dist/core/device-presets.d.ts +49 -0
- package/dist/core/device-presets.d.ts.map +1 -0
- package/dist/core/device-presets.js +141 -0
- package/dist/core/device-presets.js.map +1 -0
- package/dist/core/instructions.d.ts +4 -2
- package/dist/core/instructions.d.ts.map +1 -1
- package/dist/core/instructions.js +239 -29
- package/dist/core/instructions.js.map +1 -1
- package/dist/core/plugin-bridge-connector.d.ts +32 -0
- package/dist/core/plugin-bridge-connector.d.ts.map +1 -1
- package/dist/core/plugin-bridge-connector.js +31 -2
- package/dist/core/plugin-bridge-connector.js.map +1 -1
- package/dist/core/plugin-bridge-server.d.ts +8 -0
- package/dist/core/plugin-bridge-server.d.ts.map +1 -1
- package/dist/core/plugin-bridge-server.js +27 -2
- package/dist/core/plugin-bridge-server.js.map +1 -1
- package/dist/core/response-guard.d.ts +23 -0
- package/dist/core/response-guard.d.ts.map +1 -1
- package/dist/core/response-guard.js +113 -0
- package/dist/core/response-guard.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.d.ts.map +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/local-plugin-only.d.ts.map +1 -1
- package/dist/local-plugin-only.js +504 -85
- package/dist/local-plugin-only.js.map +1 -1
- package/f-mcp-plugin/code.js +514 -29
- package/f-mcp-plugin/ui.html +62 -6
- package/package.json +1 -1
- package/skills/SKILL_INDEX.md +13 -1
- package/skills/apply-figma-design-system/SKILL.md +37 -0
- package/skills/audit-figma-design-system/SKILL.md +38 -0
- package/skills/code-design-mapper/SKILL.md +37 -0
- package/skills/design-token-pipeline/SKILL.md +44 -0
- package/skills/figma-canvas-ops/SKILL.md +200 -240
- package/skills/fmcp-ds-audit-orchestrator/SKILL.md +205 -0
- package/skills/fmcp-intent-router/SKILL.md +574 -0
- package/skills/fmcp-project-rules/SKILL.md +9 -5
- package/skills/fmcp-screen-orchestrator/SKILL.md +166 -0
- package/skills/fmcp-screen-recipes/SKILL.md +528 -0
- package/skills/fmcp-token-sync-orchestrator/SKILL.md +198 -0
- package/skills/generate-figma-library/SKILL.md +38 -0
- package/skills/generate-figma-screen/SKILL.md +382 -19
- package/skills/implement-design/SKILL.md +32 -0
- package/skills/inspiration-intake/SKILL.md +220 -0
- package/skills/visual-qa-compare/SKILL.md +33 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: figma-canvas-ops
|
|
3
|
-
description: F-MCP Bridge ile Figma tuvalinde güvenli yazma/düzenleme için zorunlu önkoşul kılavuzu. figma_execute çağrısı öncesi bu skill yüklenmelidir.
|
|
3
|
+
description: F-MCP Bridge ile Figma tuvalinde güvenli yazma/düzenleme için zorunlu önkoşul kılavuzu. figma_execute çağrısı öncesi bu skill yüklenmelidir.
|
|
4
4
|
metadata:
|
|
5
5
|
mcp-server: user-figma-mcp-bridge
|
|
6
6
|
personas:
|
|
@@ -10,172 +10,142 @@ metadata:
|
|
|
10
10
|
|
|
11
11
|
# Figma Canvas Ops — figma_execute Güvenli Kullanım Kılavuzu
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Araç Eşleme (topluluk → F-MCP)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
**Tuval yazan her skill** (apply-figma-design-system, fix-figma-design-system-finding, generate-figma-screen, generate-figma-library, figjam-diagram-builder) bu kılavuzdaki kuralları uygulamalıdır.
|
|
18
|
-
|
|
19
|
-
## Araç eşleme (topluluk → F-MCP)
|
|
20
|
-
|
|
21
|
-
| Topluluk (resmi MCP) | F-MCP Bridge | Not |
|
|
15
|
+
| Topluluk | F-MCP Bridge | Not |
|
|
22
16
|
|---|---|---|
|
|
23
|
-
| `use_figma` | `figma_execute` | JS çalıştırma
|
|
24
|
-
| `get_metadata` | `figma_get_file_data` | Yapı/metadata
|
|
25
|
-
| `get_screenshot` | `figma_capture_screenshot` |
|
|
17
|
+
| `use_figma` | `figma_execute` | JS çalıştırma |
|
|
18
|
+
| `get_metadata` | `figma_get_file_data` | Yapı/metadata |
|
|
19
|
+
| `get_screenshot` | `figma_capture_screenshot` | Görsel doğrulama |
|
|
26
20
|
| `search_design_system` | `figma_search_components` + `figma_get_design_system_summary` | İki araç birlikte |
|
|
27
21
|
|
|
28
|
-
Detaylı eşleme: [TOOL_MAPPING.md](../TOOL_MAPPING.md)
|
|
29
|
-
|
|
30
22
|
## Prerequisites
|
|
31
23
|
|
|
32
|
-
- F-MCP Bridge plugin
|
|
33
|
-
- `
|
|
34
|
-
|
|
35
|
-
## 1. Kritik Kurallar
|
|
36
|
-
|
|
37
|
-
1. **`return` ile veri dön.** Return değeri otomatik JSON serialize edilir (object, array, string, number). `figma.closePlugin()` çağırma — bu bridge tarafından yönetilir.
|
|
24
|
+
- F-MCP Bridge plugin bağlı olmalı (`figma_get_status()`)
|
|
25
|
+
- Aktif DS context: `.claude/design-systems/active-ds.md` → `Status: ✅`
|
|
38
26
|
|
|
39
|
-
|
|
27
|
+
## 0. Design System Context (ZORUNLU)
|
|
40
28
|
|
|
41
|
-
|
|
29
|
+
### 0a — Active DS check
|
|
30
|
+
```
|
|
31
|
+
1. Read .claude/design-systems/active-ds.md
|
|
32
|
+
2. ✅ Aktif → Library Name not al, 0b'ye geç
|
|
33
|
+
❌ Seçilmedi → 0c'ye geç
|
|
34
|
+
"DS bypass mode" → DS'siz devam
|
|
35
|
+
```
|
|
42
36
|
|
|
43
|
-
|
|
37
|
+
### 0b — DS asset cache hazırlığı
|
|
38
|
+
```
|
|
39
|
+
1. .claude/design-systems/<library-id>/components.md var mı?
|
|
40
|
+
2. .claude/design-systems/<library-id>/tokens.md var mı?
|
|
41
|
+
3. Yoksa: figma_get_library_variables + figma_search_assets ile keşfet, cache'e yaz
|
|
42
|
+
```
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
### 0c — Kullanıcıya DS seçimi sor
|
|
45
|
+
active-ds.md `❌` ise: "Hangi DS? (SUI / Material / HIG / Kendi / Hiçbiri)". Yanıt sonrası active-ds.md güncelle, 0b'ye geç. Sonraki turlarda TEKRAR SORMA.
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
figma_execute({ code: "...", timeout: 15000 })
|
|
50
|
-
```
|
|
51
|
-
Kılavuz: 1-5 node → 5000ms | 6-12 node → 10000ms | 13+ node → işlemi böl veya 15000-30000ms
|
|
47
|
+
## 1. Kritik Kurallar
|
|
52
48
|
|
|
53
|
-
|
|
49
|
+
1. **`return` ile veri dön.** `figma.closePlugin()` çağırma.
|
|
54
50
|
|
|
55
|
-
|
|
56
|
-
```js
|
|
57
|
-
// Renk değerini DS'den oku, aşağıdaki sadece API FORMAT örneğidir
|
|
58
|
-
const fills = [...node.fills];
|
|
59
|
-
fills[0] = { ...fills[0], color: DS_COLOR }; // DS'den okunan değer
|
|
60
|
-
node.fills = fills;
|
|
61
|
-
```
|
|
51
|
+
2. **Düz JS, top-level `await`.** Kod otomatik async sarılır. `(async()=>{})()` sarma. **Async API zorunlu** — dynamic-page mode'da sync API'ler throws:
|
|
62
52
|
|
|
63
|
-
|
|
53
|
+
| ❌ YASAK (sync) | ✅ ZORUNLU (async) |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `instance.mainComponent` | `await instance.getMainComponentAsync()` |
|
|
56
|
+
| `figma.getNodeById(id)` | `await figma.getNodeByIdAsync(id)` |
|
|
57
|
+
| `figma.variables.importVariableByKey(key)` | `await figma.variables.importVariableByKeyAsync(key)` |
|
|
58
|
+
| `figma.importComponentByKey(key)` | `await figma.importComponentByKeyAsync(key)` |
|
|
59
|
+
| `figma.importStyleByKey(key)` | `await figma.importStyleByKeyAsync(key)` |
|
|
60
|
+
| `node.effectStyleId = x` | `await node.setEffectStyleIdAsync(x)` |
|
|
61
|
+
| `node.textStyleId = x` | `await node.setTextStyleIdAsync(x)` |
|
|
62
|
+
| `figma.listAvailableFonts()` | `await figma.listAvailableFontsAsync()` |
|
|
63
|
+
| `figma.loadFont(...)` | `await figma.loadFontAsync(...)` |
|
|
64
|
+
| `figma.variables.getVariableCollectionById(id)` | `await figma.variables.getVariableCollectionByIdAsync(id)` |
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
3. **`figma.notify()` çalışmaz** — kullanma.
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
4. **`console.log()` dönmez** — `return` kullan.
|
|
68
69
|
|
|
69
|
-
|
|
70
|
+
5. **Küçük adımlarla çalış.** Timeout: varsayılan 15000ms, max 30000ms.
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
// Fontu belirledikten sonra yükle:
|
|
73
|
-
await figma.loadFontAsync({ family: "FONT_ADI", style: "Regular" });
|
|
74
|
-
// Gerekli diğer ağırlıklar:
|
|
75
|
-
await figma.loadFontAsync({ family: "FONT_ADI", style: "Bold" });
|
|
76
|
-
```
|
|
77
|
-
**Asla** hardcoded font varsayma — her zaman bu sırayı takip et. Bu kural font, renk, boyut, spacing dahil TÜM design token'lar için geçerlidir. Detay: `project-context.md` → "Design Token Kuralı".
|
|
72
|
+
### 5a. CHUNKING MANDATE (v2.0)
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
```js
|
|
81
|
-
await figma.loadFontAsync({ family: "Inter", style: "Medium" });
|
|
82
|
-
const shape = figma.createShapeWithText();
|
|
83
|
-
shape.text.characters = "Metin"; // Medium yüklenmeden hata verir
|
|
84
|
-
```
|
|
85
|
-
Genel kural: metin düzenlemeden önce **mevcut fontu kontrol et** ve o fontu yükle:
|
|
86
|
-
```js
|
|
87
|
-
await figma.loadFontAsync(shape.text.fontName); // dinamik font algılama
|
|
88
|
-
```
|
|
74
|
+
Her `figma_execute` **max 15 atomic operation**. Atomic op'lar: node/instance oluşturma, variable/style/component import, font load, bind operasyonu, getNodeByIdAsync, getMainComponentAsync.
|
|
89
75
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
```
|
|
76
|
+
- 1 execute = 1 mega-goal (discovery, frame+structure, 3-4 component placement)
|
|
77
|
+
- 25+ op → 2-3 execute'a böl
|
|
78
|
+
- Execute arası state: nodeId'leri `return` et, sonraki execute `getNodeByIdAsync` ile al
|
|
79
|
+
- Her execute sonrası 1 satır Türkçe micro-report
|
|
95
80
|
|
|
96
|
-
|
|
81
|
+
6. **Renkler 0–1 aralığında** (0–255 değil). Hardcoded renk YASAK — DS'den oku.
|
|
97
82
|
|
|
98
|
-
|
|
83
|
+
7. **Fills/strokes read-only array** — klonla, değiştir, ata:
|
|
99
84
|
```js
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
85
|
+
const fills = [...node.fills];
|
|
86
|
+
fills[0] = { ...fills[0], color: DS_COLOR };
|
|
87
|
+
node.fills = fills;
|
|
103
88
|
```
|
|
104
89
|
|
|
105
|
-
|
|
106
|
-
```js
|
|
107
|
-
const variable = await figma.variables.importVariableByKeyAsync("VARIABLE_KEY");
|
|
108
|
-
```
|
|
90
|
+
8. **Font yükleme zorunlu.** Sıra: (a) DS cache'ten font oku → (b) Yoksa kullanıcıya sor → (c) "Sen seç" → Inter.
|
|
109
91
|
|
|
110
|
-
**
|
|
92
|
+
**8a-1) Font weight check (ZORUNLU):** `loadFontAsync` öncesi `listAvailableFontsAsync` ile kontrol et. Fallback helper:
|
|
111
93
|
```js
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
|
|
94
|
+
const allFonts = await figma.listAvailableFontsAsync();
|
|
95
|
+
const styles = allFonts.filter(f => f.fontName.family === "SHBGrotesk").map(f => f.fontName.style);
|
|
96
|
+
function pickStyle(desired, available) {
|
|
97
|
+
if (available.indexOf(desired) >= 0) return desired;
|
|
98
|
+
var fb = { "Medium":["Semi Bold","Regular"], "ExtraBold":["Bold"], "Black":["Bold"], "Thin":["Light","Regular"] };
|
|
99
|
+
var alts = fb[desired] || [];
|
|
100
|
+
for (var i = 0; i < alts.length; i++) { if (available.indexOf(alts[i]) >= 0) return alts[i]; }
|
|
101
|
+
return available.find(s => s.indexOf("Italic") < 0) || available[0];
|
|
102
|
+
}
|
|
103
|
+
await figma.loadFontAsync({ family: "SHBGrotesk", style: pickStyle("Medium", styles) });
|
|
115
104
|
```
|
|
105
|
+
**FigJam:** `createShapeWithText()` varsayılan "Inter Medium". Metin düzenlemeden önce `await figma.loadFontAsync(shape.text.fontName)`.
|
|
116
106
|
|
|
117
|
-
|
|
118
|
-
```js
|
|
119
|
-
node.setBoundVariable("paddingLeft", variable);
|
|
120
|
-
node.setBoundVariable("paddingRight", variable);
|
|
121
|
-
node.setBoundVariable("itemSpacing", variable);
|
|
122
|
-
node.setBoundVariable("topLeftRadius", variable);
|
|
123
|
-
```
|
|
107
|
+
9. **Sayfa konteksti her çağrıda sıfırlanır.** Farklı sayfa: `await figma.setCurrentPageAsync(page)`.
|
|
124
108
|
|
|
125
|
-
|
|
126
|
-
```js
|
|
127
|
-
const textStyles = await figma.getLocalTextStylesAsync();
|
|
128
|
-
const bodyStyle = textStyles.find(s => s.name === "global/surface/body");
|
|
129
|
-
await textNode.setTextStyleIdAsync(bodyStyle.id);
|
|
130
|
-
```
|
|
109
|
+
10. **Tüm tasarım değerleri DS variable'a BAĞLANMALI (ZORUNLU).**
|
|
131
110
|
|
|
132
|
-
|
|
133
|
-
```js
|
|
134
|
-
const textFills = [...textNode.fills];
|
|
135
|
-
const boundTextPaint = figma.variables.setBoundVariableForPaint(textFills[0], "color", textColorVar);
|
|
136
|
-
textNode.fills = [boundTextPaint];
|
|
137
|
-
```
|
|
111
|
+
Renk, spacing, padding, radius — HİÇBİR değer hardcoded yazılmaz. Token yoksa DURDUR, kullanıcıya sor.
|
|
138
112
|
|
|
139
|
-
|
|
113
|
+
**Akış:**
|
|
114
|
+
- **Variable import:** `const v = await figma.variables.importVariableByKeyAsync("KEY")`
|
|
115
|
+
- **Renk bind:** `node.fills = [figma.variables.setBoundVariableForPaint(fills[0], "color", v)]`
|
|
116
|
+
- **Spacing bind:** `node.setBoundVariable("paddingLeft", v)`
|
|
117
|
+
- **Text style:** `await textNode.setTextStyleIdAsync(style.id)`
|
|
118
|
+
- **Text renk:** `textNode.fills = [figma.variables.setBoundVariableForPaint(textFills[0], "color", textColorVar)]`
|
|
140
119
|
|
|
141
|
-
|
|
120
|
+
Hardcoded `node.fills = [{ type: "SOLID", color: {...} }]` YASAK.
|
|
142
121
|
|
|
143
|
-
|
|
122
|
+
11. **appendChild sıralaması kritik.** ÖNCE `parent.appendChild(child)`, SONRA `child.layoutSizingHorizontal = "FILL"` / `layoutPositioning = "ABSOLUTE"`:
|
|
123
|
+
```js
|
|
124
|
+
parent.appendChild(child); // ÖNCE
|
|
125
|
+
child.layoutSizingHorizontal = "FILL"; // SONRA
|
|
126
|
+
```
|
|
127
|
+
Hata: "Can only set layoutPositioning = ABSOLUTE if parent has layoutMode !== NONE" → child append edilmemiş.
|
|
144
128
|
|
|
145
|
-
|
|
129
|
+
12. **Yeni node'ları (0,0)'dan uzağa konumlandır.** Boş alan bul.
|
|
146
130
|
|
|
147
|
-
|
|
148
|
-
```js
|
|
149
|
-
return { createdNodeIds: [...], mutatedNodeIds: [...] };
|
|
150
|
-
```
|
|
131
|
+
13. **Hata durumunda DUR.** Hata oku, düzelt, tekrar çalıştır. Atomik — hata olursa değişiklik uygulanmaz.
|
|
151
132
|
|
|
152
|
-
|
|
153
|
-
- Arka plan: `["FRAME_FILL", "SHAPE_FILL"]`
|
|
154
|
-
- Metin rengi: `["TEXT_FILL"]`
|
|
155
|
-
- Boşluk: `["GAP"]`
|
|
133
|
+
14. **Tüm node ID'lerini RETURN ET:** `return { createdNodeIds: [...] }`
|
|
156
134
|
|
|
157
|
-
|
|
135
|
+
15. **Variable scope'ları:** Arka plan: `["FRAME_FILL"]`, Metin: `["TEXT_FILL"]`, Boşluk: `["GAP"]`
|
|
158
136
|
|
|
159
|
-
|
|
137
|
+
16. **Her Promise'i `await` et.**
|
|
160
138
|
|
|
161
|
-
|
|
139
|
+
## 2. Sayfa Kuralları
|
|
162
140
|
|
|
163
141
|
```js
|
|
164
|
-
const
|
|
165
|
-
await figma.setCurrentPageAsync(
|
|
166
|
-
// targetPage.children artık yüklü
|
|
142
|
+
const page = figma.root.children.find(p => p.name === "Sayfa");
|
|
143
|
+
await figma.setCurrentPageAsync(page);
|
|
167
144
|
```
|
|
168
|
-
|
|
169
|
-
**Sync setter `figma.currentPage = page` hata verir** — her zaman `await figma.setCurrentPageAsync(page)` kullan.
|
|
170
|
-
|
|
171
|
-
### Çağrılar arası
|
|
172
|
-
|
|
173
|
-
Her `figma_execute` çağrısında `figma.currentPage` ilk sayfaya sıfırlanır. Çoklu çağrı gerektiren iş akışlarında her çağrının başında `setCurrentPageAsync` çağır.
|
|
145
|
+
Sync `figma.currentPage = page` HATA verir. Her `figma_execute`'ta `currentPage` sıfırlanır.
|
|
174
146
|
|
|
175
147
|
## 3. Auto-Layout Kalıpları
|
|
176
148
|
|
|
177
|
-
### Frame oluşturma
|
|
178
|
-
|
|
179
149
|
```js
|
|
180
150
|
const frame = figma.createFrame();
|
|
181
151
|
frame.layoutMode = "VERTICAL";
|
|
@@ -186,140 +156,130 @@ frame.paddingTop = frame.paddingBottom = 24;
|
|
|
186
156
|
frame.paddingLeft = frame.paddingRight = 24;
|
|
187
157
|
```
|
|
188
158
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
```js
|
|
192
|
-
const parent = figma.createFrame();
|
|
193
|
-
parent.layoutMode = "VERTICAL";
|
|
194
|
-
const child = figma.createFrame();
|
|
195
|
-
parent.appendChild(child); // ÖNCE ekle
|
|
196
|
-
child.layoutSizingHorizontal = "FILL"; // SONRA FILL ayarla
|
|
197
|
-
```
|
|
159
|
+
FILL boyutlandırma: ÖNCE appendChild, SONRA `layoutSizingHorizontal = "FILL"` (Rule 11).
|
|
198
160
|
|
|
199
161
|
## 4. Bileşen ve Instance Kalıpları
|
|
200
162
|
|
|
201
|
-
### Mevcut bileşen ile instance oluşturma
|
|
202
|
-
|
|
203
|
-
Tercihen `figma_instantiate_component` aracını kullan. `figma_execute` içinde:
|
|
204
|
-
|
|
205
163
|
```js
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
164
|
+
// Local component
|
|
165
|
+
const comp = figma.root.findOne(n => n.type === "COMPONENT" && n.name === "Button");
|
|
166
|
+
const instance = comp.createInstance();
|
|
167
|
+
|
|
168
|
+
// Variant seçimi
|
|
169
|
+
const set = figma.root.findOne(n => n.type === "COMPONENT_SET" && n.name === "Button");
|
|
170
|
+
const variant = set.children.find(c => c.name === "Size=Large, Type=Primary");
|
|
171
|
+
const inst = variant.createInstance();
|
|
212
172
|
```
|
|
213
173
|
|
|
214
|
-
|
|
174
|
+
## 5. Variable Bağlama
|
|
215
175
|
|
|
216
176
|
```js
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
);
|
|
220
|
-
const variant = componentSet.children.find(
|
|
221
|
-
c => c.name === "Size=Large, Type=Primary"
|
|
222
|
-
);
|
|
223
|
-
const instance = variant.createInstance();
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
## 5. Variable Bağlama Kalıpları
|
|
227
|
-
|
|
228
|
-
```js
|
|
229
|
-
const collections = await figma.variables.getLocalVariableCollectionsAsync();
|
|
230
|
-
const colorCollection = collections.find(c => c.name === "Colors");
|
|
231
|
-
const variables = await Promise.all(
|
|
232
|
-
colorCollection.variableIds.map(id =>
|
|
233
|
-
figma.variables.getVariableByIdAsync(id)
|
|
234
|
-
)
|
|
235
|
-
);
|
|
236
|
-
const primaryColor = variables.find(v => v.name === "primary/500");
|
|
237
|
-
|
|
238
|
-
// Fill'e bağla
|
|
177
|
+
const variable = await figma.variables.importVariableByKeyAsync("KEY");
|
|
178
|
+
// Fill bind
|
|
239
179
|
const fills = [...node.fills];
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
);
|
|
243
|
-
node.fills = [boundPaint]; // YENİ paint'i geri ata
|
|
180
|
+
node.fills = [figma.variables.setBoundVariableForPaint(fills[0], "color", variable)];
|
|
181
|
+
// Spacing bind
|
|
182
|
+
node.setBoundVariable("paddingLeft", variable);
|
|
244
183
|
```
|
|
245
184
|
|
|
246
|
-
## 6. Ek API Gotcha'lar
|
|
247
|
-
|
|
248
|
-
17. **`import` keyword yasağı.** Plugin sandbox'ta
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
await
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
185
|
+
## 6. Ek API Gotcha'lar
|
|
186
|
+
|
|
187
|
+
17. **`import` keyword yasağı.** Plugin sandbox'ta reserved word. `async function getVar(k)` kullan.
|
|
188
|
+
|
|
189
|
+
18. **`setEffectStyleIdAsync` zorunlu.** Sync `node.effectStyleId = id` hata verir.
|
|
190
|
+
|
|
191
|
+
19. **`setTextStyleIdAsync` kullan, fontSize binding YASAK:**
|
|
192
|
+
```js
|
|
193
|
+
const style = await figma.importStyleByKeyAsync("KEY");
|
|
194
|
+
await textNode.setTextStyleIdAsync(style.id);
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
20. **`setExplicitVariableModeForCollection` — string ID çalışmaz.** Library API chain ile collection OBJECT al:
|
|
198
|
+
```js
|
|
199
|
+
var colls = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
|
|
200
|
+
var sem = colls.find(c => c.name.indexOf("Semantic Colors") !== -1);
|
|
201
|
+
var vars = await figma.teamLibrary.getVariablesInLibraryCollectionAsync(sem.key);
|
|
202
|
+
var first = await figma.variables.importVariableByKeyAsync(vars[0].key);
|
|
203
|
+
var coll = await figma.variables.getVariableCollectionByIdAsync(first.variableCollectionId);
|
|
204
|
+
var darkMode = coll.modes.find(m => m.name === "Dark");
|
|
205
|
+
frame.setExplicitVariableModeForCollection(coll, darkMode.modeId);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
21. **Escaped quote dikkat.** `figma_execute` code'da `\"` yerine düz `"` kullan.
|
|
209
|
+
|
|
210
|
+
23. **Style Import Sessiz Fail.** `importStyleByKeyAsync` null/throws olabilir. Her zaman try-catch:
|
|
211
|
+
```js
|
|
212
|
+
let style = null;
|
|
213
|
+
try { style = await figma.importStyleByKeyAsync("KEY"); } catch(e) {}
|
|
214
|
+
if (style) {
|
|
215
|
+
await textNode.setTextStyleIdAsync(style.id);
|
|
216
|
+
await figma.loadFontAsync(textNode.fontName);
|
|
217
|
+
textNode.characters = "Metin";
|
|
218
|
+
} else {
|
|
219
|
+
await figma.loadFontAsync({ family: "Inter", style: "Regular" });
|
|
220
|
+
textNode.fontName = { family: "Inter", style: "Regular" };
|
|
221
|
+
textNode.characters = "Metin (fallback)";
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
**Fast Path:** roleMap hazırsa `setTextStyleIdAsync(roleMap[role].id)` direkt kullan, import atla (bkz. fmcp-screen-recipes Adım 1.6).
|
|
225
|
+
|
|
226
|
+
24. **Component Discovery Fallback.** `figma_search_assets` boş dönerse manuel instance scan:
|
|
227
|
+
```js
|
|
228
|
+
const instances = figma.currentPage.findAll(n => n.type === "INSTANCE");
|
|
229
|
+
const map = new Map();
|
|
230
|
+
for (const inst of instances) {
|
|
231
|
+
const main = await inst.getMainComponentAsync();
|
|
232
|
+
if (main && main.remote && main.key && !map.has(main.name))
|
|
233
|
+
map.set(main.name, { name: main.name, key: main.key });
|
|
234
|
+
}
|
|
235
|
+
return Array.from(map.values());
|
|
236
|
+
```
|
|
237
|
+
Sıra: (1) Cache → (2) `figma_search_assets` → (3) Manuel scan → (4) Key biliniyor → `importComponentByKeyAsync(key)` direkt.
|
|
238
|
+
|
|
239
|
+
25. **`figma_validate_screen` Timeout Fallback.** 3 seviyeli:
|
|
240
|
+
- **Seviye 1:** `figma_validate_screen(nodeId, minScore=80)` — timeout olursa:
|
|
241
|
+
- **Seviye 2:** Content Body wrapper'ı validate et (daha küçük tree), minScore=70
|
|
242
|
+
- **Seviye 3:** Manuel QA Checklist üret:
|
|
243
|
+
- [ ] Instance coverage ≥60%
|
|
244
|
+
- [ ] Rastgele 5 fill'de variable icon 🎨 var mı
|
|
245
|
+
- [ ] Rastgele 3 spacing variable-bound mu
|
|
246
|
+
- [ ] Auto-layout tüm frame'lerde aktif mi
|
|
247
|
+
- [ ] Dark mode renkleri doğru mu
|
|
248
|
+
|
|
249
|
+
26. **Component Property Discovery — Tek Execute.**
|
|
250
|
+
```js
|
|
251
|
+
const comp = await figma.importComponentByKeyAsync(key);
|
|
252
|
+
let set = comp.parent?.type === "COMPONENT_SET" ? comp.parent : comp;
|
|
253
|
+
const propDefs = set.componentPropertyDefinitions || {};
|
|
254
|
+
return {
|
|
255
|
+
componentName: comp.name,
|
|
256
|
+
propertyDefinitions: Object.entries(propDefs).map(([n, d]) => ({
|
|
257
|
+
name: n, type: d.type, defaultValue: d.defaultValue, variantOptions: d.variantOptions || []
|
|
258
|
+
}))
|
|
259
|
+
};
|
|
260
|
+
```
|
|
261
|
+
`figma_instantiate_component` timeout olursa: `figma_execute` içinde `importComponentByKeyAsync(key)` + `comp.createInstance()`.
|
|
262
|
+
|
|
263
|
+
**Text Style Discovery:** (1) Instance scan: `findAll(TEXT)` → `textStyleId` → `getStyleByIdAsync` (2) Boşsa `figma_search_assets` (3) Boşsa team library API (4) Fallback Inter + hardcoded size.
|
|
292
264
|
|
|
293
265
|
## 7. Hata Kurtarma
|
|
294
266
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
## 7. Doğrulama Adımları
|
|
305
|
-
|
|
306
|
-
Her yazma işleminden sonra:
|
|
307
|
-
|
|
308
|
-
1. `figma_capture_screenshot` ile görsel doğrulama
|
|
309
|
-
2. Gerekirse `figma_get_file_data` ile yapı kontrolü
|
|
310
|
-
3. Oluşturulan node ID'lerini sonraki çağrılarda referans olarak kullan
|
|
267
|
+
| Hata | Çözüm |
|
|
268
|
+
|---|---|
|
|
269
|
+
| `Cannot read property of undefined` | Node ID geçersiz / sayfa yüklenmemiş |
|
|
270
|
+
| `Font not loaded` | `loadFontAsync` eksik |
|
|
271
|
+
| `Font could not be loaded` | Weight yok → `pickStyle()` fallback (Rule 8a-1) |
|
|
272
|
+
| `Cannot set FILL before appendChild` | Rule 11 sırası |
|
|
273
|
+
| `Maximum call stack` | Küçük parçalara böl |
|
|
274
|
+
| `Resource links not supported` | Yanlış MCP (resmi) → F-MCP kullan |
|
|
311
275
|
|
|
312
|
-
##
|
|
276
|
+
## 8. Doğrulama
|
|
313
277
|
|
|
314
|
-
|
|
315
|
-
- **generate-figma-screen** — Ekran oluşturma iş akışı
|
|
316
|
-
- **generate-figma-library** — DS kütüphanesi inşa
|
|
317
|
-
- **apply-figma-design-system** — DS hizalama
|
|
318
|
-
- **fix-figma-design-system-finding** — Tek bulgu düzeltme
|
|
319
|
-
- **figjam-diagram-builder** — FigJam diyagram oluşturma
|
|
278
|
+
Her yazma sonrası: `figma_capture_screenshot` + gerekirse `figma_get_file_data`.
|
|
320
279
|
|
|
321
|
-
##
|
|
280
|
+
## Skill Koordinasyonu
|
|
322
281
|
|
|
323
|
-
-
|
|
324
|
-
-
|
|
325
|
-
-
|
|
282
|
+
- **fmcp-screen-orchestrator** — DS GATE, Fast Path routing
|
|
283
|
+
- **fmcp-screen-recipes** — Fast Path (Rule 25 validate, Rule 26 discovery referans alınır)
|
|
284
|
+
- **generate-figma-screen** — Tam workflow
|
|
285
|
+
- **generate-figma-library** / **apply-figma-design-system** / **fix-figma-design-system-finding** / **figjam-diagram-builder**
|