src/extractors/README.md
This module provides a flexible, single-pass system for extracting data from Figma design files. It allows you to compose different extractors based on your specific needs, making it perfect for different LLM use cases where you want to optimize context window usage.
The system is built in clean layers:
import { extractFromDesign, allExtractors, layoutAndText, contentOnly } from "figma-mcp/extractors";
// Extract everything (equivalent to current parseNode)
const fullData = extractFromDesign(nodes, allExtractors);
// Extract only layout + text for content planning
const layoutData = extractFromDesign(nodes, layoutAndText, {
maxDepth: 3,
});
// Extract only text content for copy audits
const textData = extractFromDesign(nodes, contentOnly, {
nodeFilter: (node) => node.type === "TEXT",
});
layoutExtractor - Layout properties (positioning, sizing, flex properties)textExtractor - Text content and typography stylesvisualsExtractor - Visual appearance (fills, strokes, effects, opacity, borders)componentExtractor - Component instance dataallExtractors - Everything (replicates current behavior)layoutAndText - Layout + text (good for content analysis)contentOnly - Text only (good for copy extraction)visualsOnly - Visual styles only (good for design systems)layoutOnly - Layout only (good for structure analysis)import type { ExtractorFn } from "figma-mcp/extractors";
// Custom extractor that identifies design system components
const designSystemExtractor: ExtractorFn = (node, result, context) => {
if (node.name.startsWith("DS/")) {
result.isDesignSystemComponent = true;
result.dsCategory = node.name.split("/")[1];
}
};
// Use it with other extractors
const data = extractFromDesign(nodes, [layoutExtractor, designSystemExtractor]);
// Limit traversal depth
const shallowData = extractFromDesign(nodes, allExtractors, {
maxDepth: 2,
});
// Filter to specific node types
const frameData = extractFromDesign(nodes, layoutAndText, {
nodeFilter: (node) => ["FRAME", "GROUP"].includes(node.type),
});
// Custom filtering logic
const buttonData = extractFromDesign(nodes, allExtractors, {
nodeFilter: (node) => node.name.toLowerCase().includes("button"),
});
The flexible system is designed for different LLM use cases:
// For large designs - extract incrementally
function extractForLLM(nodes, phase) {
switch (phase) {
case "structure":
return extractFromDesign(nodes, layoutOnly, { maxDepth: 3 });
case "content":
return extractFromDesign(nodes, contentOnly);
case "styling":
return extractFromDesign(nodes, visualsOnly, { maxDepth: 2 });
case "full":
return extractFromDesign(nodes, allExtractors);
}
}
The new system works alongside the current parseNode function. You can:
The allExtractors combination provides equivalent functionality to the current parseNode behavior.