Skip to main content
Question

How to export assets via plugin api?

  • February 8, 2023
  • 7 replies
  • 2043 views

Iuri_Fazli

Hi to all, is it possible to export assets from figma like images, svg?. I need a zip archieve of this files. thanks!

7 replies

Gleb
  • Power Member
  • 4706 replies
  • February 8, 2023

Have you tried searching for existing solutions and plugins API documentation?


Josh_Kulpa
  • New Member
  • 3 replies
  • February 26, 2025
Gleb wrote:

Have you tried searching for existing solutions and plugins API documentation?

I certainly have, and I am no closer to determining how to make this work. What’s worse, is that the plugin API fails completely silently - I can’t even get it to throw errors with extensive error checking. 

Do you have any actual solutions, or are you just going to give another glib response?


tank666
  • 4858 replies
  • March 2, 2025

@Josh_Kulpa, what kind of help do you want? It's not clear from your description what you did. If you provide enough information, including the code you're using/wrote, you'll be more likely to get a concrete answer. And on topic, to export nodes use the exportAsync method, and to pack them into a ZIP archive you can use a library like JSZip.


Josh_Kulpa
  • New Member
  • 3 replies
  • March 5, 2025

 

tank666 wrote:

@Josh_Kulpa, what kind of help do you want? It's not clear from your description what you did. If you provide enough information, including the code you're using/wrote, you'll be more likely to get a concrete answer. And on topic, to export nodes use the exportAsync method, and to pack them into a ZIP archive you can use a library like JSZip.

 

I would like a functioning code example of how to export a frame as .svg and/or .pdf using the plugin API.

Currently, there is no such code example anywhere I can find - not the documentation, not in the community, and not anywhere else.

Here’s the code I put into my test plugin. Any help would be immensely appreciated:

 

const axios = require('axios')
const { performance } = require('perf_hooks')
const fs = require('fs')
const blobStream = require('blob-stream');
const PDFDocument = require('pdfkit')
const SVGtoPDF = require('svg-to-pdfkit');


let axiosInstance = axios.create({
    baseURL: "https://api.figma.com/v1/",
    headers: {
        "X-Figma-Token": process.env.ACCESS_TOKEN
    }
})

const pdfCreator = {
    async getFilePages(key) {
        let start = performance.now()
        let response = await axiosInstance.get(`files/${key}`)
        let end = performance.now()


        console.log(`Got file pages in ${end - start} ms`)

        return this.sortFrames(response.data.document.children[0].children
            .filter(layer => layer.type === "FRAME"))

    },
    sortFrames(pages) {
        let lines = []
        let sortedByHeight = pages.sort((a, b) => a.absoluteBoundingBox.y - b.absoluteBoundingBox.y)
        let finalArray = []
        for (let page in sortedByHeight) {
            let pageItem = sortedByHeight[page]
            let nextPageItem = sortedByHeight[parseInt(page) + 1]
            if (nextPageItem) {
                let seuil = pageItem.absoluteBoundingBox.height / 2

                if (Math.abs(nextPageItem.absoluteBoundingBox.y - pageItem.absoluteBoundingBox.y) <= seuil) {
                    if (lines.length == 0) {
                        lines.push(pageItem)
                    }
                    lines.push(nextPageItem)
                } else {
                    if (lines.length > 0) {
                        let index = sortedByHeight.findIndex((el) => { return el.id === lines[0].id })
                        let sortedLine = lines.sort((a, b) => a.absoluteBoundingBox.x - b.absoluteBoundingBox.x)
                        sortedByHeight.splice(index, lines.length)
                        sortedByHeight.splice(index, 0, ...lines);
                        lines = []
                    }
                }
            }
        }
        return sortedByHeight
    },
    async exportPages(pages, key) {
        let response = await axiosInstance.get(`images/${key}`, {
            params: {
                ids: pages.map(page => page.id).join(','),
                format: "svg"
            }
        })

        for (let page of pages) {
            page.imageUrl = response.data.images[page.id]
        }



        return "ok"
    },
    async getImagesContent(pages) {
        let start = performance.now()
        let imagesPromises = []
        for (let page of pages) {
            let imagePromise = this.getImageContent(page)
            imagesPromises.push(imagePromise)
        }
        await Promise.all(imagesPromises)
        let end = performance.now()
        console.log(`Got images content in ${end - start} ms `)
        return "ok"
    },
    async getImageContent(page) {
        let response = await axios.get(page.imageUrl)
        page.svgContent = response.data
        return "content"
    },
    async createPdf(pages, res) {
        const options = {
            assumePt: true
        }

        let doc = new PDFDocument({ compress: false, size: [pages[0].absoluteBoundingBox.width, pages[0].absoluteBoundingBox.height] })
        let stream = doc.pipe(res);
        SVGtoPDF(doc, pages[0].svgContent, 0, 0, options);
        pages.shift()
        for (let page of pages) {
            doc.addPage({ size: [page.absoluteBoundingBox.width, page.absoluteBoundingBox.height] })
            SVGtoPDF(doc, page.svgContent, 0, 0, options);
        }


        doc.end();
    }
}

module.exports = pdfCreator

 


tank666
  • 4858 replies
  • March 9, 2025

@Josh_Kulpa, are you sure you need to use the Plugin API? From the code you provided, I see that you used the REST API endpoints.

It's really weird that you didn't find any code examples for exporting nodes anywhere, because I found everything on GitHub. Here are some:


Josh_Kulpa
  • New Member
  • 3 replies
  • March 12, 2025
export interface ExportableBytes {
  name: string;
  setting: ExportSettingsImage | ExportSettingsPDF | ExportSettingsSVG;
  bytes: Uint8Array;
}

async function main(nodes): Promise<string> {
  if (!hasValidSelection(selection)) return Promise.resolve("Nothing selected for export")

  let exportableBytes: ExportableBytes[] = []
  for (let node of nodes) {
    let { name, exportSettings } = node
    if (exportSettings.length === 0) {
      exportSettings = [{ format: "PNG", suffix: '', constraint: { type: "SCALE", value: 1 }, contentsOnly: true }]
    }

> for (let node of nodes) {

> let {name, exportsettings } = node

Does this code mean that the export settings have to be provided by the user in the GUI, rather than setting them programatically? 


tank666
  • 4858 replies
  • March 20, 2025

@Josh_Kulpa, the code above takes the exportSettings array as a basis, and it does not matter whether it is added manually by the user in the Figma UI or using the API. Also in your code snippet you can see a block with a condition, where an array with one element of the export settings is programmatically added if the length of this array is 0. But for export it is not necessary to add/modify the exportSettings array, just use the previously mentioned exportAsync method with the settings you need.


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings