figma-metadata-extractor 1.0.12 → 1.0.13

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 CHANGED
@@ -1537,14 +1537,25 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
1537
1537
  );
1538
1538
  let rawApiResponse;
1539
1539
  if (nodeId) {
1540
- rawApiResponse = await figmaService.getRawNode(fileKey, nodeId, depth || void 0);
1540
+ rawApiResponse = await figmaService.getRawNode(
1541
+ fileKey,
1542
+ nodeId,
1543
+ depth || void 0
1544
+ );
1541
1545
  } else {
1542
- rawApiResponse = await figmaService.getRawFile(fileKey, depth || void 0);
1546
+ rawApiResponse = await figmaService.getRawFile(
1547
+ fileKey,
1548
+ depth || void 0
1549
+ );
1543
1550
  }
1544
- const simplifiedDesign = simplifyRawFigmaObject(rawApiResponse, allExtractors, {
1545
- maxDepth: depth || void 0,
1546
- afterChildren: collapseSvgContainers
1547
- });
1551
+ const simplifiedDesign = simplifyRawFigmaObject(
1552
+ rawApiResponse,
1553
+ allExtractors,
1554
+ {
1555
+ maxDepth: depth || void 0,
1556
+ afterChildren: collapseSvgContainers
1557
+ }
1558
+ );
1548
1559
  Logger.log(
1549
1560
  `Successfully extracted data: ${simplifiedDesign.nodes.length} nodes, ${Object.keys(simplifiedDesign.globalVars?.styles || {}).length} styles`
1550
1561
  );
@@ -1556,7 +1567,9 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
1556
1567
  };
1557
1568
  if (downloadImages) {
1558
1569
  if (!returnBuffer && !localPath) {
1559
- throw new Error("localPath is required when downloadImages is true and returnBuffer is false");
1570
+ throw new Error(
1571
+ "localPath is required when downloadImages is true and returnBuffer is false"
1572
+ );
1560
1573
  }
1561
1574
  Logger.log("Discovering and downloading image assets...");
1562
1575
  const imageAssets = findImageAssets(nodes, globalVars);
@@ -1577,10 +1590,20 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
1577
1590
  );
1578
1591
  if (returnBuffer) {
1579
1592
  result.images = downloadResults;
1580
- Logger.log(`Successfully downloaded ${downloadResults.length} images as buffers`);
1593
+ Logger.log(
1594
+ `Successfully downloaded ${downloadResults.length} images as buffers`
1595
+ );
1581
1596
  } else {
1582
- result.nodes = enrichNodesWithImages(nodes, imageAssets, downloadResults, useRelativePaths, localPath);
1583
- Logger.log(`Successfully downloaded and enriched ${downloadResults.length} images`);
1597
+ result.nodes = enrichNodesWithImages(
1598
+ nodes,
1599
+ imageAssets,
1600
+ downloadResults,
1601
+ useRelativePaths,
1602
+ localPath
1603
+ );
1604
+ Logger.log(
1605
+ `Successfully downloaded and enriched ${downloadResults.length} images`
1606
+ );
1584
1607
  }
1585
1608
  }
1586
1609
  }
@@ -1598,7 +1621,15 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
1598
1621
  }
1599
1622
  }
1600
1623
  async function downloadFigmaImages(figmaUrl, nodes, options) {
1601
- const { apiKey, oauthToken, useOAuth = false, pngScale = 2, localPath, enableLogging = false, returnBuffer = false } = options;
1624
+ const {
1625
+ apiKey,
1626
+ oauthToken,
1627
+ useOAuth = false,
1628
+ pngScale = 2,
1629
+ localPath,
1630
+ enableLogging = false,
1631
+ returnBuffer = false
1632
+ } = options;
1602
1633
  Logger.enableLogging = enableLogging;
1603
1634
  if (!apiKey && !oauthToken) {
1604
1635
  throw new Error("Either apiKey or oauthToken is required");
@@ -1621,14 +1652,21 @@ async function downloadFigmaImages(figmaUrl, nodes, options) {
1621
1652
  ...node,
1622
1653
  nodeId: node.nodeId.replace(/-/g, ":")
1623
1654
  }));
1624
- const results = await figmaService.downloadImages(fileKey, localPath || "", processedNodes, {
1625
- pngScale,
1626
- returnBuffer
1627
- });
1655
+ const results = await figmaService.downloadImages(
1656
+ fileKey,
1657
+ localPath || "",
1658
+ processedNodes,
1659
+ {
1660
+ pngScale,
1661
+ returnBuffer
1662
+ }
1663
+ );
1628
1664
  return results;
1629
1665
  } catch (error) {
1630
1666
  Logger.error(`Error downloading images from ${fileKey}:`, error);
1631
- throw new Error(`Failed to download images: ${error instanceof Error ? error.message : String(error)}`);
1667
+ throw new Error(
1668
+ `Failed to download images: ${error instanceof Error ? error.message : String(error)}`
1669
+ );
1632
1670
  }
1633
1671
  }
1634
1672
  async function downloadFigmaFrameImage(figmaUrl, options) {
@@ -1648,7 +1686,9 @@ async function downloadFigmaFrameImage(figmaUrl, options) {
1648
1686
  throw new Error("Either apiKey or oauthToken is required");
1649
1687
  }
1650
1688
  if (!returnBuffer && (!localPath || !fileName)) {
1651
- throw new Error("localPath and fileName are required when returnBuffer is false");
1689
+ throw new Error(
1690
+ "localPath and fileName are required when returnBuffer is false"
1691
+ );
1652
1692
  }
1653
1693
  const urlMatch = figmaUrl.match(/figma\.com\/(file|design)\/([a-zA-Z0-9]+)/);
1654
1694
  if (!urlMatch) {
@@ -1657,13 +1697,17 @@ async function downloadFigmaFrameImage(figmaUrl, options) {
1657
1697
  const fileKey = urlMatch[2];
1658
1698
  const nodeIdMatch = figmaUrl.match(/node-id=([^&]+)/);
1659
1699
  if (!nodeIdMatch) {
1660
- throw new Error("No frame node-id found in URL. Please provide a Figma URL with a node-id parameter (e.g., ?node-id=123-456)");
1700
+ throw new Error(
1701
+ "No frame node-id found in URL. Please provide a Figma URL with a node-id parameter (e.g., ?node-id=123-456)"
1702
+ );
1661
1703
  }
1662
1704
  const nodeId = nodeIdMatch[1].replace(/-/g, ":");
1663
1705
  if (fileName) {
1664
1706
  const expectedExtension = `.${format}`;
1665
1707
  if (!fileName.toLowerCase().endsWith(expectedExtension)) {
1666
- throw new Error(`Filename must end with ${expectedExtension} for ${format} format`);
1708
+ throw new Error(
1709
+ `Filename must end with ${expectedExtension} for ${format} format`
1710
+ );
1667
1711
  }
1668
1712
  }
1669
1713
  const figmaService = new FigmaService({
@@ -1672,27 +1716,38 @@ async function downloadFigmaFrameImage(figmaUrl, options) {
1672
1716
  useOAuth: useOAuth && !!oauthToken
1673
1717
  });
1674
1718
  try {
1675
- Logger.log(`Downloading ${format.toUpperCase()} image for frame ${nodeId} from file ${fileKey}`);
1719
+ Logger.log(
1720
+ `Downloading ${format.toUpperCase()} image for frame ${nodeId} from file ${fileKey}`
1721
+ );
1676
1722
  const imageNode = {
1677
1723
  nodeId,
1678
1724
  fileName: fileName || `temp.${format}`
1679
1725
  };
1680
- const results = await figmaService.downloadImages(fileKey, localPath || "", [imageNode], {
1681
- pngScale: format === "png" ? pngScale : void 0,
1682
- returnBuffer
1683
- });
1726
+ const results = await figmaService.downloadImages(
1727
+ fileKey,
1728
+ localPath || "",
1729
+ [imageNode],
1730
+ {
1731
+ pngScale: format === "png" ? pngScale : void 0,
1732
+ returnBuffer
1733
+ }
1734
+ );
1684
1735
  if (results.length === 0) {
1685
1736
  throw new Error(`Failed to download image for frame ${nodeId}`);
1686
1737
  }
1687
1738
  if (returnBuffer) {
1688
1739
  Logger.log(`Successfully downloaded frame image as buffer`);
1689
1740
  } else {
1690
- Logger.log(`Successfully downloaded frame image to: ${results[0].filePath}`);
1741
+ Logger.log(
1742
+ `Successfully downloaded frame image to: ${results[0].filePath}`
1743
+ );
1691
1744
  }
1692
1745
  return results[0];
1693
1746
  } catch (error) {
1694
1747
  Logger.error(`Error downloading frame image from ${fileKey}:`, error);
1695
- throw new Error(`Failed to download frame image: ${error instanceof Error ? error.message : String(error)}`);
1748
+ throw new Error(
1749
+ `Failed to download frame image: ${error instanceof Error ? error.message : String(error)}`
1750
+ );
1696
1751
  }
1697
1752
  }
1698
1753
  function getImageNodeInfo(metadata) {
@@ -1714,7 +1769,9 @@ function enrichMetadataWithImages(metadata, imagePaths, options = {}) {
1714
1769
  let downloadResults;
1715
1770
  if (Array.isArray(imagePaths)) {
1716
1771
  if (imagePaths.length !== metadata.images.length) {
1717
- throw new Error(`Number of image paths (${imagePaths.length}) must match number of images (${metadata.images.length})`);
1772
+ throw new Error(
1773
+ `Number of image paths (${imagePaths.length}) must match number of images (${metadata.images.length})`
1774
+ );
1718
1775
  }
1719
1776
  downloadResults = imagePaths.map((filePath, index) => ({
1720
1777
  filePath,
@@ -1726,16 +1783,23 @@ function enrichMetadataWithImages(metadata, imagePaths, options = {}) {
1726
1783
  downloadResults = imageAssets.map((asset) => {
1727
1784
  const filePath = imagePaths[asset.id];
1728
1785
  if (!filePath) {
1729
- throw new Error(`No image path provided for node ID: ${asset.id}`);
1786
+ return null;
1730
1787
  }
1731
- const imageMetadata = metadata.images.find((img) => img.nodeId === asset.id);
1788
+ const imageMetadata = metadata.images.find(
1789
+ (img) => img.nodeId === asset.id
1790
+ );
1732
1791
  return {
1733
1792
  filePath,
1734
- finalDimensions: imageMetadata?.finalDimensions || { width: 0, height: 0 },
1793
+ finalDimensions: imageMetadata?.finalDimensions || {
1794
+ width: 0,
1795
+ height: 0
1796
+ },
1735
1797
  wasCropped: imageMetadata?.wasCropped || false,
1736
1798
  cssVariables: imageMetadata?.cssVariables
1737
1799
  };
1738
- });
1800
+ }).filter(
1801
+ (result) => result !== null
1802
+ );
1739
1803
  }
1740
1804
  const enrichedNodes = enrichNodesWithImages(
1741
1805
  metadata.nodes,
package/dist/index.js CHANGED
@@ -1535,14 +1535,25 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
1535
1535
  );
1536
1536
  let rawApiResponse;
1537
1537
  if (nodeId) {
1538
- rawApiResponse = await figmaService.getRawNode(fileKey, nodeId, depth || void 0);
1538
+ rawApiResponse = await figmaService.getRawNode(
1539
+ fileKey,
1540
+ nodeId,
1541
+ depth || void 0
1542
+ );
1539
1543
  } else {
1540
- rawApiResponse = await figmaService.getRawFile(fileKey, depth || void 0);
1544
+ rawApiResponse = await figmaService.getRawFile(
1545
+ fileKey,
1546
+ depth || void 0
1547
+ );
1541
1548
  }
1542
- const simplifiedDesign = simplifyRawFigmaObject(rawApiResponse, allExtractors, {
1543
- maxDepth: depth || void 0,
1544
- afterChildren: collapseSvgContainers
1545
- });
1549
+ const simplifiedDesign = simplifyRawFigmaObject(
1550
+ rawApiResponse,
1551
+ allExtractors,
1552
+ {
1553
+ maxDepth: depth || void 0,
1554
+ afterChildren: collapseSvgContainers
1555
+ }
1556
+ );
1546
1557
  Logger.log(
1547
1558
  `Successfully extracted data: ${simplifiedDesign.nodes.length} nodes, ${Object.keys(simplifiedDesign.globalVars?.styles || {}).length} styles`
1548
1559
  );
@@ -1554,7 +1565,9 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
1554
1565
  };
1555
1566
  if (downloadImages) {
1556
1567
  if (!returnBuffer && !localPath) {
1557
- throw new Error("localPath is required when downloadImages is true and returnBuffer is false");
1568
+ throw new Error(
1569
+ "localPath is required when downloadImages is true and returnBuffer is false"
1570
+ );
1558
1571
  }
1559
1572
  Logger.log("Discovering and downloading image assets...");
1560
1573
  const imageAssets = findImageAssets(nodes, globalVars);
@@ -1575,10 +1588,20 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
1575
1588
  );
1576
1589
  if (returnBuffer) {
1577
1590
  result.images = downloadResults;
1578
- Logger.log(`Successfully downloaded ${downloadResults.length} images as buffers`);
1591
+ Logger.log(
1592
+ `Successfully downloaded ${downloadResults.length} images as buffers`
1593
+ );
1579
1594
  } else {
1580
- result.nodes = enrichNodesWithImages(nodes, imageAssets, downloadResults, useRelativePaths, localPath);
1581
- Logger.log(`Successfully downloaded and enriched ${downloadResults.length} images`);
1595
+ result.nodes = enrichNodesWithImages(
1596
+ nodes,
1597
+ imageAssets,
1598
+ downloadResults,
1599
+ useRelativePaths,
1600
+ localPath
1601
+ );
1602
+ Logger.log(
1603
+ `Successfully downloaded and enriched ${downloadResults.length} images`
1604
+ );
1582
1605
  }
1583
1606
  }
1584
1607
  }
@@ -1596,7 +1619,15 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
1596
1619
  }
1597
1620
  }
1598
1621
  async function downloadFigmaImages(figmaUrl, nodes, options) {
1599
- const { apiKey, oauthToken, useOAuth = false, pngScale = 2, localPath, enableLogging = false, returnBuffer = false } = options;
1622
+ const {
1623
+ apiKey,
1624
+ oauthToken,
1625
+ useOAuth = false,
1626
+ pngScale = 2,
1627
+ localPath,
1628
+ enableLogging = false,
1629
+ returnBuffer = false
1630
+ } = options;
1600
1631
  Logger.enableLogging = enableLogging;
1601
1632
  if (!apiKey && !oauthToken) {
1602
1633
  throw new Error("Either apiKey or oauthToken is required");
@@ -1619,14 +1650,21 @@ async function downloadFigmaImages(figmaUrl, nodes, options) {
1619
1650
  ...node,
1620
1651
  nodeId: node.nodeId.replace(/-/g, ":")
1621
1652
  }));
1622
- const results = await figmaService.downloadImages(fileKey, localPath || "", processedNodes, {
1623
- pngScale,
1624
- returnBuffer
1625
- });
1653
+ const results = await figmaService.downloadImages(
1654
+ fileKey,
1655
+ localPath || "",
1656
+ processedNodes,
1657
+ {
1658
+ pngScale,
1659
+ returnBuffer
1660
+ }
1661
+ );
1626
1662
  return results;
1627
1663
  } catch (error) {
1628
1664
  Logger.error(`Error downloading images from ${fileKey}:`, error);
1629
- throw new Error(`Failed to download images: ${error instanceof Error ? error.message : String(error)}`);
1665
+ throw new Error(
1666
+ `Failed to download images: ${error instanceof Error ? error.message : String(error)}`
1667
+ );
1630
1668
  }
1631
1669
  }
1632
1670
  async function downloadFigmaFrameImage(figmaUrl, options) {
@@ -1646,7 +1684,9 @@ async function downloadFigmaFrameImage(figmaUrl, options) {
1646
1684
  throw new Error("Either apiKey or oauthToken is required");
1647
1685
  }
1648
1686
  if (!returnBuffer && (!localPath || !fileName)) {
1649
- throw new Error("localPath and fileName are required when returnBuffer is false");
1687
+ throw new Error(
1688
+ "localPath and fileName are required when returnBuffer is false"
1689
+ );
1650
1690
  }
1651
1691
  const urlMatch = figmaUrl.match(/figma\.com\/(file|design)\/([a-zA-Z0-9]+)/);
1652
1692
  if (!urlMatch) {
@@ -1655,13 +1695,17 @@ async function downloadFigmaFrameImage(figmaUrl, options) {
1655
1695
  const fileKey = urlMatch[2];
1656
1696
  const nodeIdMatch = figmaUrl.match(/node-id=([^&]+)/);
1657
1697
  if (!nodeIdMatch) {
1658
- throw new Error("No frame node-id found in URL. Please provide a Figma URL with a node-id parameter (e.g., ?node-id=123-456)");
1698
+ throw new Error(
1699
+ "No frame node-id found in URL. Please provide a Figma URL with a node-id parameter (e.g., ?node-id=123-456)"
1700
+ );
1659
1701
  }
1660
1702
  const nodeId = nodeIdMatch[1].replace(/-/g, ":");
1661
1703
  if (fileName) {
1662
1704
  const expectedExtension = `.${format}`;
1663
1705
  if (!fileName.toLowerCase().endsWith(expectedExtension)) {
1664
- throw new Error(`Filename must end with ${expectedExtension} for ${format} format`);
1706
+ throw new Error(
1707
+ `Filename must end with ${expectedExtension} for ${format} format`
1708
+ );
1665
1709
  }
1666
1710
  }
1667
1711
  const figmaService = new FigmaService({
@@ -1670,27 +1714,38 @@ async function downloadFigmaFrameImage(figmaUrl, options) {
1670
1714
  useOAuth: useOAuth && !!oauthToken
1671
1715
  });
1672
1716
  try {
1673
- Logger.log(`Downloading ${format.toUpperCase()} image for frame ${nodeId} from file ${fileKey}`);
1717
+ Logger.log(
1718
+ `Downloading ${format.toUpperCase()} image for frame ${nodeId} from file ${fileKey}`
1719
+ );
1674
1720
  const imageNode = {
1675
1721
  nodeId,
1676
1722
  fileName: fileName || `temp.${format}`
1677
1723
  };
1678
- const results = await figmaService.downloadImages(fileKey, localPath || "", [imageNode], {
1679
- pngScale: format === "png" ? pngScale : void 0,
1680
- returnBuffer
1681
- });
1724
+ const results = await figmaService.downloadImages(
1725
+ fileKey,
1726
+ localPath || "",
1727
+ [imageNode],
1728
+ {
1729
+ pngScale: format === "png" ? pngScale : void 0,
1730
+ returnBuffer
1731
+ }
1732
+ );
1682
1733
  if (results.length === 0) {
1683
1734
  throw new Error(`Failed to download image for frame ${nodeId}`);
1684
1735
  }
1685
1736
  if (returnBuffer) {
1686
1737
  Logger.log(`Successfully downloaded frame image as buffer`);
1687
1738
  } else {
1688
- Logger.log(`Successfully downloaded frame image to: ${results[0].filePath}`);
1739
+ Logger.log(
1740
+ `Successfully downloaded frame image to: ${results[0].filePath}`
1741
+ );
1689
1742
  }
1690
1743
  return results[0];
1691
1744
  } catch (error) {
1692
1745
  Logger.error(`Error downloading frame image from ${fileKey}:`, error);
1693
- throw new Error(`Failed to download frame image: ${error instanceof Error ? error.message : String(error)}`);
1746
+ throw new Error(
1747
+ `Failed to download frame image: ${error instanceof Error ? error.message : String(error)}`
1748
+ );
1694
1749
  }
1695
1750
  }
1696
1751
  function getImageNodeInfo(metadata) {
@@ -1712,7 +1767,9 @@ function enrichMetadataWithImages(metadata, imagePaths, options = {}) {
1712
1767
  let downloadResults;
1713
1768
  if (Array.isArray(imagePaths)) {
1714
1769
  if (imagePaths.length !== metadata.images.length) {
1715
- throw new Error(`Number of image paths (${imagePaths.length}) must match number of images (${metadata.images.length})`);
1770
+ throw new Error(
1771
+ `Number of image paths (${imagePaths.length}) must match number of images (${metadata.images.length})`
1772
+ );
1716
1773
  }
1717
1774
  downloadResults = imagePaths.map((filePath, index) => ({
1718
1775
  filePath,
@@ -1724,16 +1781,23 @@ function enrichMetadataWithImages(metadata, imagePaths, options = {}) {
1724
1781
  downloadResults = imageAssets.map((asset) => {
1725
1782
  const filePath = imagePaths[asset.id];
1726
1783
  if (!filePath) {
1727
- throw new Error(`No image path provided for node ID: ${asset.id}`);
1784
+ return null;
1728
1785
  }
1729
- const imageMetadata = metadata.images.find((img) => img.nodeId === asset.id);
1786
+ const imageMetadata = metadata.images.find(
1787
+ (img) => img.nodeId === asset.id
1788
+ );
1730
1789
  return {
1731
1790
  filePath,
1732
- finalDimensions: imageMetadata?.finalDimensions || { width: 0, height: 0 },
1791
+ finalDimensions: imageMetadata?.finalDimensions || {
1792
+ width: 0,
1793
+ height: 0
1794
+ },
1733
1795
  wasCropped: imageMetadata?.wasCropped || false,
1734
1796
  cssVariables: imageMetadata?.cssVariables
1735
1797
  };
1736
- });
1798
+ }).filter(
1799
+ (result) => result !== null
1800
+ );
1737
1801
  }
1738
1802
  const enrichedNodes = enrichNodesWithImages(
1739
1803
  metadata.nodes,
package/dist/lib.d.ts CHANGED
@@ -14,7 +14,7 @@ export interface FigmaMetadataOptions {
14
14
  /** Local path for downloaded images (required if downloadImages is true) */
15
15
  localPath?: string;
16
16
  /** Image format for downloads (defaults to 'png') */
17
- imageFormat?: 'png' | 'svg';
17
+ imageFormat?: "png" | "svg";
18
18
  /** Export scale for PNG images (defaults to 2) */
19
19
  pngScale?: number;
20
20
  /**
@@ -85,7 +85,7 @@ export interface FigmaFrameImageOptions {
85
85
  /** The filename for the downloaded image (must end with .png or .svg, optional if returnBuffer is true) */
86
86
  fileName?: string;
87
87
  /** Image format to download (defaults to 'png') */
88
- format?: 'png' | 'svg';
88
+ format?: "png" | "svg";
89
89
  /** Enable JSON debug log files (defaults to false) */
90
90
  enableLogging?: boolean;
91
91
  /** Return image as ArrayBuffer instead of saving to disk (defaults to false) */
@@ -99,10 +99,10 @@ export interface FigmaFrameImageOptions {
99
99
  * @returns Promise resolving to the extracted metadata
100
100
  */
101
101
  export declare function getFigmaMetadata(figmaUrl: string, options: FigmaMetadataOptions & {
102
- outputFormat: 'json';
102
+ outputFormat: "json";
103
103
  }): Promise<string>;
104
104
  export declare function getFigmaMetadata(figmaUrl: string, options: FigmaMetadataOptions & {
105
- outputFormat: 'yaml';
105
+ outputFormat: "yaml";
106
106
  }): Promise<string>;
107
107
  export declare function getFigmaMetadata(figmaUrl: string, options?: FigmaMetadataOptions): Promise<FigmaMetadataResult>;
108
108
  /**
@@ -155,6 +155,7 @@ export declare function getImageNodeInfo(metadata: FigmaMetadataResult): Array<{
155
155
  * Enrich metadata with saved image file paths
156
156
  *
157
157
  * Use this function after saving images from buffers to disk to add file path information to the metadata.
158
+ * When using the object format, missing image paths for node IDs are skipped rather than throwing errors.
158
159
  *
159
160
  * @param metadata - The metadata result from getFigmaMetadata
160
161
  * @param imagePaths - Array of file paths (ordered) OR object mapping node IDs to paths/URLs
@@ -167,6 +168,7 @@ export declare function getImageNodeInfo(metadata: FigmaMetadataResult): Array<{
167
168
  * const enriched = enrichMetadataWithImages(metadata, ['/path/to/img1.png', '/path/to/img2.png']);
168
169
  *
169
170
  * // Object format (keyed by node ID) - useful after uploading to CDN
171
+ * // Missing node IDs are automatically skipped
170
172
  * const enriched = enrichMetadataWithImages(metadata, {
171
173
  * '123:456': 'https://cdn.example.com/icon.png',
172
174
  * '789:012': 'https://cdn.example.com/logo.png'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figma-metadata-extractor",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
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",