@su-record/vibe 2.9.1 → 2.9.3
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/CLAUDE.md +31 -10
- package/README.ko.md +90 -25
- package/README.md +139 -25
- package/agents/teams/debug-team.md +70 -0
- package/agents/teams/dev-team.md +88 -0
- package/agents/teams/docs-team.md +80 -0
- package/agents/teams/figma/figma-analyst.md +52 -0
- package/agents/teams/figma/figma-architect.md +112 -0
- package/agents/teams/figma/figma-auditor.md +82 -0
- package/agents/teams/figma/figma-builder.md +100 -0
- package/agents/teams/figma-team.md +85 -0
- package/agents/teams/fullstack-team.md +83 -0
- package/agents/teams/lite-team.md +69 -0
- package/agents/teams/migration-team.md +78 -0
- package/agents/teams/refactor-team.md +94 -0
- package/agents/teams/research-team.md +86 -0
- package/agents/teams/review-debate-team.md +125 -0
- package/agents/teams/security-team.md +81 -0
- package/commands/vibe.analyze.md +324 -170
- package/commands/vibe.figma.md +549 -34
- package/commands/vibe.harness.md +177 -0
- package/commands/vibe.review.md +1 -63
- package/commands/vibe.run.md +52 -403
- package/commands/vibe.scaffold.md +195 -0
- package/commands/vibe.spec.md +373 -1003
- package/commands/vibe.trace.md +17 -0
- package/commands/vibe.verify.md +19 -10
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +29 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +4 -2
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/postinstall/constants.d.ts +1 -1
- package/dist/cli/postinstall/constants.d.ts.map +1 -1
- package/dist/cli/postinstall/constants.js +6 -1
- package/dist/cli/postinstall/constants.js.map +1 -1
- package/dist/cli/setup/ProjectSetup.d.ts +12 -1
- package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
- package/dist/cli/setup/ProjectSetup.js +259 -72
- package/dist/cli/setup/ProjectSetup.js.map +1 -1
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +1 -1
- package/dist/cli/setup.js.map +1 -1
- package/hooks/scripts/figma-guard.js +220 -0
- package/hooks/scripts/figma-refine.js +315 -0
- package/hooks/scripts/figma-to-scss.js +394 -0
- package/hooks/scripts/figma-validate.js +353 -0
- package/package.json +1 -1
- package/skills/arch-guard/SKILL.md +1 -1
- package/skills/capability-loop/SKILL.md +106 -2
- package/skills/chub-usage/SKILL.md +43 -43
- package/skills/claude-md-guide/SKILL.md +175 -175
- package/skills/design-teach/SKILL.md +33 -33
- package/skills/devlog/SKILL.md +38 -38
- package/skills/event-comms/SKILL.md +23 -13
- package/skills/event-ops/SKILL.md +28 -19
- package/skills/event-planning/SKILL.md +13 -1
- package/skills/priority-todos/SKILL.md +1 -1
- package/skills/vibe.figma/SKILL.md +263 -115
- package/skills/vibe.figma/templates/component-spec.md +168 -0
- package/skills/vibe.figma.convert/SKILL.md +131 -84
- package/skills/vibe.figma.convert/rubrics/conversion-rules.md +12 -0
- package/skills/vibe.figma.extract/SKILL.md +148 -108
- package/skills/vibe.figma.extract/rubrics/image-rules.md +15 -3
- package/skills/vibe.interview/SKILL.md +358 -0
- package/skills/vibe.interview/checklists/api.md +101 -0
- package/skills/vibe.interview/checklists/feature.md +88 -0
- package/skills/vibe.interview/checklists/library.md +95 -0
- package/skills/vibe.interview/checklists/mobile.md +89 -0
- package/skills/vibe.interview/checklists/webapp.md +97 -0
- package/skills/vibe.interview/checklists/website.md +99 -0
- package/skills/vibe.plan/SKILL.md +216 -0
- package/skills/vibe.spec/SKILL.md +1155 -0
- package/{commands/vibe.spec.review.md → skills/vibe.spec.review/SKILL.md} +272 -155
- package/vibe/templates/claudemd-template.md +74 -0
- package/vibe/templates/constitution-template.md +15 -0
- package/vibe/templates/plan-template.md +194 -0
|
@@ -1,179 +1,219 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: vibe.figma.extract
|
|
3
|
-
description:
|
|
3
|
+
description: Acquire code generation data via Figma REST API — tree (primary), images, screenshots (for validation)
|
|
4
4
|
triggers: []
|
|
5
5
|
tier: standard
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# vibe.figma.extract —
|
|
8
|
+
# vibe.figma.extract — Acquire Code Generation Data
|
|
9
9
|
|
|
10
|
-
Figma REST API(`src/infra/lib/figma/`)
|
|
10
|
+
Uses the Figma REST API (`src/infra/lib/figma/`) to extract **all data needed for structural code generation**.
|
|
11
11
|
|
|
12
12
|
```
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
Extraction priority:
|
|
14
|
+
1st: Node tree + CSS (PRIMARY source for code generation)
|
|
15
|
+
2nd: Image assets (fill images + item node rendering)
|
|
16
|
+
3rd: Screenshots (for Phase 6 visual validation — not used for code generation)
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
## 1.
|
|
21
|
+
## 1. Node Tree + CSS — Source of Truth for Code Generation
|
|
22
22
|
|
|
23
23
|
```
|
|
24
24
|
Bash:
|
|
25
|
-
node "
|
|
25
|
+
node "{{VIBE_PATH}}/hooks/scripts/figma-extract.js" tree {fileKey} {nodeId}
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Returns (FigmaNode JSON):
|
|
28
28
|
{
|
|
29
29
|
nodeId, name, type, size: { width, height },
|
|
30
30
|
css: { display, flexDirection, gap, ... },
|
|
31
|
-
text: "
|
|
32
|
-
imageRef: "abc123" (
|
|
31
|
+
text: "text content" (TEXT nodes only),
|
|
32
|
+
imageRef: "abc123" (image fill),
|
|
33
33
|
imageScaleMode: "FILL" (FILL/FIT/CROP/TILE),
|
|
34
34
|
layoutSizingH: "HUG" (FIXED/HUG/FILL),
|
|
35
35
|
layoutSizingV: "FILL",
|
|
36
|
-
fills: [...] (2
|
|
37
|
-
isMask: true (
|
|
36
|
+
fills: [...] (only when 2 or more),
|
|
37
|
+
isMask: true (mask nodes only),
|
|
38
38
|
children: [...]
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
→ /tmp/{feature}/tree.json
|
|
41
|
+
→ Save to /tmp/{feature}/tree.json
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
### Figma
|
|
44
|
+
### Figma Property → CSS Direct Mapping Table
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
Properties automatically converted by the tree extraction tool. **These values map directly to SCSS:**
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
**Layout:**
|
|
49
49
|
|
|
50
|
-
| Figma
|
|
50
|
+
| Figma Property | CSS | vw conversion |
|
|
51
51
|
|-----------|-----|---------|
|
|
52
|
-
| `layoutMode=VERTICAL` | `display:flex; flex-direction:column` |
|
|
53
|
-
| `layoutMode=HORIZONTAL` | `display:flex; flex-direction:row` |
|
|
54
|
-
| `primaryAxisAlignItems` | `justify-content` |
|
|
55
|
-
| `counterAxisAlignItems` | `align-items` |
|
|
56
|
-
| `itemSpacing` | `gap` |
|
|
57
|
-
| `layoutGrow=1` | `flex-grow: 1` |
|
|
58
|
-
| `padding*` | `padding` |
|
|
59
|
-
| `absoluteBoundingBox.width/height` | `width/height` |
|
|
60
|
-
| `layoutPositioning=ABSOLUTE` | `position: absolute` + `top/left` (
|
|
61
|
-
| `layoutSizingHorizontal=HUG` | width
|
|
62
|
-
| `layoutSizingHorizontal=FILL` |
|
|
63
|
-
| `layoutSizingVertical=HUG` | height
|
|
64
|
-
| `layoutSizingVertical=FILL` |
|
|
65
|
-
| `clipsContent` | `overflow: hidden` |
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
| Figma
|
|
52
|
+
| `layoutMode=VERTICAL` | `display:flex; flex-direction:column` | No |
|
|
53
|
+
| `layoutMode=HORIZONTAL` | `display:flex; flex-direction:row` | No |
|
|
54
|
+
| `primaryAxisAlignItems` | `justify-content` | No |
|
|
55
|
+
| `counterAxisAlignItems` | `align-items` | No |
|
|
56
|
+
| `itemSpacing` | `gap` | Yes |
|
|
57
|
+
| `layoutGrow=1` | `flex-grow: 1` | No |
|
|
58
|
+
| `padding*` | `padding` | Yes |
|
|
59
|
+
| `absoluteBoundingBox.width/height` | `width/height` | Yes |
|
|
60
|
+
| `layoutPositioning=ABSOLUTE` | `position: absolute` + `top/left` (relative to parent) | Yes |
|
|
61
|
+
| `layoutSizingHorizontal=HUG` | remove width (auto) | — |
|
|
62
|
+
| `layoutSizingHorizontal=FILL` | metadata `layoutSizingH` (converter decides flex:1/100%) | — |
|
|
63
|
+
| `layoutSizingVertical=HUG` | remove height (auto) | — |
|
|
64
|
+
| `layoutSizingVertical=FILL` | metadata `layoutSizingV` (converter decides) | — |
|
|
65
|
+
| `clipsContent` | `overflow: hidden` | No |
|
|
66
|
+
|
|
67
|
+
**Visual:**
|
|
68
|
+
|
|
69
|
+
| Figma Property | CSS | vw conversion |
|
|
70
70
|
|-----------|-----|---------|
|
|
71
|
-
| `fills[].SOLID` | `background-color` |
|
|
71
|
+
| `fills[].SOLID` | `background-color` | No |
|
|
72
72
|
| `fills[].IMAGE` | `imageRef` + `imageScaleMode` (FILL/FIT/CROP/TILE) | — |
|
|
73
|
-
| `fills[].GRADIENT_LINEAR` | `background-image: linear-gradient(...)` |
|
|
74
|
-
| `fills[].GRADIENT_RADIAL` | `background-image: radial-gradient(...)` |
|
|
75
|
-
| `fills[] (2
|
|
76
|
-
| `fills[].blendMode` | `background-blend-mode` |
|
|
77
|
-
| `fills[].filters.saturation` | `filter: grayscale(X%)` / `saturate(X%)` |
|
|
78
|
-
| `fills[].color` (TEXT) | `color` |
|
|
79
|
-
| `strokes[] + strokeAlign=INSIDE` | `border` + `box-sizing: border-box` |
|
|
80
|
-
| `strokes[] + strokeAlign=OUTSIDE` | `outline` |
|
|
81
|
-
| `individualStrokeWeights` | `border-top/right/bottom/left`
|
|
82
|
-
| `strokeDashes` | `border-style: dashed` |
|
|
83
|
-
| `effects[].DROP_SHADOW` | `box-shadow` |
|
|
84
|
-
| `effects[].INNER_SHADOW` | `box-shadow` (inset) |
|
|
85
|
-
| `effects[].LAYER_BLUR` | `filter: blur()` (
|
|
86
|
-
| `effects[].BACKGROUND_BLUR` | `backdrop-filter: blur()` |
|
|
87
|
-
| `cornerRadius` | `border-radius` |
|
|
88
|
-
| `opacity` | `opacity` |
|
|
89
|
-
| `rotation` | `transform: rotate(Xdeg)` |
|
|
90
|
-
| `blendMode` (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
| Figma
|
|
73
|
+
| `fills[].GRADIENT_LINEAR` | `background-image: linear-gradient(...)` | No |
|
|
74
|
+
| `fills[].GRADIENT_RADIAL` | `background-image: radial-gradient(...)` | No |
|
|
75
|
+
| `fills[] (2 or more)` | `fills` array (type, color, imageRef, gradient, blendMode, filters) | — |
|
|
76
|
+
| `fills[].blendMode` | `background-blend-mode` | No |
|
|
77
|
+
| `fills[].filters.saturation` | `filter: grayscale(X%)` / `saturate(X%)` | No |
|
|
78
|
+
| `fills[].color` (TEXT) | `color` | No |
|
|
79
|
+
| `strokes[] + strokeAlign=INSIDE` | `border` + `box-sizing: border-box` | Yes (width only) |
|
|
80
|
+
| `strokes[] + strokeAlign=OUTSIDE` | `outline` | Yes (width only) |
|
|
81
|
+
| `individualStrokeWeights` | `border-top/right/bottom/left` individually | Yes (width only) |
|
|
82
|
+
| `strokeDashes` | `border-style: dashed` | No |
|
|
83
|
+
| `effects[].DROP_SHADOW` | `box-shadow` | Yes (px only) |
|
|
84
|
+
| `effects[].INNER_SHADOW` | `box-shadow` (inset) | Yes (px only) |
|
|
85
|
+
| `effects[].LAYER_BLUR` | `filter: blur()` (accumulated) | Yes |
|
|
86
|
+
| `effects[].BACKGROUND_BLUR` | `backdrop-filter: blur()` | Yes |
|
|
87
|
+
| `cornerRadius` | `border-radius` | Yes |
|
|
88
|
+
| `opacity` | `opacity` | No |
|
|
89
|
+
| `rotation` | `transform: rotate(Xdeg)` | No |
|
|
90
|
+
| `blendMode` (node level) | `mix-blend-mode` | No |
|
|
91
|
+
|
|
92
|
+
**Text:**
|
|
93
|
+
|
|
94
|
+
| Figma Property | CSS | vw conversion |
|
|
95
95
|
|-----------|-----|---------|
|
|
96
|
-
| `style.fontFamily` | `font-family` |
|
|
97
|
-
| `style.fontSize` | `font-size` |
|
|
98
|
-
| `style.fontWeight` | `font-weight` |
|
|
99
|
-
| `style.lineHeightPx` | `line-height` |
|
|
100
|
-
| `style.letterSpacing` | `letter-spacing` |
|
|
101
|
-
| `style.textAlignHorizontal` | `text-align` |
|
|
102
|
-
| `style.textCase` | `text-transform` |
|
|
103
|
-
| `style.textTruncation` | `overflow: hidden; text-overflow: ellipsis` |
|
|
104
|
-
| `style.paragraphSpacing` | `margin-bottom` |
|
|
105
|
-
| `characters` |
|
|
96
|
+
| `style.fontFamily` | `font-family` | No |
|
|
97
|
+
| `style.fontSize` | `font-size` | Yes |
|
|
98
|
+
| `style.fontWeight` | `font-weight` | No |
|
|
99
|
+
| `style.lineHeightPx` | `line-height` | No |
|
|
100
|
+
| `style.letterSpacing` | `letter-spacing` | Yes |
|
|
101
|
+
| `style.textAlignHorizontal` | `text-align` | No |
|
|
102
|
+
| `style.textCase` | `text-transform` | No |
|
|
103
|
+
| `style.textTruncation` | `overflow: hidden; text-overflow: ellipsis` | No |
|
|
104
|
+
| `style.paragraphSpacing` | `margin-bottom` | Yes |
|
|
105
|
+
| `characters` | text content | — |
|
|
106
106
|
|
|
107
107
|
---
|
|
108
108
|
|
|
109
|
-
## 2.
|
|
109
|
+
## 2. Image Assets — Node Rendering Based
|
|
110
110
|
|
|
111
111
|
```
|
|
112
|
-
|
|
113
|
-
→
|
|
114
|
-
→
|
|
112
|
+
Do NOT download imageRef individually
|
|
113
|
+
→ If a texture fill is shared, the original texture (22.7MB) will be downloaded
|
|
114
|
+
→ Rendering the node produces the final result as applied to that node (364KB)
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
All images must be rendered as nodes via the Figma screenshot API
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
### 2-1. BG
|
|
119
|
+
### 2-1. BG Frame Rendering
|
|
120
120
|
|
|
121
121
|
```
|
|
122
|
-
BG
|
|
123
|
-
- name
|
|
124
|
-
-
|
|
122
|
+
BG frame identification criteria:
|
|
123
|
+
- name contains "BG" or "bg"
|
|
124
|
+
- OR same size as parent (±10%) + 3 or more child images
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
node "
|
|
126
|
+
Rendering:
|
|
127
|
+
node "{{VIBE_PATH}}/hooks/scripts/figma-extract.js" screenshot {fileKey} {bg.nodeId} --out=/tmp/{feature}/bg/{section}-bg.webp
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
-
### 2-2.
|
|
130
|
+
### 2-2. Content Node Rendering
|
|
131
131
|
|
|
132
132
|
```
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
133
|
+
Targets (identified from tree.json):
|
|
134
|
+
- Icons (VECTOR/GROUP size ≤ 64px)
|
|
135
|
+
- Item/reward thumbnails (name contains "item", "reward", "token", "coin")
|
|
136
|
+
- Vector text GROUPs (3 or more VECTORs under parent, each <60px)
|
|
137
|
+
- Design text (any of the following):
|
|
138
|
+
· TEXT node with 2 or more fills (gradient + solid overlap)
|
|
139
|
+
· TEXT node has effects (DROP_SHADOW, stroke)
|
|
140
|
+
· TEXT node fills contain GRADIENT type
|
|
141
|
+
· fontFamily not in project web fonts
|
|
142
|
+
→ Must be included in rendering targets
|
|
143
|
+
- Decorative panels (wooden signs, metal plates, and other textured backgrounds)
|
|
144
|
+
→ Render the same way as BG frames
|
|
137
145
|
|
|
138
|
-
|
|
139
|
-
node "
|
|
146
|
+
Rendering:
|
|
147
|
+
node "{{VIBE_PATH}}/hooks/scripts/figma-extract.js" screenshot {fileKey} {node.nodeId} --out=/tmp/{feature}/content/{name}.webp
|
|
140
148
|
```
|
|
141
149
|
|
|
142
|
-
### 2-3. imageRef
|
|
150
|
+
### 2-3. imageRef Download (Fallback)
|
|
143
151
|
|
|
144
152
|
```
|
|
145
|
-
|
|
146
|
-
|
|
153
|
+
Only when node rendering is not possible (API failure, DOCUMENT level):
|
|
154
|
+
File size exceeds 5MB → texture fill warning
|
|
147
155
|
```
|
|
148
156
|
|
|
149
157
|
---
|
|
150
158
|
|
|
151
|
-
## 3.
|
|
159
|
+
## 3. Screenshots — Reference for Phase 6 Validation
|
|
152
160
|
|
|
153
161
|
```
|
|
154
|
-
|
|
162
|
+
Not used for code generation.
|
|
155
163
|
|
|
156
|
-
|
|
157
|
-
|
|
164
|
+
Full: screenshot → /tmp/{feature}/full-screenshot.webp
|
|
165
|
+
Per section: each 1-depth child → /tmp/{feature}/sections/{name}.webp
|
|
158
166
|
```
|
|
159
167
|
|
|
160
168
|
---
|
|
161
169
|
|
|
162
|
-
## 4.
|
|
170
|
+
## 4. Extracted Data Summary
|
|
163
171
|
|
|
164
172
|
```
|
|
165
173
|
/tmp/{feature}/
|
|
166
|
-
├── tree.json ← PRIMARY
|
|
167
|
-
├── bg/ ← BG
|
|
168
|
-
├── content/ ←
|
|
169
|
-
├── full-screenshot.webp ←
|
|
170
|
-
└── sections/ ←
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
|
174
|
+
├── tree.json ← PRIMARY source
|
|
175
|
+
├── bg/ ← BG frame rendering
|
|
176
|
+
├── content/ ← Content node rendering
|
|
177
|
+
├── full-screenshot.webp ← For validation
|
|
178
|
+
└── sections/ ← Per-section validation
|
|
179
|
+
|
|
180
|
+
Image classification summary:
|
|
181
|
+
| Category | Handling |
|
|
174
182
|
|------|------|
|
|
175
|
-
| BG
|
|
176
|
-
|
|
|
177
|
-
|
|
|
178
|
-
|
|
|
183
|
+
| BG frames | Frame rendering → bg/ |
|
|
184
|
+
| Design text | Node rendering → content/ |
|
|
185
|
+
| Vector text | GROUP rendering → content/ |
|
|
186
|
+
| Content | Node rendering → content/ |
|
|
187
|
+
| Decorative panels | Frame rendering → content/ |
|
|
188
|
+
| Decorations | Included in BG rendering |
|
|
179
189
|
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 5. Extraction Completion Validation (Required Before Entering Phase 3)
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
If any item is missing → re-extract (do NOT proceed to Phase 3)
|
|
197
|
+
|
|
198
|
+
1. tree.json exists + root node children > 0
|
|
199
|
+
2. BG for each section → file exists in bg/
|
|
200
|
+
3. Design text check:
|
|
201
|
+
Traverse tree.json → generate list of TEXT nodes with 2 or more fills or effects
|
|
202
|
+
→ All such nodes must have rendering files in content/
|
|
203
|
+
4. Vector text check:
|
|
204
|
+
GROUP with 3 or more VECTORs → rendering file exists in content/
|
|
205
|
+
5. Per-section validation screenshots → files exist in sections/
|
|
206
|
+
6. File naming convention: all kebab-case (no hash filenames)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Error Recovery
|
|
212
|
+
|
|
213
|
+
| Failure | Recovery |
|
|
214
|
+
|---------|----------|
|
|
215
|
+
| Figma API 401 (unauthorized) | Prompt user to set FIGMA_ACCESS_TOKEN in environment or ~/.vibe/config.json |
|
|
216
|
+
| Figma API 404 (file not found) | Verify fileKey extracted from URL. Check if file is shared/accessible. |
|
|
217
|
+
| Figma API 429 (rate limit) | Wait 60s, retry with reduced node scope (single page instead of full file) |
|
|
218
|
+
| API timeout on large file | Split request by page — fetch one page at a time via nodeId parameter |
|
|
219
|
+
| Screenshot download failure | Skip screenshot, proceed with tree.json only (mark visual verification as manual) |
|
|
@@ -82,17 +82,29 @@ BG 프레임 = 다음 중 하나:
|
|
|
82
82
|
- 웹폰트 없는 장식 타이틀 ("MISSION 01" 등)
|
|
83
83
|
- VECTOR 타입으로 분해된 글자 → GROUP 렌더링
|
|
84
84
|
|
|
85
|
-
2.
|
|
85
|
+
2. ⛔ 디자인 텍스트 (NEW — 그래디언트/스트로크/다중 효과 텍스트):
|
|
86
|
+
- TEXT 노드의 fills 2개 이상 (그래디언트+솔리드 중첩)
|
|
87
|
+
- TEXT 노드에 effects 있음 (DROP_SHADOW, stroke)
|
|
88
|
+
- TEXT 노드의 fills에 GRADIENT 타입 포함
|
|
89
|
+
- → 해당 TEXT 노드(또는 감싸는 GROUP)를 통째 렌더링
|
|
90
|
+
- → content/{section}-title.webp 등으로 저장
|
|
91
|
+
- ❌ CSS text-shadow/gradient로 근사치 구현 금지
|
|
92
|
+
|
|
93
|
+
3. 합성 배경 (BG 프레임):
|
|
86
94
|
- 눈, 나무, 파티클 등 장식 레이어 합성물
|
|
87
95
|
- 텍스트 미포함 확인 필수
|
|
88
96
|
|
|
89
|
-
|
|
97
|
+
4. 래스터 이미지 에셋:
|
|
90
98
|
- 게임 아이템 썸네일, 코인 아이콘 등
|
|
91
99
|
- imageRef가 있는 개별 RECTANGLE/노드
|
|
92
100
|
|
|
93
|
-
|
|
101
|
+
5. 복잡한 벡터 그래픽:
|
|
94
102
|
- CSS로 재현 불가능한 일러스트/아이콘
|
|
95
103
|
- VECTOR/GROUP 조합의 복잡한 그래픽
|
|
104
|
+
|
|
105
|
+
6. 장식 패널 배경 (목재 간판, 금속 플레이트 등):
|
|
106
|
+
- CSS로 재현 불가능한 텍스처/질감 배경
|
|
107
|
+
- → BG 프레임과 동일하게 렌더링 → background-image로 적용
|
|
96
108
|
```
|
|
97
109
|
|
|
98
110
|
## Format
|