/**
* Orchestrator — composes all transformers to simplify Figma nodes.
*/
import {isVisible, stripMetadata, type FigmaNode} from './filter.js';
import {fillsToCSS} from './color.js';
import {extractLayout} from './layout.js';
import {extractText} from './text.js';
import {extractEffects} from './effects.js';
export interface SimplifiedNode {
id: string;
name: string;
type: string;
layout?: ReturnType<typeof extractLayout>;
text?: ReturnType<typeof extractText>;
effects?: ReturnType<typeof extractEffects>;
background?: string;
borderRadius?: string;
dimensions?: {width: number; height: number};
children?: SimplifiedNode[];
}
/**
* Simplify a Figma node tree into a clean structure with CSS-like properties.
* Filters invisible nodes, strips metadata, and transforms properties.
*
* @param node - Raw Figma API node
* @param depth - Current recursion depth
* @param maxDepth - Maximum depth to recurse (default 3)
*/
export function simplifyNode(node: FigmaNode, depth = 0, maxDepth = 3): SimplifiedNode | null {
if (!isVisible(node)) return null;
const cleaned = stripMetadata(node);
const simplified: SimplifiedNode = {
id: cleaned.id ?? '',
name: cleaned.name ?? '',
type: cleaned.type ?? 'UNKNOWN',
};
// Layout (auto-layout → flexbox)
const layout = extractLayout(cleaned);
if (layout) simplified.layout = layout;
// Text content + typography
const text = extractText(cleaned);
if (text) simplified.text = text;
// Effects (shadows, blurs)
if (cleaned.effects?.length) {
const effects = extractEffects(cleaned.effects);
if (effects) simplified.effects = effects;
}
// Background color/gradient
if (cleaned.fills?.length) {
const bg = fillsToCSS(cleaned.fills);
if (bg) simplified.background = bg;
}
// Border radius
if (cleaned.cornerRadius && cleaned.cornerRadius > 0) {
simplified.borderRadius = `${cleaned.cornerRadius}px`;
} else if (cleaned.rectangleCornerRadii) {
const [tl, tr, br, bl] = cleaned.rectangleCornerRadii;
if (tl > 0 || tr > 0 || br > 0 || bl > 0) {
simplified.borderRadius = `${tl}px ${tr}px ${br}px ${bl}px`;
}
}
// Dimensions from bounding box
if (cleaned.absoluteBoundingBox) {
const {width, height} = cleaned.absoluteBoundingBox;
simplified.dimensions = {width, height};
}
// Recurse into children
if (cleaned.children?.length && depth < maxDepth) {
const children: SimplifiedNode[] = [];
for (const child of cleaned.children) {
const simplifiedChild = simplifyNode(child, depth + 1, maxDepth);
if (simplifiedChild) children.push(simplifiedChild);
}
if (children.length) simplified.children = children;
}
return simplified;
}
export {isVisible, stripMetadata} from './filter.js';
export {colorToCSS, fillsToCSS} from './color.js';
export {extractLayout} from './layout.js';
export {extractText} from './text.js';
export {extractEffects} from './effects.js';