Skip to content

Instantly share code, notes, and snippets.

@stuartlangridge
Last active March 4, 2024 19:04
Show Gist options
  • Save stuartlangridge/2ec64a7d7793d5b9d24be0cf18550ff6 to your computer and use it in GitHub Desktop.
Save stuartlangridge/2ec64a7d7793d5b9d24be0cf18550ff6 to your computer and use it in GitHub Desktop.
Exporting an SVG from Figma and identifying which SVG elements in the exported file correspond to which objects in Figma
const getSvgNamesForNodes = () => {
// this is guesswork. When Figma has two nodes with the same name (say, "Union"),
// it serialises them into SVG with names "Union" and "Union_2", but it's not
// clear which one becomes "Union" and which "Union_2". It is theorised that this
// is done in the same order that .findAll returns, so we make use of that.
// Figma might decide to change this at any time, of course. It would be much
// nicer if there were an SVG export option which also serialised getPluginData()
// data as data-* attributes in the output SVG, but there isn't, yet.
let names = {};
let nameIndices = {};
window.figma.currentPage.findAll().forEach(o => {
let index = "";
if (nameIndices[o.name]) {
index = "_" + (nameIndices[o.name] + 1);
nameIndices[o.name] += 1
} else {
nameIndices[o.name] = 1;
}
names[o.name + index] = o;
});
return names;
}
// grab the current page as an SVG
const im = await figma.currentPage.exportAsync({format:"SVG", svgIdAttribute: true});
const svgtext = new TextDecoder("utf-8").decode(im);
// parse it into a DOM
const parser = new DOMParser();
const doc = parser.parseFromString(svgtext, "image/svg+xml");
// get the calculated names for each Figma node
const mapping = getSvgNamesForNodes();
// use the names to pair each SVG element with its corresponding Figma node, and copy some info across
for (let calculated_svgname in mapping) {
let svgel = doc.getElementById(calculated_svgname);
if (!svgel) { continue; }
svgel.setAttribute("data-figma-nodeid", mapping[calculated_svgname].id);
}
// there should now be no SVG elements with an ID but without a nodeid: check, for paranoia
const unmatched = doc.querySelectorAll("[id]:not([data-figma-nodeid])");
if (unmatched.length > 0) {
console.warn("Failed to match up the following nodes:", unmatched);
}
// serialise the DOM back into svg text
const finaltext = new XMLSerializer().serializeToString(doc);
console.log(finaltext);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment