figma-metadata-extractor 1.0.15 → 1.0.16
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 +85 -148
- package/dist/index.js +85 -148
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -499,143 +499,67 @@ class FigmaService {
|
|
|
499
499
|
);
|
|
500
500
|
}
|
|
501
501
|
}
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
returnBuffer
|
|
534
|
-
);
|
|
502
|
+
const imageRefs = [
|
|
503
|
+
...new Set(items.map((i) => i.imageRef).filter((r) => !!r))
|
|
504
|
+
];
|
|
505
|
+
const pngNodeIds = items.filter(
|
|
506
|
+
(i) => !i.imageRef && i.nodeId && !i.fileName.toLowerCase().endsWith(".svg")
|
|
507
|
+
).map((i) => i.nodeId);
|
|
508
|
+
const svgNodeIds = items.filter(
|
|
509
|
+
(i) => !i.imageRef && i.nodeId && i.fileName.toLowerCase().endsWith(".svg")
|
|
510
|
+
).map((i) => i.nodeId);
|
|
511
|
+
const [fillUrls, pngUrls, svgUrls] = await Promise.all([
|
|
512
|
+
imageRefs.length > 0 ? this.getImageFillUrls(fileKey) : Promise.resolve({}),
|
|
513
|
+
pngNodeIds.length > 0 ? this.getNodeRenderUrls(fileKey, pngNodeIds, "png", { pngScale }) : Promise.resolve({}),
|
|
514
|
+
svgNodeIds.length > 0 ? this.getNodeRenderUrls(fileKey, svgNodeIds, "svg", { svgOptions }) : Promise.resolve({})
|
|
515
|
+
]);
|
|
516
|
+
const tasks = items.map((item) => {
|
|
517
|
+
const {
|
|
518
|
+
imageRef,
|
|
519
|
+
nodeId,
|
|
520
|
+
fileName,
|
|
521
|
+
needsCropping,
|
|
522
|
+
cropTransform,
|
|
523
|
+
requiresImageDimensions
|
|
524
|
+
} = item;
|
|
525
|
+
let imageUrl;
|
|
526
|
+
if (imageRef) {
|
|
527
|
+
imageUrl = fillUrls[imageRef];
|
|
528
|
+
} else if (nodeId) {
|
|
529
|
+
if (fileName.toLowerCase().endsWith(".svg")) {
|
|
530
|
+
imageUrl = svgUrls[nodeId];
|
|
531
|
+
} else {
|
|
532
|
+
imageUrl = pngUrls[nodeId];
|
|
535
533
|
}
|
|
536
|
-
).filter(
|
|
537
|
-
(task) => task !== null
|
|
538
|
-
);
|
|
539
|
-
if (fillTasks.length > 0) {
|
|
540
|
-
downloadPromises.push(runWithConcurrency(fillTasks, CONCURRENCY_LIMIT));
|
|
541
534
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
);
|
|
547
|
-
const svgNodes = renderNodes.filter(
|
|
548
|
-
(node) => node.fileName.toLowerCase().endsWith(".svg")
|
|
549
|
-
);
|
|
550
|
-
if (pngNodes.length > 0) {
|
|
551
|
-
const pngUrls = await this.getNodeRenderUrls(
|
|
552
|
-
fileKey,
|
|
553
|
-
pngNodes.map((n) => n.nodeId),
|
|
554
|
-
"png",
|
|
555
|
-
{ pngScale }
|
|
556
|
-
);
|
|
557
|
-
const pngTasks = pngNodes.map(
|
|
558
|
-
({
|
|
559
|
-
nodeId,
|
|
560
|
-
fileName,
|
|
561
|
-
needsCropping,
|
|
562
|
-
cropTransform,
|
|
563
|
-
requiresImageDimensions
|
|
564
|
-
}) => {
|
|
565
|
-
const imageUrl = pngUrls[nodeId];
|
|
566
|
-
if (!imageUrl) {
|
|
567
|
-
Logger.log(
|
|
568
|
-
`Skipping PNG render with missing URL for nodeId: ${nodeId}`
|
|
569
|
-
);
|
|
570
|
-
return null;
|
|
571
|
-
}
|
|
572
|
-
return () => downloadAndProcessImage(
|
|
573
|
-
fileName,
|
|
574
|
-
resolvedPath,
|
|
575
|
-
imageUrl,
|
|
576
|
-
needsCropping,
|
|
577
|
-
cropTransform,
|
|
578
|
-
requiresImageDimensions,
|
|
579
|
-
returnBuffer
|
|
580
|
-
).then(
|
|
581
|
-
(result) => ({ ...result, nodeId })
|
|
582
|
-
);
|
|
583
|
-
}
|
|
584
|
-
).filter(
|
|
585
|
-
(task) => task !== null
|
|
586
|
-
);
|
|
587
|
-
if (pngTasks.length > 0) {
|
|
588
|
-
downloadPromises.push(
|
|
589
|
-
runWithConcurrency(pngTasks, CONCURRENCY_LIMIT)
|
|
535
|
+
if (!imageUrl) {
|
|
536
|
+
return () => {
|
|
537
|
+
Logger.log(
|
|
538
|
+
`Skipping missing image for ${imageRef ? `imageRef: ${imageRef}` : `nodeId: ${nodeId}`}`
|
|
590
539
|
);
|
|
591
|
-
|
|
592
|
-
}
|
|
593
|
-
if (svgNodes.length > 0) {
|
|
594
|
-
const svgUrls = await this.getNodeRenderUrls(
|
|
595
|
-
fileKey,
|
|
596
|
-
svgNodes.map((n) => n.nodeId),
|
|
597
|
-
"svg",
|
|
598
|
-
{ svgOptions }
|
|
599
|
-
);
|
|
600
|
-
const svgTasks = svgNodes.map(
|
|
601
|
-
({
|
|
540
|
+
return Promise.resolve({
|
|
602
541
|
nodeId,
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
})
|
|
608
|
-
|
|
609
|
-
if (!imageUrl) {
|
|
610
|
-
Logger.log(
|
|
611
|
-
`Skipping SVG render with missing URL for nodeId: ${nodeId}`
|
|
612
|
-
);
|
|
613
|
-
return null;
|
|
614
|
-
}
|
|
615
|
-
return () => downloadAndProcessImage(
|
|
616
|
-
fileName,
|
|
617
|
-
resolvedPath,
|
|
618
|
-
imageUrl,
|
|
619
|
-
needsCropping,
|
|
620
|
-
cropTransform,
|
|
621
|
-
requiresImageDimensions,
|
|
622
|
-
returnBuffer
|
|
623
|
-
).then(
|
|
624
|
-
(result) => ({ ...result, nodeId })
|
|
625
|
-
);
|
|
626
|
-
}
|
|
627
|
-
).filter(
|
|
628
|
-
(task) => task !== null
|
|
629
|
-
);
|
|
630
|
-
if (svgTasks.length > 0) {
|
|
631
|
-
downloadPromises.push(
|
|
632
|
-
runWithConcurrency(svgTasks, CONCURRENCY_LIMIT)
|
|
633
|
-
);
|
|
634
|
-
}
|
|
542
|
+
originalDimensions: { width: 0, height: 0 },
|
|
543
|
+
finalDimensions: { width: 0, height: 0 },
|
|
544
|
+
wasCropped: false,
|
|
545
|
+
processingLog: ["Skipped: URL not found"]
|
|
546
|
+
});
|
|
547
|
+
};
|
|
635
548
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
549
|
+
return async () => {
|
|
550
|
+
const result = await downloadAndProcessImage(
|
|
551
|
+
fileName,
|
|
552
|
+
resolvedPath,
|
|
553
|
+
imageUrl,
|
|
554
|
+
needsCropping,
|
|
555
|
+
cropTransform,
|
|
556
|
+
requiresImageDimensions,
|
|
557
|
+
returnBuffer
|
|
558
|
+
);
|
|
559
|
+
return { ...result, nodeId };
|
|
560
|
+
};
|
|
561
|
+
});
|
|
562
|
+
return runWithConcurrency(tasks, CONCURRENCY_LIMIT);
|
|
639
563
|
}
|
|
640
564
|
/**
|
|
641
565
|
* Get raw Figma API response for a file (for use with flexible extractors)
|
|
@@ -1596,7 +1520,11 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
|
|
|
1596
1520
|
if (imageAssets.length > 0) {
|
|
1597
1521
|
const imageNodes = imageAssets.map((asset) => ({
|
|
1598
1522
|
nodeId: asset.id,
|
|
1599
|
-
|
|
1523
|
+
imageRef: asset.imageRef,
|
|
1524
|
+
fileName: sanitizeFileName(asset.name) + (asset.filenameSuffix ? `-${asset.filenameSuffix}` : "") + `.${imageFormat}`,
|
|
1525
|
+
needsCropping: asset.needsCropping,
|
|
1526
|
+
cropTransform: asset.cropTransform,
|
|
1527
|
+
requiresImageDimensions: asset.requiresImageDimensions
|
|
1600
1528
|
}));
|
|
1601
1529
|
const downloadResults = await figmaService.downloadImages(
|
|
1602
1530
|
fileKey,
|
|
@@ -1831,28 +1759,37 @@ function sanitizeFileName(name) {
|
|
|
1831
1759
|
return name.replace(/[^a-z0-9]/gi, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").toLowerCase();
|
|
1832
1760
|
}
|
|
1833
1761
|
function findImageAssets(nodes, globalVars) {
|
|
1834
|
-
const
|
|
1762
|
+
const assets = [];
|
|
1835
1763
|
function traverse(node) {
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1764
|
+
if (node.type === "IMAGE-SVG") {
|
|
1765
|
+
assets.push({
|
|
1766
|
+
...node,
|
|
1767
|
+
id: node.id,
|
|
1768
|
+
name: node.name,
|
|
1769
|
+
type: "render"
|
|
1770
|
+
});
|
|
1771
|
+
} else if (node.fills && typeof node.fills === "string") {
|
|
1772
|
+
const fillData = globalVars?.styles?.[node.fills];
|
|
1773
|
+
if (Array.isArray(fillData)) {
|
|
1774
|
+
const imageFill = fillData.find((f) => f.type === "IMAGE");
|
|
1775
|
+
if (imageFill) {
|
|
1776
|
+
assets.push({
|
|
1777
|
+
...node,
|
|
1778
|
+
id: node.id,
|
|
1779
|
+
name: node.name,
|
|
1780
|
+
type: "fill",
|
|
1781
|
+
imageRef: imageFill.imageRef,
|
|
1782
|
+
...imageFill.imageDownloadArguments
|
|
1783
|
+
});
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1839
1786
|
}
|
|
1840
1787
|
if (node.children && Array.isArray(node.children)) {
|
|
1841
1788
|
node.children.forEach(traverse);
|
|
1842
1789
|
}
|
|
1843
1790
|
}
|
|
1844
1791
|
nodes.forEach(traverse);
|
|
1845
|
-
return
|
|
1846
|
-
}
|
|
1847
|
-
function hasImageFill(node, globalVars) {
|
|
1848
|
-
if (!node.fills || typeof node.fills !== "string") {
|
|
1849
|
-
return false;
|
|
1850
|
-
}
|
|
1851
|
-
const fillData = globalVars?.styles?.[node.fills];
|
|
1852
|
-
if (!fillData || !Array.isArray(fillData)) {
|
|
1853
|
-
return false;
|
|
1854
|
-
}
|
|
1855
|
-
return fillData.some((fill) => fill?.type === "IMAGE");
|
|
1792
|
+
return assets;
|
|
1856
1793
|
}
|
|
1857
1794
|
function enrichNodesWithImages(nodes, imageAssets, downloadResults, useRelativePaths = true, localPath) {
|
|
1858
1795
|
const imageMap = /* @__PURE__ */ new Map();
|
package/dist/index.js
CHANGED
|
@@ -497,143 +497,67 @@ class FigmaService {
|
|
|
497
497
|
);
|
|
498
498
|
}
|
|
499
499
|
}
|
|
500
|
-
const
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
returnBuffer
|
|
532
|
-
);
|
|
500
|
+
const imageRefs = [
|
|
501
|
+
...new Set(items.map((i) => i.imageRef).filter((r) => !!r))
|
|
502
|
+
];
|
|
503
|
+
const pngNodeIds = items.filter(
|
|
504
|
+
(i) => !i.imageRef && i.nodeId && !i.fileName.toLowerCase().endsWith(".svg")
|
|
505
|
+
).map((i) => i.nodeId);
|
|
506
|
+
const svgNodeIds = items.filter(
|
|
507
|
+
(i) => !i.imageRef && i.nodeId && i.fileName.toLowerCase().endsWith(".svg")
|
|
508
|
+
).map((i) => i.nodeId);
|
|
509
|
+
const [fillUrls, pngUrls, svgUrls] = await Promise.all([
|
|
510
|
+
imageRefs.length > 0 ? this.getImageFillUrls(fileKey) : Promise.resolve({}),
|
|
511
|
+
pngNodeIds.length > 0 ? this.getNodeRenderUrls(fileKey, pngNodeIds, "png", { pngScale }) : Promise.resolve({}),
|
|
512
|
+
svgNodeIds.length > 0 ? this.getNodeRenderUrls(fileKey, svgNodeIds, "svg", { svgOptions }) : Promise.resolve({})
|
|
513
|
+
]);
|
|
514
|
+
const tasks = items.map((item) => {
|
|
515
|
+
const {
|
|
516
|
+
imageRef,
|
|
517
|
+
nodeId,
|
|
518
|
+
fileName,
|
|
519
|
+
needsCropping,
|
|
520
|
+
cropTransform,
|
|
521
|
+
requiresImageDimensions
|
|
522
|
+
} = item;
|
|
523
|
+
let imageUrl;
|
|
524
|
+
if (imageRef) {
|
|
525
|
+
imageUrl = fillUrls[imageRef];
|
|
526
|
+
} else if (nodeId) {
|
|
527
|
+
if (fileName.toLowerCase().endsWith(".svg")) {
|
|
528
|
+
imageUrl = svgUrls[nodeId];
|
|
529
|
+
} else {
|
|
530
|
+
imageUrl = pngUrls[nodeId];
|
|
533
531
|
}
|
|
534
|
-
).filter(
|
|
535
|
-
(task) => task !== null
|
|
536
|
-
);
|
|
537
|
-
if (fillTasks.length > 0) {
|
|
538
|
-
downloadPromises.push(runWithConcurrency(fillTasks, CONCURRENCY_LIMIT));
|
|
539
532
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
);
|
|
545
|
-
const svgNodes = renderNodes.filter(
|
|
546
|
-
(node) => node.fileName.toLowerCase().endsWith(".svg")
|
|
547
|
-
);
|
|
548
|
-
if (pngNodes.length > 0) {
|
|
549
|
-
const pngUrls = await this.getNodeRenderUrls(
|
|
550
|
-
fileKey,
|
|
551
|
-
pngNodes.map((n) => n.nodeId),
|
|
552
|
-
"png",
|
|
553
|
-
{ pngScale }
|
|
554
|
-
);
|
|
555
|
-
const pngTasks = pngNodes.map(
|
|
556
|
-
({
|
|
557
|
-
nodeId,
|
|
558
|
-
fileName,
|
|
559
|
-
needsCropping,
|
|
560
|
-
cropTransform,
|
|
561
|
-
requiresImageDimensions
|
|
562
|
-
}) => {
|
|
563
|
-
const imageUrl = pngUrls[nodeId];
|
|
564
|
-
if (!imageUrl) {
|
|
565
|
-
Logger.log(
|
|
566
|
-
`Skipping PNG render with missing URL for nodeId: ${nodeId}`
|
|
567
|
-
);
|
|
568
|
-
return null;
|
|
569
|
-
}
|
|
570
|
-
return () => downloadAndProcessImage(
|
|
571
|
-
fileName,
|
|
572
|
-
resolvedPath,
|
|
573
|
-
imageUrl,
|
|
574
|
-
needsCropping,
|
|
575
|
-
cropTransform,
|
|
576
|
-
requiresImageDimensions,
|
|
577
|
-
returnBuffer
|
|
578
|
-
).then(
|
|
579
|
-
(result) => ({ ...result, nodeId })
|
|
580
|
-
);
|
|
581
|
-
}
|
|
582
|
-
).filter(
|
|
583
|
-
(task) => task !== null
|
|
584
|
-
);
|
|
585
|
-
if (pngTasks.length > 0) {
|
|
586
|
-
downloadPromises.push(
|
|
587
|
-
runWithConcurrency(pngTasks, CONCURRENCY_LIMIT)
|
|
533
|
+
if (!imageUrl) {
|
|
534
|
+
return () => {
|
|
535
|
+
Logger.log(
|
|
536
|
+
`Skipping missing image for ${imageRef ? `imageRef: ${imageRef}` : `nodeId: ${nodeId}`}`
|
|
588
537
|
);
|
|
589
|
-
|
|
590
|
-
}
|
|
591
|
-
if (svgNodes.length > 0) {
|
|
592
|
-
const svgUrls = await this.getNodeRenderUrls(
|
|
593
|
-
fileKey,
|
|
594
|
-
svgNodes.map((n) => n.nodeId),
|
|
595
|
-
"svg",
|
|
596
|
-
{ svgOptions }
|
|
597
|
-
);
|
|
598
|
-
const svgTasks = svgNodes.map(
|
|
599
|
-
({
|
|
538
|
+
return Promise.resolve({
|
|
600
539
|
nodeId,
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
})
|
|
606
|
-
|
|
607
|
-
if (!imageUrl) {
|
|
608
|
-
Logger.log(
|
|
609
|
-
`Skipping SVG render with missing URL for nodeId: ${nodeId}`
|
|
610
|
-
);
|
|
611
|
-
return null;
|
|
612
|
-
}
|
|
613
|
-
return () => downloadAndProcessImage(
|
|
614
|
-
fileName,
|
|
615
|
-
resolvedPath,
|
|
616
|
-
imageUrl,
|
|
617
|
-
needsCropping,
|
|
618
|
-
cropTransform,
|
|
619
|
-
requiresImageDimensions,
|
|
620
|
-
returnBuffer
|
|
621
|
-
).then(
|
|
622
|
-
(result) => ({ ...result, nodeId })
|
|
623
|
-
);
|
|
624
|
-
}
|
|
625
|
-
).filter(
|
|
626
|
-
(task) => task !== null
|
|
627
|
-
);
|
|
628
|
-
if (svgTasks.length > 0) {
|
|
629
|
-
downloadPromises.push(
|
|
630
|
-
runWithConcurrency(svgTasks, CONCURRENCY_LIMIT)
|
|
631
|
-
);
|
|
632
|
-
}
|
|
540
|
+
originalDimensions: { width: 0, height: 0 },
|
|
541
|
+
finalDimensions: { width: 0, height: 0 },
|
|
542
|
+
wasCropped: false,
|
|
543
|
+
processingLog: ["Skipped: URL not found"]
|
|
544
|
+
});
|
|
545
|
+
};
|
|
633
546
|
}
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
547
|
+
return async () => {
|
|
548
|
+
const result = await downloadAndProcessImage(
|
|
549
|
+
fileName,
|
|
550
|
+
resolvedPath,
|
|
551
|
+
imageUrl,
|
|
552
|
+
needsCropping,
|
|
553
|
+
cropTransform,
|
|
554
|
+
requiresImageDimensions,
|
|
555
|
+
returnBuffer
|
|
556
|
+
);
|
|
557
|
+
return { ...result, nodeId };
|
|
558
|
+
};
|
|
559
|
+
});
|
|
560
|
+
return runWithConcurrency(tasks, CONCURRENCY_LIMIT);
|
|
637
561
|
}
|
|
638
562
|
/**
|
|
639
563
|
* Get raw Figma API response for a file (for use with flexible extractors)
|
|
@@ -1594,7 +1518,11 @@ async function getFigmaMetadata(figmaUrl, options = {}) {
|
|
|
1594
1518
|
if (imageAssets.length > 0) {
|
|
1595
1519
|
const imageNodes = imageAssets.map((asset) => ({
|
|
1596
1520
|
nodeId: asset.id,
|
|
1597
|
-
|
|
1521
|
+
imageRef: asset.imageRef,
|
|
1522
|
+
fileName: sanitizeFileName(asset.name) + (asset.filenameSuffix ? `-${asset.filenameSuffix}` : "") + `.${imageFormat}`,
|
|
1523
|
+
needsCropping: asset.needsCropping,
|
|
1524
|
+
cropTransform: asset.cropTransform,
|
|
1525
|
+
requiresImageDimensions: asset.requiresImageDimensions
|
|
1598
1526
|
}));
|
|
1599
1527
|
const downloadResults = await figmaService.downloadImages(
|
|
1600
1528
|
fileKey,
|
|
@@ -1829,28 +1757,37 @@ function sanitizeFileName(name) {
|
|
|
1829
1757
|
return name.replace(/[^a-z0-9]/gi, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").toLowerCase();
|
|
1830
1758
|
}
|
|
1831
1759
|
function findImageAssets(nodes, globalVars) {
|
|
1832
|
-
const
|
|
1760
|
+
const assets = [];
|
|
1833
1761
|
function traverse(node) {
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1762
|
+
if (node.type === "IMAGE-SVG") {
|
|
1763
|
+
assets.push({
|
|
1764
|
+
...node,
|
|
1765
|
+
id: node.id,
|
|
1766
|
+
name: node.name,
|
|
1767
|
+
type: "render"
|
|
1768
|
+
});
|
|
1769
|
+
} else if (node.fills && typeof node.fills === "string") {
|
|
1770
|
+
const fillData = globalVars?.styles?.[node.fills];
|
|
1771
|
+
if (Array.isArray(fillData)) {
|
|
1772
|
+
const imageFill = fillData.find((f) => f.type === "IMAGE");
|
|
1773
|
+
if (imageFill) {
|
|
1774
|
+
assets.push({
|
|
1775
|
+
...node,
|
|
1776
|
+
id: node.id,
|
|
1777
|
+
name: node.name,
|
|
1778
|
+
type: "fill",
|
|
1779
|
+
imageRef: imageFill.imageRef,
|
|
1780
|
+
...imageFill.imageDownloadArguments
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1837
1784
|
}
|
|
1838
1785
|
if (node.children && Array.isArray(node.children)) {
|
|
1839
1786
|
node.children.forEach(traverse);
|
|
1840
1787
|
}
|
|
1841
1788
|
}
|
|
1842
1789
|
nodes.forEach(traverse);
|
|
1843
|
-
return
|
|
1844
|
-
}
|
|
1845
|
-
function hasImageFill(node, globalVars) {
|
|
1846
|
-
if (!node.fills || typeof node.fills !== "string") {
|
|
1847
|
-
return false;
|
|
1848
|
-
}
|
|
1849
|
-
const fillData = globalVars?.styles?.[node.fills];
|
|
1850
|
-
if (!fillData || !Array.isArray(fillData)) {
|
|
1851
|
-
return false;
|
|
1852
|
-
}
|
|
1853
|
-
return fillData.some((fill) => fill?.type === "IMAGE");
|
|
1790
|
+
return assets;
|
|
1854
1791
|
}
|
|
1855
1792
|
function enrichNodesWithImages(nodes, imageAssets, downloadResults, useRelativePaths = true, localPath) {
|
|
1856
1793
|
const imageMap = /* @__PURE__ */ new Map();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "figma-metadata-extractor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
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",
|