|
1 | | -import type { ExtractorFn, GlobalVars, StyleTypes, TraversalContext } from "./types.js"; |
| 1 | +import type { |
| 2 | + ExtractorFn, |
| 3 | + GlobalVars, |
| 4 | + StyleTypes, |
| 5 | + TraversalContext, |
| 6 | + SimplifiedNode, |
| 7 | +} from "./types.js"; |
2 | 8 | import { buildSimplifiedLayout } from "~/transformers/layout.js"; |
3 | 9 | import { buildSimplifiedStrokes, parsePaint } from "~/transformers/style.js"; |
4 | 10 | import { buildSimplifiedEffects } from "~/transformers/effects.js"; |
@@ -196,3 +202,52 @@ export const visualsOnly = [visualsExtractor]; |
196 | 202 | * Layout only - useful for structure analysis. |
197 | 203 | */ |
198 | 204 | export const layoutOnly = [layoutExtractor]; |
| 205 | + |
| 206 | +// -------------------- AFTER CHILDREN HELPERS -------------------- |
| 207 | + |
| 208 | +/** |
| 209 | + * Node types that can be exported as SVG images. |
| 210 | + * When a FRAME, GROUP, or INSTANCE contains only these types, we can collapse it to IMAGE-SVG. |
| 211 | + * Note: FRAME/GROUP/INSTANCE are NOT included here—they're only eligible if collapsed to IMAGE-SVG. |
| 212 | + */ |
| 213 | +export const SVG_ELIGIBLE_TYPES = new Set([ |
| 214 | + "IMAGE-SVG", // VECTOR nodes are converted to IMAGE-SVG, or containers that were collapsed |
| 215 | + "STAR", |
| 216 | + "LINE", |
| 217 | + "ELLIPSE", |
| 218 | + "REGULAR_POLYGON", |
| 219 | + "RECTANGLE", |
| 220 | +]); |
| 221 | + |
| 222 | +/** |
| 223 | + * afterChildren callback that collapses SVG-heavy containers to IMAGE-SVG. |
| 224 | + * |
| 225 | + * If a FRAME, GROUP, or INSTANCE contains only SVG-eligible children, the parent |
| 226 | + * is marked as IMAGE-SVG and children are omitted, reducing payload size. |
| 227 | + * |
| 228 | + * @param node - Original Figma node |
| 229 | + * @param result - SimplifiedNode being built |
| 230 | + * @param children - Processed children |
| 231 | + * @returns Children to include (empty array if collapsed) |
| 232 | + */ |
| 233 | +export function collapseSvgContainers( |
| 234 | + node: FigmaDocumentNode, |
| 235 | + result: SimplifiedNode, |
| 236 | + children: SimplifiedNode[], |
| 237 | +): SimplifiedNode[] { |
| 238 | + const allChildrenAreSvgEligible = children.every((child) => |
| 239 | + SVG_ELIGIBLE_TYPES.has(child.type), |
| 240 | + ); |
| 241 | + |
| 242 | + if ( |
| 243 | + (node.type === "FRAME" || node.type === "GROUP" || node.type === "INSTANCE") && |
| 244 | + allChildrenAreSvgEligible |
| 245 | + ) { |
| 246 | + // Collapse to IMAGE-SVG and omit children |
| 247 | + result.type = "IMAGE-SVG"; |
| 248 | + return []; |
| 249 | + } |
| 250 | + |
| 251 | + // Include all children normally |
| 252 | + return children; |
| 253 | +} |
0 commit comments