figma-metadata-extractor 1.0.9 → 1.0.11
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.
- package/dist/index.cjs +57 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +57 -2
- package/dist/lib.d.ts +44 -2
- package/dist/utils/image-processing.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -420,7 +420,7 @@ class FigmaService {
|
|
|
420
420
|
cropTransform,
|
|
421
421
|
requiresImageDimensions,
|
|
422
422
|
returnBuffer
|
|
423
|
-
) : null;
|
|
423
|
+
).then((result) => ({ ...result, nodeId })) : null;
|
|
424
424
|
}).filter((promise) => promise !== null);
|
|
425
425
|
if (pngDownloads.length > 0) {
|
|
426
426
|
downloadPromises.push(Promise.all(pngDownloads));
|
|
@@ -443,7 +443,7 @@ class FigmaService {
|
|
|
443
443
|
cropTransform,
|
|
444
444
|
requiresImageDimensions,
|
|
445
445
|
returnBuffer
|
|
446
|
-
) : null;
|
|
446
|
+
).then((result) => ({ ...result, nodeId })) : null;
|
|
447
447
|
}).filter((promise) => promise !== null);
|
|
448
448
|
if (svgDownloads.length > 0) {
|
|
449
449
|
downloadPromises.push(Promise.all(svgDownloads));
|
|
@@ -1630,6 +1630,59 @@ async function downloadFigmaFrameImage(figmaUrl, options) {
|
|
|
1630
1630
|
throw new Error(`Failed to download frame image: ${error instanceof Error ? error.message : String(error)}`);
|
|
1631
1631
|
}
|
|
1632
1632
|
}
|
|
1633
|
+
function getImageNodeInfo(metadata) {
|
|
1634
|
+
if (!metadata.images || metadata.images.length === 0) {
|
|
1635
|
+
return [];
|
|
1636
|
+
}
|
|
1637
|
+
const imageAssets = findImageAssets(metadata.nodes, metadata.globalVars);
|
|
1638
|
+
return imageAssets.map((asset) => ({
|
|
1639
|
+
nodeId: asset.id,
|
|
1640
|
+
name: asset.name
|
|
1641
|
+
}));
|
|
1642
|
+
}
|
|
1643
|
+
function enrichMetadataWithImages(metadata, imagePaths, options = {}) {
|
|
1644
|
+
const { useRelativePaths = true, localPath } = options;
|
|
1645
|
+
if (!metadata.images || metadata.images.length === 0) {
|
|
1646
|
+
return metadata;
|
|
1647
|
+
}
|
|
1648
|
+
const imageAssets = findImageAssets(metadata.nodes, metadata.globalVars);
|
|
1649
|
+
let downloadResults;
|
|
1650
|
+
if (Array.isArray(imagePaths)) {
|
|
1651
|
+
if (imagePaths.length !== metadata.images.length) {
|
|
1652
|
+
throw new Error(`Number of image paths (${imagePaths.length}) must match number of images (${metadata.images.length})`);
|
|
1653
|
+
}
|
|
1654
|
+
downloadResults = imagePaths.map((filePath, index) => ({
|
|
1655
|
+
filePath,
|
|
1656
|
+
finalDimensions: metadata.images[index].finalDimensions,
|
|
1657
|
+
wasCropped: metadata.images[index].wasCropped,
|
|
1658
|
+
cssVariables: metadata.images[index].cssVariables
|
|
1659
|
+
}));
|
|
1660
|
+
} else {
|
|
1661
|
+
downloadResults = imageAssets.map((asset) => {
|
|
1662
|
+
const filePath = imagePaths[asset.id];
|
|
1663
|
+
if (!filePath) {
|
|
1664
|
+
throw new Error(`No image path provided for node ID: ${asset.id}`);
|
|
1665
|
+
}
|
|
1666
|
+
const imageMetadata = metadata.images.find((img) => img.nodeId === asset.id);
|
|
1667
|
+
return {
|
|
1668
|
+
filePath,
|
|
1669
|
+
finalDimensions: imageMetadata?.finalDimensions || { width: 0, height: 0 },
|
|
1670
|
+
wasCropped: imageMetadata?.wasCropped || false,
|
|
1671
|
+
cssVariables: imageMetadata?.cssVariables
|
|
1672
|
+
};
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
const enrichedNodes = enrichNodesWithImages(
|
|
1676
|
+
metadata.nodes,
|
|
1677
|
+
imageAssets,
|
|
1678
|
+
downloadResults,
|
|
1679
|
+
useRelativePaths
|
|
1680
|
+
);
|
|
1681
|
+
return {
|
|
1682
|
+
...metadata,
|
|
1683
|
+
nodes: enrichedNodes
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1633
1686
|
function sanitizeFileName(name) {
|
|
1634
1687
|
return name.replace(/[^a-z0-9]/gi, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").toLowerCase();
|
|
1635
1688
|
}
|
|
@@ -1706,8 +1759,10 @@ exports.componentExtractor = componentExtractor;
|
|
|
1706
1759
|
exports.contentOnly = contentOnly;
|
|
1707
1760
|
exports.downloadFigmaFrameImage = downloadFigmaFrameImage;
|
|
1708
1761
|
exports.downloadFigmaImages = downloadFigmaImages;
|
|
1762
|
+
exports.enrichMetadataWithImages = enrichMetadataWithImages;
|
|
1709
1763
|
exports.extractFromDesign = extractFromDesign;
|
|
1710
1764
|
exports.getFigmaMetadata = getFigmaMetadata;
|
|
1765
|
+
exports.getImageNodeInfo = getImageNodeInfo;
|
|
1711
1766
|
exports.layoutAndText = layoutAndText;
|
|
1712
1767
|
exports.layoutExtractor = layoutExtractor;
|
|
1713
1768
|
exports.layoutOnly = layoutOnly;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { getFigmaMetadata, downloadFigmaImages, downloadFigmaFrameImage, type FigmaMetadataOptions, type FigmaImageOptions, type FigmaFrameImageOptions, type FigmaImageNode, type FigmaMetadataResult, type FigmaImageResult, } from "./lib.js";
|
|
1
|
+
export { getFigmaMetadata, downloadFigmaImages, downloadFigmaFrameImage, enrichMetadataWithImages, getImageNodeInfo, type FigmaMetadataOptions, type FigmaImageOptions, type FigmaFrameImageOptions, type FigmaImageNode, type FigmaMetadataResult, type FigmaImageResult, } from "./lib.js";
|
|
2
2
|
export type { SimplifiedDesign } from "./extractors/types.js";
|
|
3
3
|
export type { ExtractorFn, TraversalContext, TraversalOptions, GlobalVars, StyleTypes, } from "./extractors/index.js";
|
|
4
4
|
export { extractFromDesign, simplifyRawFigmaObject, layoutExtractor, textExtractor, visualsExtractor, componentExtractor, allExtractors, layoutAndText, contentOnly, visualsOnly, layoutOnly, collapseSvgContainers, } from "./extractors/index.js";
|
package/dist/index.js
CHANGED
|
@@ -418,7 +418,7 @@ class FigmaService {
|
|
|
418
418
|
cropTransform,
|
|
419
419
|
requiresImageDimensions,
|
|
420
420
|
returnBuffer
|
|
421
|
-
) : null;
|
|
421
|
+
).then((result) => ({ ...result, nodeId })) : null;
|
|
422
422
|
}).filter((promise) => promise !== null);
|
|
423
423
|
if (pngDownloads.length > 0) {
|
|
424
424
|
downloadPromises.push(Promise.all(pngDownloads));
|
|
@@ -441,7 +441,7 @@ class FigmaService {
|
|
|
441
441
|
cropTransform,
|
|
442
442
|
requiresImageDimensions,
|
|
443
443
|
returnBuffer
|
|
444
|
-
) : null;
|
|
444
|
+
).then((result) => ({ ...result, nodeId })) : null;
|
|
445
445
|
}).filter((promise) => promise !== null);
|
|
446
446
|
if (svgDownloads.length > 0) {
|
|
447
447
|
downloadPromises.push(Promise.all(svgDownloads));
|
|
@@ -1628,6 +1628,59 @@ async function downloadFigmaFrameImage(figmaUrl, options) {
|
|
|
1628
1628
|
throw new Error(`Failed to download frame image: ${error instanceof Error ? error.message : String(error)}`);
|
|
1629
1629
|
}
|
|
1630
1630
|
}
|
|
1631
|
+
function getImageNodeInfo(metadata) {
|
|
1632
|
+
if (!metadata.images || metadata.images.length === 0) {
|
|
1633
|
+
return [];
|
|
1634
|
+
}
|
|
1635
|
+
const imageAssets = findImageAssets(metadata.nodes, metadata.globalVars);
|
|
1636
|
+
return imageAssets.map((asset) => ({
|
|
1637
|
+
nodeId: asset.id,
|
|
1638
|
+
name: asset.name
|
|
1639
|
+
}));
|
|
1640
|
+
}
|
|
1641
|
+
function enrichMetadataWithImages(metadata, imagePaths, options = {}) {
|
|
1642
|
+
const { useRelativePaths = true, localPath } = options;
|
|
1643
|
+
if (!metadata.images || metadata.images.length === 0) {
|
|
1644
|
+
return metadata;
|
|
1645
|
+
}
|
|
1646
|
+
const imageAssets = findImageAssets(metadata.nodes, metadata.globalVars);
|
|
1647
|
+
let downloadResults;
|
|
1648
|
+
if (Array.isArray(imagePaths)) {
|
|
1649
|
+
if (imagePaths.length !== metadata.images.length) {
|
|
1650
|
+
throw new Error(`Number of image paths (${imagePaths.length}) must match number of images (${metadata.images.length})`);
|
|
1651
|
+
}
|
|
1652
|
+
downloadResults = imagePaths.map((filePath, index) => ({
|
|
1653
|
+
filePath,
|
|
1654
|
+
finalDimensions: metadata.images[index].finalDimensions,
|
|
1655
|
+
wasCropped: metadata.images[index].wasCropped,
|
|
1656
|
+
cssVariables: metadata.images[index].cssVariables
|
|
1657
|
+
}));
|
|
1658
|
+
} else {
|
|
1659
|
+
downloadResults = imageAssets.map((asset) => {
|
|
1660
|
+
const filePath = imagePaths[asset.id];
|
|
1661
|
+
if (!filePath) {
|
|
1662
|
+
throw new Error(`No image path provided for node ID: ${asset.id}`);
|
|
1663
|
+
}
|
|
1664
|
+
const imageMetadata = metadata.images.find((img) => img.nodeId === asset.id);
|
|
1665
|
+
return {
|
|
1666
|
+
filePath,
|
|
1667
|
+
finalDimensions: imageMetadata?.finalDimensions || { width: 0, height: 0 },
|
|
1668
|
+
wasCropped: imageMetadata?.wasCropped || false,
|
|
1669
|
+
cssVariables: imageMetadata?.cssVariables
|
|
1670
|
+
};
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
const enrichedNodes = enrichNodesWithImages(
|
|
1674
|
+
metadata.nodes,
|
|
1675
|
+
imageAssets,
|
|
1676
|
+
downloadResults,
|
|
1677
|
+
useRelativePaths
|
|
1678
|
+
);
|
|
1679
|
+
return {
|
|
1680
|
+
...metadata,
|
|
1681
|
+
nodes: enrichedNodes
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1631
1684
|
function sanitizeFileName(name) {
|
|
1632
1685
|
return name.replace(/[^a-z0-9]/gi, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").toLowerCase();
|
|
1633
1686
|
}
|
|
@@ -1705,8 +1758,10 @@ export {
|
|
|
1705
1758
|
contentOnly,
|
|
1706
1759
|
downloadFigmaFrameImage,
|
|
1707
1760
|
downloadFigmaImages,
|
|
1761
|
+
enrichMetadataWithImages,
|
|
1708
1762
|
extractFromDesign,
|
|
1709
1763
|
getFigmaMetadata,
|
|
1764
|
+
getImageNodeInfo,
|
|
1710
1765
|
layoutAndText,
|
|
1711
1766
|
layoutExtractor,
|
|
1712
1767
|
layoutOnly,
|
package/dist/lib.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ export interface FigmaMetadataResult {
|
|
|
61
61
|
images?: FigmaImageResult[];
|
|
62
62
|
}
|
|
63
63
|
export interface FigmaImageResult {
|
|
64
|
+
nodeId?: string;
|
|
64
65
|
filePath?: string;
|
|
65
66
|
buffer?: ArrayBuffer;
|
|
66
67
|
finalDimensions: {
|
|
@@ -121,17 +122,58 @@ export declare function downloadFigmaImages(figmaUrl: string, nodes: FigmaImageN
|
|
|
121
122
|
* @returns Promise resolving to the download result
|
|
122
123
|
*/
|
|
123
124
|
export declare function downloadFigmaFrameImage(figmaUrl: string, options: FigmaFrameImageOptions): Promise<FigmaImageResult>;
|
|
125
|
+
/**
|
|
126
|
+
* Get image node information from metadata
|
|
127
|
+
*
|
|
128
|
+
* Returns an array of objects containing node IDs and names for all images in the metadata.
|
|
129
|
+
* Use this to create a mapping between node IDs and uploaded URLs.
|
|
130
|
+
*
|
|
131
|
+
* @param metadata - The metadata result from getFigmaMetadata
|
|
132
|
+
* @returns Array of objects with nodeId and name for each image
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* const imageInfo = getImageNodeInfo(metadata);
|
|
137
|
+
* // [{ nodeId: '123:456', name: 'icon' }, { nodeId: '789:012', name: 'logo' }]
|
|
138
|
+
*
|
|
139
|
+
* // Upload images and create mapping
|
|
140
|
+
* const urlMap: Record<string, string> = {};
|
|
141
|
+
* for (const info of imageInfo) {
|
|
142
|
+
* const url = await uploadToS3(metadata.images.find(img => img.nodeId === info.nodeId).buffer);
|
|
143
|
+
* urlMap[info.nodeId] = url;
|
|
144
|
+
* }
|
|
145
|
+
*
|
|
146
|
+
* // Enrich metadata with URLs
|
|
147
|
+
* const enriched = enrichMetadataWithImages(metadata, urlMap);
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export declare function getImageNodeInfo(metadata: FigmaMetadataResult): Array<{
|
|
151
|
+
nodeId: string;
|
|
152
|
+
name: string;
|
|
153
|
+
}>;
|
|
124
154
|
/**
|
|
125
155
|
* Enrich metadata with saved image file paths
|
|
126
156
|
*
|
|
127
157
|
* Use this function after saving images from buffers to disk to add file path information to the metadata.
|
|
128
158
|
*
|
|
129
159
|
* @param metadata - The metadata result from getFigmaMetadata
|
|
130
|
-
* @param imagePaths - Array of file paths
|
|
160
|
+
* @param imagePaths - Array of file paths (ordered) OR object mapping node IDs to paths/URLs
|
|
131
161
|
* @param options - Options for path generation
|
|
132
162
|
* @returns Enriched metadata with downloadedImage properties on nodes
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```typescript
|
|
166
|
+
* // Array format (ordered)
|
|
167
|
+
* const enriched = enrichMetadataWithImages(metadata, ['/path/to/img1.png', '/path/to/img2.png']);
|
|
168
|
+
*
|
|
169
|
+
* // Object format (keyed by node ID) - useful after uploading to CDN
|
|
170
|
+
* const enriched = enrichMetadataWithImages(metadata, {
|
|
171
|
+
* '123:456': 'https://cdn.example.com/icon.png',
|
|
172
|
+
* '789:012': 'https://cdn.example.com/logo.png'
|
|
173
|
+
* });
|
|
174
|
+
* ```
|
|
133
175
|
*/
|
|
134
|
-
export declare function enrichMetadataWithImages(metadata: FigmaMetadataResult, imagePaths: string[], options?: {
|
|
176
|
+
export declare function enrichMetadataWithImages(metadata: FigmaMetadataResult, imagePaths: string[] | Record<string, string>, options?: {
|
|
135
177
|
useRelativePaths?: boolean | string;
|
|
136
178
|
localPath?: string;
|
|
137
179
|
}): FigmaMetadataResult;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "figma-metadata-extractor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Extract metadata and download images from Figma files. A standalone library for accessing Figma design data and downloading frame images programmatically.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|