@mcp-consultant-tools/figma 1.0.0

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.
Files changed (61) hide show
  1. package/build/FigmaService.d.ts +47 -0
  2. package/build/FigmaService.d.ts.map +1 -0
  3. package/build/FigmaService.js +108 -0
  4. package/build/FigmaService.js.map +1 -0
  5. package/build/figma/extractors/built-in.d.ts +57 -0
  6. package/build/figma/extractors/built-in.d.ts.map +1 -0
  7. package/build/figma/extractors/built-in.js +206 -0
  8. package/build/figma/extractors/built-in.js.map +1 -0
  9. package/build/figma/extractors/design-extractor.d.ts +7 -0
  10. package/build/figma/extractors/design-extractor.d.ts.map +1 -0
  11. package/build/figma/extractors/design-extractor.js +66 -0
  12. package/build/figma/extractors/design-extractor.js.map +1 -0
  13. package/build/figma/extractors/index.d.ts +5 -0
  14. package/build/figma/extractors/index.d.ts.map +1 -0
  15. package/build/figma/extractors/index.js +11 -0
  16. package/build/figma/extractors/index.js.map +1 -0
  17. package/build/figma/extractors/node-walker.d.ts +16 -0
  18. package/build/figma/extractors/node-walker.d.ts.map +1 -0
  19. package/build/figma/extractors/node-walker.js +93 -0
  20. package/build/figma/extractors/node-walker.js.map +1 -0
  21. package/build/figma/extractors/types.d.ts +73 -0
  22. package/build/figma/extractors/types.d.ts.map +1 -0
  23. package/build/figma/extractors/types.js +2 -0
  24. package/build/figma/extractors/types.js.map +1 -0
  25. package/build/figma/transformers/component.d.ts +27 -0
  26. package/build/figma/transformers/component.d.ts.map +1 -0
  27. package/build/figma/transformers/component.js +29 -0
  28. package/build/figma/transformers/component.js.map +1 -0
  29. package/build/figma/transformers/effects.d.ts +9 -0
  30. package/build/figma/transformers/effects.d.ts.map +1 -0
  31. package/build/figma/transformers/effects.js +50 -0
  32. package/build/figma/transformers/effects.js.map +1 -0
  33. package/build/figma/transformers/layout.d.ts +27 -0
  34. package/build/figma/transformers/layout.d.ts.map +1 -0
  35. package/build/figma/transformers/layout.js +203 -0
  36. package/build/figma/transformers/layout.js.map +1 -0
  37. package/build/figma/transformers/style.d.ts +120 -0
  38. package/build/figma/transformers/style.d.ts.map +1 -0
  39. package/build/figma/transformers/style.js +539 -0
  40. package/build/figma/transformers/style.js.map +1 -0
  41. package/build/figma/transformers/text.d.ts +31 -0
  42. package/build/figma/transformers/text.d.ts.map +1 -0
  43. package/build/figma/transformers/text.js +34 -0
  44. package/build/figma/transformers/text.js.map +1 -0
  45. package/build/figma/utils/common.d.ts +70 -0
  46. package/build/figma/utils/common.d.ts.map +1 -0
  47. package/build/figma/utils/common.js +167 -0
  48. package/build/figma/utils/common.js.map +1 -0
  49. package/build/figma/utils/fetch-with-retry.d.ts +13 -0
  50. package/build/figma/utils/fetch-with-retry.d.ts.map +1 -0
  51. package/build/figma/utils/fetch-with-retry.js +70 -0
  52. package/build/figma/utils/fetch-with-retry.js.map +1 -0
  53. package/build/figma/utils/identity.d.ts +23 -0
  54. package/build/figma/utils/identity.d.ts.map +1 -0
  55. package/build/figma/utils/identity.js +71 -0
  56. package/build/figma/utils/identity.js.map +1 -0
  57. package/build/index.d.ts +20 -0
  58. package/build/index.d.ts.map +1 -0
  59. package/build/index.js +88 -0
  60. package/build/index.js.map +1 -0
  61. package/package.json +54 -0
@@ -0,0 +1,47 @@
1
+ import type { SimplifiedDesign } from "./figma/extractors/types.js";
2
+ export interface FigmaConfig {
3
+ apiKey?: string;
4
+ oauthToken?: string;
5
+ useOAuth: boolean;
6
+ }
7
+ /**
8
+ * Service for interacting with the Figma API
9
+ * Follows the service pattern established by PowerPlatformService
10
+ */
11
+ export declare class FigmaService {
12
+ private config;
13
+ private readonly baseUrl;
14
+ constructor(config: FigmaConfig);
15
+ /**
16
+ * Get authentication headers based on configuration
17
+ */
18
+ private getAuthHeaders;
19
+ /**
20
+ * Make an authenticated request to the Figma API
21
+ */
22
+ private request;
23
+ /**
24
+ * Get raw Figma API response for a file
25
+ * @param fileKey - The Figma file key from the URL
26
+ * @param depth - Optional depth limit for traversal
27
+ */
28
+ private getFigmaFile;
29
+ /**
30
+ * Get raw Figma API response for specific nodes
31
+ * @param fileKey - The Figma file key from the URL
32
+ * @param nodeIds - Array of node IDs to fetch
33
+ * @param depth - Optional depth limit for traversal
34
+ */
35
+ private getFigmaNodes;
36
+ /**
37
+ * Get comprehensive Figma design data in simplified, AI-friendly format
38
+ * This is the main method exposed to MCP tools
39
+ *
40
+ * @param fileKey - The Figma file key from the URL
41
+ * @param nodeId - Optional specific node ID(s) to fetch (format: "1:10" or "1:10;2:20")
42
+ * @param depth - Optional tree traversal depth limit
43
+ * @returns Simplified design data ready for AI consumption
44
+ */
45
+ getFigmaData(fileKey: string, nodeId?: string, depth?: number): Promise<SimplifiedDesign>;
46
+ }
47
+ //# sourceMappingURL=FigmaService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FigmaService.d.ts","sourceRoot":"","sources":["../src/FigmaService.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,6BAA6B,CAAC;AAEtF,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;gBAE1C,MAAM,EAAE,WAAW;IAiB/B;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;YACW,OAAO;IAgBrB;;;;OAIG;YACW,YAAY;IAQ1B;;;;;OAKG;YACW,aAAa;IAc3B;;;;;;;;OAQG;IACG,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,CAAC;CA8B7B"}
@@ -0,0 +1,108 @@
1
+ import { fetchWithRetry } from "./figma/utils/fetch-with-retry.js";
2
+ import { simplifyRawFigmaObject } from "./figma/extractors/design-extractor.js";
3
+ import { allExtractors } from "./figma/extractors/built-in.js";
4
+ /**
5
+ * Service for interacting with the Figma API
6
+ * Follows the service pattern established by PowerPlatformService
7
+ */
8
+ export class FigmaService {
9
+ config;
10
+ baseUrl = "https://api.figma.com/v1";
11
+ constructor(config) {
12
+ this.config = config;
13
+ // Validate configuration
14
+ if (!this.config.apiKey && !this.config.oauthToken) {
15
+ throw new Error("Figma configuration requires either apiKey or oauthToken");
16
+ }
17
+ if (this.config.useOAuth && !this.config.oauthToken) {
18
+ throw new Error("useOAuth is true but oauthToken is not provided");
19
+ }
20
+ }
21
+ /**
22
+ * Get authentication headers based on configuration
23
+ */
24
+ getAuthHeaders() {
25
+ if (this.config.useOAuth && this.config.oauthToken) {
26
+ console.error("Using OAuth Bearer token for authentication");
27
+ return { Authorization: `Bearer ${this.config.oauthToken}` };
28
+ }
29
+ else if (this.config.apiKey) {
30
+ console.error("Using Personal Access Token for authentication");
31
+ return { "X-Figma-Token": this.config.apiKey };
32
+ }
33
+ throw new Error("No valid authentication method configured");
34
+ }
35
+ /**
36
+ * Make an authenticated request to the Figma API
37
+ */
38
+ async request(endpoint) {
39
+ try {
40
+ console.error(`Calling ${this.baseUrl}${endpoint}`);
41
+ const headers = this.getAuthHeaders();
42
+ return await fetchWithRetry(`${this.baseUrl}${endpoint}`, {
43
+ headers,
44
+ });
45
+ }
46
+ catch (error) {
47
+ const errorMessage = error instanceof Error ? error.message : String(error);
48
+ throw new Error(`Failed to make request to Figma API endpoint '${endpoint}': ${errorMessage}`);
49
+ }
50
+ }
51
+ /**
52
+ * Get raw Figma API response for a file
53
+ * @param fileKey - The Figma file key from the URL
54
+ * @param depth - Optional depth limit for traversal
55
+ */
56
+ async getFigmaFile(fileKey, depth) {
57
+ const endpoint = `/files/${fileKey}${depth ? `?depth=${depth}` : ""}`;
58
+ console.error(`Retrieving Figma file: ${fileKey} (depth: ${depth ?? "default"})`);
59
+ const response = await this.request(endpoint);
60
+ return response;
61
+ }
62
+ /**
63
+ * Get raw Figma API response for specific nodes
64
+ * @param fileKey - The Figma file key from the URL
65
+ * @param nodeIds - Array of node IDs to fetch
66
+ * @param depth - Optional depth limit for traversal
67
+ */
68
+ async getFigmaNodes(fileKey, nodeIds, depth) {
69
+ const endpoint = `/files/${fileKey}/nodes?ids=${nodeIds.join(",")}${depth ? `&depth=${depth}` : ""}`;
70
+ console.error(`Retrieving Figma nodes: ${nodeIds.join(", ")} from ${fileKey} (depth: ${depth ?? "default"})`);
71
+ const response = await this.request(endpoint);
72
+ return response;
73
+ }
74
+ /**
75
+ * Get comprehensive Figma design data in simplified, AI-friendly format
76
+ * This is the main method exposed to MCP tools
77
+ *
78
+ * @param fileKey - The Figma file key from the URL
79
+ * @param nodeId - Optional specific node ID(s) to fetch (format: "1:10" or "1:10;2:20")
80
+ * @param depth - Optional tree traversal depth limit
81
+ * @returns Simplified design data ready for AI consumption
82
+ */
83
+ async getFigmaData(fileKey, nodeId, depth) {
84
+ try {
85
+ // Fetch raw data from Figma API
86
+ let rawData;
87
+ if (nodeId) {
88
+ // Parse node IDs (support both single and multiple, semicolon-separated)
89
+ const nodeIds = nodeId.split(";").map(id => id.trim()).filter(id => id.length > 0);
90
+ rawData = await this.getFigmaNodes(fileKey, nodeIds, depth);
91
+ }
92
+ else {
93
+ rawData = await this.getFigmaFile(fileKey, depth);
94
+ }
95
+ // Transform raw Figma data into simplified format using extractors
96
+ const options = {
97
+ maxDepth: depth,
98
+ };
99
+ const simplifiedData = simplifyRawFigmaObject(rawData, allExtractors, options);
100
+ return simplifiedData;
101
+ }
102
+ catch (error) {
103
+ console.error("Error fetching Figma data:", error);
104
+ throw new Error(`Failed to fetch Figma data: ${error.message}`);
105
+ }
106
+ }
107
+ }
108
+ //# sourceMappingURL=FigmaService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FigmaService.js","sourceRoot":"","sources":["../src/FigmaService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { ExtractorFn, SimplifiedNode } from "./types.js";
2
+ import type { Node as FigmaDocumentNode } from "@figma/rest-api-spec";
3
+ /**
4
+ * Extracts layout-related properties from a node.
5
+ */
6
+ export declare const layoutExtractor: ExtractorFn;
7
+ /**
8
+ * Extracts text content and text styling from a node.
9
+ */
10
+ export declare const textExtractor: ExtractorFn;
11
+ /**
12
+ * Extracts visual appearance properties (fills, strokes, effects, opacity, border radius).
13
+ */
14
+ export declare const visualsExtractor: ExtractorFn;
15
+ /**
16
+ * Extracts component-related properties from INSTANCE nodes.
17
+ */
18
+ export declare const componentExtractor: ExtractorFn;
19
+ /**
20
+ * All extractors - replicates the current parseNode behavior.
21
+ */
22
+ export declare const allExtractors: ExtractorFn[];
23
+ /**
24
+ * Layout and text only - useful for content analysis and layout planning.
25
+ */
26
+ export declare const layoutAndText: ExtractorFn[];
27
+ /**
28
+ * Text content only - useful for content audits and copy extraction.
29
+ */
30
+ export declare const contentOnly: ExtractorFn[];
31
+ /**
32
+ * Visuals only - useful for design system analysis and style extraction.
33
+ */
34
+ export declare const visualsOnly: ExtractorFn[];
35
+ /**
36
+ * Layout only - useful for structure analysis.
37
+ */
38
+ export declare const layoutOnly: ExtractorFn[];
39
+ /**
40
+ * Node types that can be exported as SVG images.
41
+ * When a FRAME, GROUP, or INSTANCE contains only these types, we can collapse it to IMAGE-SVG.
42
+ * Note: FRAME/GROUP/INSTANCE are NOT included here—they're only eligible if collapsed to IMAGE-SVG.
43
+ */
44
+ export declare const SVG_ELIGIBLE_TYPES: Set<string>;
45
+ /**
46
+ * afterChildren callback that collapses SVG-heavy containers to IMAGE-SVG.
47
+ *
48
+ * If a FRAME, GROUP, or INSTANCE contains only SVG-eligible children, the parent
49
+ * is marked as IMAGE-SVG and children are omitted, reducing payload size.
50
+ *
51
+ * @param node - Original Figma node
52
+ * @param result - SimplifiedNode being built
53
+ * @param children - Processed children
54
+ * @returns Children to include (empty array if collapsed)
55
+ */
56
+ export declare function collapseSvgContainers(node: FigmaDocumentNode, result: SimplifiedNode, children: SimplifiedNode[]): SimplifiedNode[];
57
+ //# sourceMappingURL=built-in.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"built-in.d.ts","sourceRoot":"","sources":["../../../src/figma/extractors/built-in.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAIX,cAAc,EACf,MAAM,YAAY,CAAC;AAYpB,OAAO,KAAK,EAAE,IAAI,IAAI,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAsBtE;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,WAK7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,WAoB3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,WA0D9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAiBhC,CAAC;AAsBF;;GAEG;AACH,eAAO,MAAM,aAAa,eAAyE,CAAC;AAEpG;;GAEG;AACH,eAAO,MAAM,aAAa,eAAmC,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,WAAW,eAAkB,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,WAAW,eAAqB,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,UAAU,eAAoB,CAAC;AAI5C;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,aAO7B,CAAC;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,cAAc,EAAE,GACzB,cAAc,EAAE,CAgBlB"}
@@ -0,0 +1,206 @@
1
+ import { buildSimplifiedLayout } from "../transformers/layout.js";
2
+ import { buildSimplifiedStrokes, parsePaint } from "../transformers/style.js";
3
+ import { buildSimplifiedEffects } from "../transformers/effects.js";
4
+ import { extractNodeText, extractTextStyle, hasTextStyle, isTextNode, } from "../transformers/text.js";
5
+ import { hasValue, isRectangleCornerRadii } from "../utils/identity.js";
6
+ import { generateVarId } from "../utils/common.js";
7
+ /**
8
+ * Helper function to find or create a global variable.
9
+ */
10
+ function findOrCreateVar(globalVars, value, prefix) {
11
+ // Check if the same value already exists
12
+ const [existingVarId] = Object.entries(globalVars.styles).find(([_, existingValue]) => JSON.stringify(existingValue) === JSON.stringify(value)) ?? [];
13
+ if (existingVarId) {
14
+ return existingVarId;
15
+ }
16
+ // Create a new variable if it doesn't exist
17
+ const varId = generateVarId(prefix);
18
+ globalVars.styles[varId] = value;
19
+ return varId;
20
+ }
21
+ /**
22
+ * Extracts layout-related properties from a node.
23
+ */
24
+ export const layoutExtractor = (node, result, context) => {
25
+ const layout = buildSimplifiedLayout(node, context.parent);
26
+ if (Object.keys(layout).length > 1) {
27
+ result.layout = findOrCreateVar(context.globalVars, layout, "layout");
28
+ }
29
+ };
30
+ /**
31
+ * Extracts text content and text styling from a node.
32
+ */
33
+ export const textExtractor = (node, result, context) => {
34
+ // Extract text content
35
+ if (isTextNode(node)) {
36
+ result.text = extractNodeText(node);
37
+ }
38
+ // Extract text style
39
+ if (hasTextStyle(node)) {
40
+ const textStyle = extractTextStyle(node);
41
+ if (textStyle) {
42
+ // Prefer Figma named style when available
43
+ const styleName = getStyleName(node, context, ["text", "typography"]);
44
+ if (styleName) {
45
+ context.globalVars.styles[styleName] = textStyle;
46
+ result.textStyle = styleName;
47
+ }
48
+ else {
49
+ result.textStyle = findOrCreateVar(context.globalVars, textStyle, "style");
50
+ }
51
+ }
52
+ }
53
+ };
54
+ /**
55
+ * Extracts visual appearance properties (fills, strokes, effects, opacity, border radius).
56
+ */
57
+ export const visualsExtractor = (node, result, context) => {
58
+ // Check if node has children to determine CSS properties
59
+ const hasChildren = hasValue("children", node) && Array.isArray(node.children) && node.children.length > 0;
60
+ // fills
61
+ if (hasValue("fills", node) && Array.isArray(node.fills) && node.fills.length) {
62
+ const fills = node.fills.map((fill) => parsePaint(fill, hasChildren)).reverse();
63
+ const styleName = getStyleName(node, context, ["fill", "fills"]);
64
+ if (styleName) {
65
+ context.globalVars.styles[styleName] = fills;
66
+ result.fills = styleName;
67
+ }
68
+ else {
69
+ result.fills = findOrCreateVar(context.globalVars, fills, "fill");
70
+ }
71
+ }
72
+ // strokes
73
+ const strokes = buildSimplifiedStrokes(node, hasChildren);
74
+ if (strokes.colors.length) {
75
+ const styleName = getStyleName(node, context, ["stroke", "strokes"]);
76
+ if (styleName) {
77
+ // Only colors are stylable; keep other stroke props on the node
78
+ context.globalVars.styles[styleName] = strokes.colors;
79
+ result.strokes = styleName;
80
+ if (strokes.strokeWeight)
81
+ result.strokeWeight = strokes.strokeWeight;
82
+ if (strokes.strokeDashes)
83
+ result.strokeDashes = strokes.strokeDashes;
84
+ if (strokes.strokeWeights)
85
+ result.strokeWeights = strokes.strokeWeights;
86
+ }
87
+ else {
88
+ result.strokes = findOrCreateVar(context.globalVars, strokes, "stroke");
89
+ }
90
+ }
91
+ // effects
92
+ const effects = buildSimplifiedEffects(node);
93
+ if (Object.keys(effects).length) {
94
+ const styleName = getStyleName(node, context, ["effect", "effects"]);
95
+ if (styleName) {
96
+ // Effects styles store only the effect values
97
+ context.globalVars.styles[styleName] = effects;
98
+ result.effects = styleName;
99
+ }
100
+ else {
101
+ result.effects = findOrCreateVar(context.globalVars, effects, "effect");
102
+ }
103
+ }
104
+ // opacity
105
+ if (hasValue("opacity", node) && typeof node.opacity === "number" && node.opacity !== 1) {
106
+ result.opacity = node.opacity;
107
+ }
108
+ // border radius
109
+ if (hasValue("cornerRadius", node) && typeof node.cornerRadius === "number") {
110
+ result.borderRadius = `${node.cornerRadius}px`;
111
+ }
112
+ if (hasValue("rectangleCornerRadii", node, isRectangleCornerRadii)) {
113
+ result.borderRadius = `${node.rectangleCornerRadii[0]}px ${node.rectangleCornerRadii[1]}px ${node.rectangleCornerRadii[2]}px ${node.rectangleCornerRadii[3]}px`;
114
+ }
115
+ };
116
+ /**
117
+ * Extracts component-related properties from INSTANCE nodes.
118
+ */
119
+ export const componentExtractor = (node, result, _context) => {
120
+ if (node.type === "INSTANCE") {
121
+ if (hasValue("componentId", node)) {
122
+ result.componentId = node.componentId;
123
+ }
124
+ // Add specific properties for instances of components
125
+ if (hasValue("componentProperties", node)) {
126
+ result.componentProperties = Object.entries(node.componentProperties ?? {}).map(([name, { value, type }]) => ({
127
+ name,
128
+ value: value.toString(),
129
+ type,
130
+ }));
131
+ }
132
+ }
133
+ };
134
+ // Helper to fetch a Figma style name for specific style keys on a node
135
+ function getStyleName(node, context, keys) {
136
+ if (!hasValue("styles", node))
137
+ return undefined;
138
+ const styleMap = node.styles;
139
+ for (const key of keys) {
140
+ const styleId = styleMap[key];
141
+ if (styleId) {
142
+ const meta = context.globalVars.extraStyles?.[styleId];
143
+ if (meta?.name)
144
+ return meta.name;
145
+ }
146
+ }
147
+ return undefined;
148
+ }
149
+ // -------------------- CONVENIENCE COMBINATIONS --------------------
150
+ /**
151
+ * All extractors - replicates the current parseNode behavior.
152
+ */
153
+ export const allExtractors = [layoutExtractor, textExtractor, visualsExtractor, componentExtractor];
154
+ /**
155
+ * Layout and text only - useful for content analysis and layout planning.
156
+ */
157
+ export const layoutAndText = [layoutExtractor, textExtractor];
158
+ /**
159
+ * Text content only - useful for content audits and copy extraction.
160
+ */
161
+ export const contentOnly = [textExtractor];
162
+ /**
163
+ * Visuals only - useful for design system analysis and style extraction.
164
+ */
165
+ export const visualsOnly = [visualsExtractor];
166
+ /**
167
+ * Layout only - useful for structure analysis.
168
+ */
169
+ export const layoutOnly = [layoutExtractor];
170
+ // -------------------- AFTER CHILDREN HELPERS --------------------
171
+ /**
172
+ * Node types that can be exported as SVG images.
173
+ * When a FRAME, GROUP, or INSTANCE contains only these types, we can collapse it to IMAGE-SVG.
174
+ * Note: FRAME/GROUP/INSTANCE are NOT included here—they're only eligible if collapsed to IMAGE-SVG.
175
+ */
176
+ export const SVG_ELIGIBLE_TYPES = new Set([
177
+ "IMAGE-SVG", // VECTOR nodes are converted to IMAGE-SVG, or containers that were collapsed
178
+ "STAR",
179
+ "LINE",
180
+ "ELLIPSE",
181
+ "REGULAR_POLYGON",
182
+ "RECTANGLE",
183
+ ]);
184
+ /**
185
+ * afterChildren callback that collapses SVG-heavy containers to IMAGE-SVG.
186
+ *
187
+ * If a FRAME, GROUP, or INSTANCE contains only SVG-eligible children, the parent
188
+ * is marked as IMAGE-SVG and children are omitted, reducing payload size.
189
+ *
190
+ * @param node - Original Figma node
191
+ * @param result - SimplifiedNode being built
192
+ * @param children - Processed children
193
+ * @returns Children to include (empty array if collapsed)
194
+ */
195
+ export function collapseSvgContainers(node, result, children) {
196
+ const allChildrenAreSvgEligible = children.every((child) => SVG_ELIGIBLE_TYPES.has(child.type));
197
+ if ((node.type === "FRAME" || node.type === "GROUP" || node.type === "INSTANCE") &&
198
+ allChildrenAreSvgEligible) {
199
+ // Collapse to IMAGE-SVG and omit children
200
+ result.type = "IMAGE-SVG";
201
+ return [];
202
+ }
203
+ // Include all children normally
204
+ return children;
205
+ }
206
+ //# sourceMappingURL=built-in.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"built-in.js","sourceRoot":"","sources":["../../../src/figma/extractors/built-in.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { GetFileResponse, GetFileNodesResponse } from "@figma/rest-api-spec";
2
+ import type { ExtractorFn, TraversalOptions, SimplifiedDesign } from "./types.js";
3
+ /**
4
+ * Extract a complete SimplifiedDesign from raw Figma API response using extractors.
5
+ */
6
+ export declare function simplifyRawFigmaObject(apiResponse: GetFileResponse | GetFileNodesResponse, nodeExtractors: ExtractorFn[], options?: TraversalOptions): SimplifiedDesign;
7
+ //# sourceMappingURL=design-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-extractor.d.ts","sourceRoot":"","sources":["../../../src/figma/extractors/design-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EAKrB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAoB,MAAM,YAAY,CAAC;AAGpG;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,eAAe,GAAG,oBAAoB,EACnD,cAAc,EAAE,WAAW,EAAE,EAC7B,OAAO,GAAE,gBAAqB,GAC7B,gBAAgB,CAsBlB"}
@@ -0,0 +1,66 @@
1
+ import { simplifyComponents, simplifyComponentSets } from "../transformers/component.js";
2
+ import { isVisible } from "../utils/common.js";
3
+ import { extractFromDesign } from "./node-walker.js";
4
+ /**
5
+ * Extract a complete SimplifiedDesign from raw Figma API response using extractors.
6
+ */
7
+ export function simplifyRawFigmaObject(apiResponse, nodeExtractors, options = {}) {
8
+ // Extract components, componentSets, and raw nodes from API response
9
+ const { metadata, rawNodes, components, componentSets, extraStyles } = parseAPIResponse(apiResponse);
10
+ // Process nodes using the flexible extractor system
11
+ const globalVars = { styles: {}, extraStyles };
12
+ const { nodes: extractedNodes, globalVars: finalGlobalVars } = extractFromDesign(rawNodes, nodeExtractors, options, globalVars);
13
+ // Return complete design
14
+ return {
15
+ ...metadata,
16
+ nodes: extractedNodes,
17
+ components: simplifyComponents(components),
18
+ componentSets: simplifyComponentSets(componentSets),
19
+ globalVars: { styles: finalGlobalVars.styles },
20
+ };
21
+ }
22
+ /**
23
+ * Parse the raw Figma API response to extract metadata, nodes, and components.
24
+ */
25
+ function parseAPIResponse(data) {
26
+ const aggregatedComponents = {};
27
+ const aggregatedComponentSets = {};
28
+ let extraStyles = {};
29
+ let nodesToParse;
30
+ if ("nodes" in data) {
31
+ // GetFileNodesResponse
32
+ const nodeResponses = Object.values(data.nodes);
33
+ nodeResponses.forEach((nodeResponse) => {
34
+ if (nodeResponse.components) {
35
+ Object.assign(aggregatedComponents, nodeResponse.components);
36
+ }
37
+ if (nodeResponse.componentSets) {
38
+ Object.assign(aggregatedComponentSets, nodeResponse.componentSets);
39
+ }
40
+ if (nodeResponse.styles) {
41
+ Object.assign(extraStyles, nodeResponse.styles);
42
+ }
43
+ });
44
+ nodesToParse = nodeResponses.map((n) => n.document).filter(isVisible);
45
+ }
46
+ else {
47
+ // GetFileResponse
48
+ Object.assign(aggregatedComponents, data.components);
49
+ Object.assign(aggregatedComponentSets, data.componentSets);
50
+ if (data.styles) {
51
+ extraStyles = data.styles;
52
+ }
53
+ nodesToParse = data.document.children.filter(isVisible);
54
+ }
55
+ const { name } = data;
56
+ return {
57
+ metadata: {
58
+ name,
59
+ },
60
+ rawNodes: nodesToParse,
61
+ extraStyles,
62
+ components: aggregatedComponents,
63
+ componentSets: aggregatedComponentSets,
64
+ };
65
+ }
66
+ //# sourceMappingURL=design-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-extractor.js","sourceRoot":"","sources":["../../../src/figma/extractors/design-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type { ExtractorFn, TraversalContext, TraversalOptions, GlobalVars, StyleTypes, } from "./types.js";
2
+ export { extractFromDesign } from "./node-walker.js";
3
+ export { simplifyRawFigmaObject } from "./design-extractor.js";
4
+ export { layoutExtractor, textExtractor, visualsExtractor, componentExtractor, allExtractors, layoutAndText, contentOnly, visualsOnly, layoutOnly, collapseSvgContainers, SVG_ELIGIBLE_TYPES, } from "./built-in.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/figma/extractors/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,OAAO,EACL,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAElB,aAAa,EACb,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EAEV,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,11 @@
1
+ // Core traversal function
2
+ export { extractFromDesign } from "./node-walker.js";
3
+ // Design-level extraction (unified nodes + components)
4
+ export { simplifyRawFigmaObject } from "./design-extractor.js";
5
+ // Built-in extractors and afterChildren helpers
6
+ export { layoutExtractor, textExtractor, visualsExtractor, componentExtractor,
7
+ // Convenience combinations
8
+ allExtractors, layoutAndText, contentOnly, visualsOnly, layoutOnly,
9
+ // afterChildren helpers
10
+ collapseSvgContainers, SVG_ELIGIBLE_TYPES, } from "./built-in.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/figma/extractors/index.ts"],"names":[],"mappings":"AASA,0BAA0B;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,uDAAuD;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,gDAAgD;AAChD,OAAO,EACL,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,kBAAkB;AAClB,2BAA2B;AAC3B,aAAa,EACb,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU;AACV,wBAAwB;AACxB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { Node as FigmaDocumentNode } from "@figma/rest-api-spec";
2
+ import type { ExtractorFn, TraversalOptions, GlobalVars, SimplifiedNode } from "./types.js";
3
+ /**
4
+ * Extract data from Figma nodes using a flexible, single-pass approach.
5
+ *
6
+ * @param nodes - The Figma nodes to process
7
+ * @param extractors - Array of extractor functions to apply during traversal
8
+ * @param options - Traversal options (filtering, depth limits, etc.)
9
+ * @param globalVars - Global variables for style deduplication
10
+ * @returns Object containing processed nodes and updated global variables
11
+ */
12
+ export declare function extractFromDesign(nodes: FigmaDocumentNode[], extractors: ExtractorFn[], options?: TraversalOptions, globalVars?: GlobalVars): {
13
+ nodes: SimplifiedNode[];
14
+ globalVars: GlobalVars;
15
+ };
16
+ //# sourceMappingURL=node-walker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-walker.d.ts","sourceRoot":"","sources":["../../../src/figma/extractors/node-walker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGtE,OAAO,KAAK,EACV,WAAW,EAEX,gBAAgB,EAChB,UAAU,EACV,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,iBAAiB,EAAE,EAC1B,UAAU,EAAE,WAAW,EAAE,EACzB,OAAO,GAAE,gBAAqB,EAC9B,UAAU,GAAE,UAA2B,GACtC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAerD"}