Skip to main content
Glama
built-in.ts4.72 kB
import type { Node as FigmaDocumentNode } from "@figma/rest-api-spec"; import type { ExtractorFn } from "./types.js"; import { buildSimplifiedLayout } from "~/transformers/layout.js"; import { buildSimplifiedStrokes, parsePaint } from "~/transformers/style.js"; import { buildSimplifiedEffects } from "~/transformers/effects.js"; import { extractNodeText, extractTextStyle, hasTextStyle, isTextNode, } from "~/transformers/text.js"; import { hasValue, isRectangleCornerRadii } from "~/utils/identity.js"; import { generateVarId } from "~/utils/common.js"; /** * Helper function to find or create a global variable. */ function findOrCreateVar(globalVars: any, value: any, prefix: string): string { // Check if the same value already exists const [existingVarId] = Object.entries(globalVars.styles).find( ([_, existingValue]) => JSON.stringify(existingValue) === JSON.stringify(value), ) ?? []; if (existingVarId) { return existingVarId; } // Create a new variable if it doesn't exist const varId = generateVarId(prefix); globalVars.styles[varId] = value; return varId; } /** * Extracts layout-related properties from a node. */ export const layoutExtractor: ExtractorFn = (node, result, context) => { const layout = buildSimplifiedLayout(node, context.parent); if (Object.keys(layout).length > 1) { result.layout = findOrCreateVar(context.globalVars, layout, "layout"); } }; /** * Extracts text content and text styling from a node. */ export const textExtractor: ExtractorFn = (node, result, context) => { // Extract text content if (isTextNode(node)) { result.text = extractNodeText(node); } // Extract text style if (hasTextStyle(node)) { const textStyle = extractTextStyle(node); result.textStyle = findOrCreateVar(context.globalVars, textStyle, "style"); } }; /** * Extracts visual appearance properties (fills, strokes, effects, opacity, border radius). */ export const visualsExtractor: ExtractorFn = (node, result, context) => { // Check if node has children to determine CSS properties const hasChildren = hasValue("children", node) && Array.isArray(node.children) && node.children.length > 0; // fills if (hasValue("fills", node) && Array.isArray(node.fills) && node.fills.length) { const fills = node.fills.map((fill) => parsePaint(fill, hasChildren)).reverse(); result.fills = findOrCreateVar(context.globalVars, fills, "fill"); } // strokes const strokes = buildSimplifiedStrokes(node, hasChildren); if (strokes.colors.length) { result.strokes = findOrCreateVar(context.globalVars, strokes, "stroke"); } // effects const effects = buildSimplifiedEffects(node); if (Object.keys(effects).length) { result.effects = findOrCreateVar(context.globalVars, effects, "effect"); } // opacity if (hasValue("opacity", node) && typeof node.opacity === "number" && node.opacity !== 1) { result.opacity = node.opacity; } // border radius if (hasValue("cornerRadius", node) && typeof node.cornerRadius === "number") { result.borderRadius = `${node.cornerRadius}px`; } if (hasValue("rectangleCornerRadii", node, isRectangleCornerRadii)) { result.borderRadius = `${node.rectangleCornerRadii[0]}px ${node.rectangleCornerRadii[1]}px ${node.rectangleCornerRadii[2]}px ${node.rectangleCornerRadii[3]}px`; } }; /** * Extracts component-related properties from INSTANCE nodes. */ export const componentExtractor: ExtractorFn = (node, result, context) => { if (node.type === "INSTANCE") { if (hasValue("componentId", node)) { result.componentId = node.componentId; } // Add specific properties for instances of components if (hasValue("componentProperties", node)) { result.componentProperties = Object.entries(node.componentProperties ?? {}).map( ([name, { value, type }]) => ({ name, value: value.toString(), type, }), ); } } }; // -------------------- CONVENIENCE COMBINATIONS -------------------- /** * All extractors - replicates the current parseNode behavior. */ export const allExtractors = [layoutExtractor, textExtractor, visualsExtractor, componentExtractor]; /** * Layout and text only - useful for content analysis and layout planning. */ export const layoutAndText = [layoutExtractor, textExtractor]; /** * Text content only - useful for content audits and copy extraction. */ export const contentOnly = [textExtractor]; /** * Visuals only - useful for design system analysis and style extraction. */ export const visualsOnly = [visualsExtractor]; /** * Layout only - useful for structure analysis. */ export const layoutOnly = [layoutExtractor];

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/violet4795/figma-developer-mcp-ncds'

If you have feedback or need assistance with the MCP directory API, please join our Discord server