Giter Club home page Giter Club logo

figma-export's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

figma-export's Issues

Support Component Instance

Hi, thanks for this great library.

One issue I'm facing is that my designer created a page on Figma with all of our icons as "component instance".

If I console.log the figma.ts getComponents for the node type, it returns as instances:

const getComponents = (children = [], filter = () => true, pathToComponent = []) => {
    let components = [];
    children.forEach((node) => {
        console.log(node.type) // INSTANCE
        if (node.type === 'COMPONENT' && filter(node)) {
            components.push(Object.assign(Object.assign({}, node), {
                svg: '', figmaExport: {
                    id: node.id,
                    dirname: (0, path_1.dirname)(node.name),
                    basename: (0, path_1.basename)(node.name),
                    pathToComponent,
                }
            }));
            return;
        }
        if ('children' in node) {
            components = [
                ...components,
                ...getComponents((node.children), filter, [...pathToComponent, { name: node.name, type: node.type }]),
            ];
        }
    });
    return components;
};

Can we support components instances on the CLI? Or is this a super narrow case and I should fork this repo?

Thanks in advance

Ability to export text/color styles from a Library

Hi there! I might be misunderstanding what this tool is already capable of, but is there a way to export all colors / font styles from a Figma Library (not just files)?

If not, I'd like to request the feature here. Nice work on this!

Getting ERR_REQUIRE_ESM

Hi there, I'm started to get these error when I run figma-export use-confg command.


const stripAnsi = require('strip-ansi');
                  ^
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/XXXXX/node_modules/strip-ansi/index.js from /Users/XXXXX/node_modules/ora/index.js not supported.
Instead change the require of /Users/XXXXX/node_modules/strip-ansi/index.js in /Users/XXXXX/node_modules/ora/index.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (/Users/XXXXX/node_modules/ora/index.js:7:19) {
  code: 'ERR_REQUIRE_ESM'
}

My config

const fs = require("fs");
const path = require("path");

const customOutput = async (pages) => {
  const output = "./kit/primitives/Icon/resources";

  fs.mkdirSync(output, { recursive: true });

  console.log("OUTPUT", output);

  try {
    const Icons = [];
    pages.forEach(({ name: pageName, components }) => {
      console.log("PAGE", pageName);
      components
        .filter(({ name }) => name.startsWith("Icons/"))
        .forEach(({ name, svg, id }) => {
          const componentName = name.replaceAll("Icons/", "");
          const filePath = path.resolve(output, `${componentName}.tsx`);

          let p = filePath.split("/");
          p.pop();
          p = p.join("/");

          fs.mkdirSync(p, { recursive: true });

          svg = svg
            .replaceAll(`fill-rule`, "fillRule")
            .replaceAll(`clip-rule`, "clipRule")
            .replaceAll(`fill="#121120"`, "")
            .replaceAll(`fill="#000000"`, "")
            .replaceAll(`<svg `, "<svg className={props.className}");

          fs.writeFileSync(
            filePath,
            `
            import React from "react";

            export const Icon${componentName} = (props: { className?:string }) => {
              return (${svg})
            }
          `,
          );
          Icons.push(componentName);
          console.log("GENERATED", componentName);
        });
    });

    const index = `
    import dynamic from "next/dynamic";

    export const RawIcon: Record<string, any> = {
      ${Icons.map(
        (i) =>
          `"${i}": dynamic<any>(() => import("./${i}").then(m=> m.Icon${i})) `,
      ).join(",\n")}
    }

    export type IconName = ${Icons.map((i) => `"${i}"`).join(" | ")}
    `;

    const filePath = path.resolve(output, `index.tsx`);
    fs.writeFileSync(filePath, index);
    console.log("GENERATED", "INDEX");
  } catch (e) {
    console.error(e);
  }
};

module.exports = {
  commands: [
    [
      "components",
      {
        fileId: "xxxx",
        onlyFromPages: ["assets"],
        transformers: [
          require("@figma-export/transform-svg-with-svgo")({
            plugins: ["removeViewBox", "removeDimensions", "cleanupIDs"],
          }),
        ],
        outputters: [customOutput],
      },
    ],
  ],
};

Node.js Version: v20.11.0

Asset name on transformer arguments

I am working on a custom transformer to transform components SVGs based on the asset name on Figma.
Example:

  • icon/mono > remove fills
  • icon/color > do nothing

Is there any way to get the asset name on transformers?

Expose the component ID in the ComponentExtras

Currently the function getBasename in the output-components-as-svg module uses only the basename value to generate the file name in output:

getBasename = (options): string => `${options.basename}.svg`,

But if the icons are variants, there may be cases in which two different variants have the same name (because of how Figma assigns the name to the variants). For example, we have a set of icons as component sets, where each one of them has two sizes, (each one is a component, with two variants, and a property with two values sm and md assigned to each one of them).

When we export the icons, even if the icons' (parent) component set have different names, the variants all have name Size=sm or Size=md so each icon exported overrides the previous one, and we end up with only two files (one called Size=sm.svg` and the other Size=md.svg`.

What I propose here is to expose also the ID of the component (which we know is unique) so that a consumer of the library can create their own unique basename and use the getBasename function (passed to the outputComponentsAsSvg outputter) to override the default behaviour, eg.

getBasename: (options): string => `${options.id}__${options.basename}.svg`

The way in which we can expose it is to add an id key to ComponentExtras type, and then in the getComponents method add the id value to the figmaExport object.

I'll submit a PR for this small change.

Error: ENOENT: no such file or directory

Hey there,

Am I doing something wrong here?

The error;

Error: ENOENT: no such file or directory, open '/foo/bar/output/Resources-icons/wish.svg'
    at components.forEach (~/bar/node_modules/@figma-export/output-components-as-svg/index.js:11:20)
    at Array.forEach (<anonymous>)
    at pages.forEach (~/bar/node_modules/@figma-export/output-components-as-svg/index.js:9:24)
    at Array.forEach (<anonymous>)
    at ~/bar/node_modules/@figma-export/output-components-as-svg/index.js:8:15
    at Promise.all.outputters.map (~/bar/node_modules/@figma-export/core/lib/export-components.js:21:53)
    at Array.map (<anonymous>)
    at Object.components (~/bar/node_modules/@figma-export/core/lib/export-components.js:21:34)

.figmaexportrc.js

module.exports = {
  commands: [
    [
      "components",
      {
        fileId: "XXX",
        onlyFromPages: ["Resources"],
        transformers: [
          require("@figma-export/transform-svg-with-svgo")({
            plugins: [{ removeViewBox: false }, { removeDimensions: true }]
          })
        ],
        outputters: [
          require("@figma-export/output-components-as-svg")({
            output: "./output"
          })
        ]
      }
    ]
  ]
};

run command

figma-export use-config

Apple Silicon Support

Hi, looks like you restricted node version on your package.json, we want to use it under node v16. If this package works under 16 can you update the package.json.

AWS Export Errors

Firstly, just want to say thank you so much for your work on this fantastic module! It has been awesome to be able to use the figma API so easily. My use case involves a very large icon library with many different variations and sizes (1000s of files).

Every so often, I get stack traces like this:

fetching components 2000/3953
fetching components 2001/3953
fetching components 2002/3953
fetching components 2003/3953
fetching components 2004/3953
fetching components 2005/3953
Error: while fetching svg "https://s3-us-west-2.amazonaws.com/figma-alpha-api/img/xxxxxxxxxxxxxxxxxxxxxxxxxxxxx": getaddrinfo ENOTFOUND s3-us-west-2.amazonaws.com
    at /Users/amcolash/dev/figma-export/node_modules/@figma-export/core/dist/lib/utils.js:47:15
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

It seems like something on Figma's side breaks once in a while or aws throttles the downloads. This issue is a bit of a feature request and of an ask for help. If I do have time and you have pointers, I might be able to whip up a PR.

It would be useful for my case to set a "retry" value in the config to retry the download - say maybe once or twice for a file before it totally crashes the export halfway through. In a scenario where the download fails, wait a moment, then retry until a the failure count is too great or the download succeeds.

Unfortunately, this behavior is very spotty and not easy to reproduce.

Any help would be appreciated. Right now, I have my CI job set to retry on failure, but that incurs a lot of overhead instead of just retrying the download on this module side. Thanks!

Export styles to JSON

Hi, it would be great if it was possible to export the styles to a JSON file with an object-structure that follows the same kind of naming convention you have in your figma file.

Example style name in Figma:

Light theme / Primary / Main -> #ff0000
Dark theme / Primary / Main -> #00ff00

JSON output:

{ "Light theme":{ "Primary":{ "main": " #ff000" } }, "Dark theme":{ "Primary":{ "main": " #00ff00" } } }

onlyFromPages has no effect when exporting styles

Currently when using onlyFromPages to export styles, it makes no difference to output whether it is specified or not.

What happens is that the result of getPages is always empty because it only returns page nodes that have at least one component associated with them. client.file request with depth of 1 does not return any child nodes for a page:

const ids = getPages((document), { only: onlyFromPages })
.map((page) => page.id);

.filter((page) => page.components.length > 0);

At first I thought that it is sufficient to increase the depth of the initial file request by one to fetch the next level of nodes but eventually realized that the test will still fail when there are no components at the top level of page (for example when using it with octicons-by-github page from the demo file).

Removing depth from the file request will work around that limitation, but then another question arises - is it valid to restrict styles to be exported only from pages if they contain at least one component? Is there any particular reason as to why exporting styles requires a component to be present at the moment?


PS: My goal is to enable exporting both components and styles from hierarchies that may be sub-sections of a page (eg a sub-node with all of its children) which should be a more general case of how onlyFromPages is supposed to work.

Request failed with status code 400

Hello,

I'm testing figma export cli, in the goal of exporting svgs from figma file.
I created a Personal Access Token, and checked that using it through curl commands works fine.

But the same thing does not work through @figma-export/cli
I get the following error whatever the configuration I use

✖ fetching document
Error: while fetching file "tGSuhDDoppmJXa8Y5Pinq8": Request failed with status code 400
at /Users/helier_e/Dev/tests/figma/figma-export-cli/node_modules/@figma-export/core/dist/lib/export-components.js:21:15
at processTicksAndRejections (node:internal/process/task_queues:96:5)

I use this npm script : dotenv figma-export use-config
With an .env file providing FIGMA_TOKEN, and the following .figmaexportrc.js file content

module.exports = {
  commands: [
    [
      "components",
      {
        fileId: "tGSuhDDoppmJXa8Y5Pinq8",
        outputters: [
          require("@figma-export/output-components-as-svg")({
            output: "./dist/svg",
          }),
        ],
      },
    ],
  ],
};

Any hint on how I can debug this ?
I'm operating through a corporate proxy, but curl commands work (I have HTTP_PROXY and HTTPS_PROXY env vars defined)
I thing it uses axios internally, that should also take into account HTTP_PROXY env vars.

Am I missing something ? Or how can I debug the error further ?

Export typescript enum based on Icons export from Figma

Hi, good morning, and thanks for the amazing job on this cli. 🚀

I've been using this for a while on a project with Typescript and I would like to know if there is any possibility to add an export for a given enum containing the file definitions for every icon.

The idea would be to read the index.js file and based on that append every entry on the file to an enum. This would be a handful when using something like this:

import * as Icons from "./foo";

export enum IconsEnum {
  "foo" = "foo",
}

const Icon = ({ name }: { name: keyof typeof IconsEnum  }) => {
    const Component = Icon[Name];
    
    return <Component />;
}

I would be glad tying to figure this out at PR because it was quite difficult to handle the fetching of icons/parse from Figma before finding this library. 😅

Html node name from figma node name

Currently there is an option to get the name of the figma node as a class name.

Would it be possible to have a similar option to directly have a custom html node name?
In that case, we would be able to directly use your html as our Angular template file.

Thanks in advance for your answer.

Benjamin

SVGO Transformer Error: Plugin name should be specified

I'm getting a "Plugin name should be specified" error when using the SVGO transformer. Can anyone please help?

Snippet

require("dotenv").config();

module.exports = {
	commands: [
		[
			"components",
			{
				fileId: process.env.FILE_ID,
				onlyFromPages: ["solid"],
				transformers: [
					require("@figma-export/transform-svg-with-svgo")({
						plugins: [
							{ removeViewBox: false },
							{ removeDimensions: true },
						],
					}),
				],
				outputters: [
					// https://www.npmjs.com/package/@figma-export/output-components-as-es6
					require("@figma-export/output-components-as-svg")({
						output: "./",
					}),
				],
			},
		],
	],
};

Error

✖ preparing components
Error: Plugin name should be specified
    at resolvePluginConfig (/Users/bacon/Documents/Projects/Ecosphere Icons/node_modules/svgo/lib/svgo/config.js:113:13)
    at Array.map (<anonymous>)
    at optimize (/Users/bacon/Documents/Projects/Ecosphere Icons/node_modules/svgo/lib/svgo.js:50:37)
    at optimize (/Users/bacon/Documents/Projects/Ecosphere Icons/node_modules/svgo/lib/svgo-node.js:97:10)
    at /Users/bacon/Documents/Projects/Ecosphere Icons/node_modules/@figma-export/transform-svg-with-svgo/dist/index.js:14:44
    at Generator.next (<anonymous>)
    at /Users/bacon/Documents/Projects/Ecosphere Icons/node_modules/@figma-export/transform-svg-with-svgo/dist/index.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/bacon/Documents/Projects/Ecosphere Icons/node_modules/@figma-export/transform-svg-with-svgo/dist/index.js:4:12)
    at /Users/bacon/Documents/Projects/Ecosphere Icons/node_modules/@figma-export/transform-svg-with-svgo/dist/index.js:13:21

Support latest node version

Those packages specify the latest valid node version as <= 13.x. Is this intentional? Anything that breaks with the latest 14.x release and I could help with? or should this just be adjusted in the package.json?

error @figma-export/[email protected]: The engine "node" is incompatible with this module. Expected version ">= 8.3 <= 13.x". Got "14.5.0"

SVGR additional options (index.js)

Hi! I was testing the current SVGR outputter but I miss some extra configuration.

My suggestions:

  • When creating components in .tsx (getFileExtension) index file should be index.ts, not index.js
  • Add an option to customize exports from that index.ts export { default as ${reactComponentName} } from './${basename}';

I've created a fork for this, if you think this could be useful I can create a PR here

Thanks!

Export styles from page or node

Hello.
First i wanna thank you for great figma export module, it`s really cool!

I need to export styles from specific page of figma to keep the best structure of our design system in figma. Figma-js accepts ids params to get only certain nodes, it seems that's what I need.
image

But @figma-export/output-styles-as-sass doesn`t accept ids. it would be nice to be able to load only certain nodes.

feature request: separate out component name and component file name

for '@figma-export/output-components-as-svgr'

the option getComponentName also is set as the component file name

in our use case, i would like the file name to be kebab-case but the component name to still be pascal-case but that is not currently supported. I can set the getComponentName to return the kebab-case component names but that is not valid javascript component names

perhaps we can add an option that is getComponentFileName

ECONNRESET

I'm getting UnhandledPromiseRejectionWarning: Error: read ECONNRESET,

Is there a debug mode so I can understand what's happening here?

my config file:

module.exports = {
  commands: [
    [
      "components",
      {
        fileId: "XXXX",
        onlyFromPages: ["icons", "illustrations"],
        transformers: [
          require("@figma-export/transform-svg-with-svgo")({
            plugins: [{ removeViewBox: false }, { removeDimensions: true }],
          }),
        ],
        outputters: [
          async (pages) => {
            const output = "./public";
            fs.mkdirSync(output, { recursive: true });
            console.log("OUTPUT", output);
            try {
              pages.forEach(({ name: pageName, components }) => {
                console.log("PAGE", pageName);
                components.forEach(({ name: componentName, svg }) => {
                  const filePath = path.resolve(output, `${componentName}.svg`);

                  let p = filePath.split("/");
                  p.pop();
                  p = p.join("/");

                  fs.mkdirSync(p, { recursive: true });

                  fs.writeFileSync(filePath, svg);

                  console.log("GENERATED", filePath, componentName);
                });
              });
            } catch (e) {
              console.log(e);
            }
          },
        ],
      },
    ],
  ],
};

Error: 'document' is missing.

Hi,

Somewhere in the last week, something on —as far as I can gather— Figma's side changed causing the package to fail with the error Error: 'document' is missing. It also does this on your example project, see screenshot:

Screenshot 2024-03-26 at 09 28 59

Drop Node.js 12 and 14 support

Drop Node.js 12 and 14 support starting from figma-export v5.0.0.
This will ensure a massive update to the latest dependencies and remove all vulnerability issues.

Commands other than `components`

Firstly - thanks for this awesome tool!

I would like to extract effect styles and paint styles from my Figma files... We're already using this script to extract components so it would be awesome if we could also use it for that purpose.

I was wondering if there is any plan to handle commands other than components? If you don't have plans to add it yourself, would you be interested in a PR adding it? If so then do you have any suggestions on where to slot the functionality in?

Config file option to not include React

Would be nice to have an option in my config file where I can define if I want to import React or which parts of it, since Babel already takes care of it with the "runtime": "automatic" option

image

image

.babelrc

"presets": [
   [
     "@nrwl/react/babel", {
       "runtime": "automatic",
       "useBuiltIns": "usage"
     }
   ]
 ],

DOCS

Errors when using with ts-node

I'm getting the following SyntaxError when following the README for TS:

> ts-node ./node_modules/.bin/figma-export use-config .figmaexportrc.ts

REDACTED/node_modules/.bin/figma-export:2
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
          ^^^^^^^

SyntaxError: missing ) after argument list
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at main (REDACTED/node_modules/.pnpm/[email protected]_06de4b00c69b73d094e2c5b522a6ad57/node_modules/ts-node/src/bin.ts:331:12)
    at Object.<anonymous> (REDACTED/node_modules/.pnpm/[email protected]_06de4b00c69b73d094e2c5b522a6ad57/node_modules/ts-node/src/bin.ts:482:3)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
 ELIFECYCLE  Command failed with exit code 1.

The versions I'm using are:

ts-node: v10.4.0
node: v16.13.2

ts-node node_modules/.bin/figma-export --version gives the same error.

I've tried to match this project's tsconfig.json it didn't work.
I'm having tsconfig.json with module: esnext and target: esnext now, but in vain.

Support for require in es6 modules

Hi @marcomontalbano,

Great work! Excited to try out the package. While using the .figmaexportrc.ts file in my "type": "module" project, i came across this error

const err = new Error(getErrRequireEsmMessage(filename, parentPath, packageJsonPath)) ^ Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/Tacos/ui/.figmaexportrc.ts require() of ES modules is not supported. require() of /Users/Tacos/ui/.figmaexportrc.ts from /Users/Tacos/ui/node_modules/@figma-export/cli/dist/commands/use-config.js is an ES module file as it is a .ts file whose nearest parent package.json contains "type": "module" which defines all .ts files in that package scope as ES modules. Instead change the requiring code to use import(), or remove "type": "module" from /Users/Tacos/ui/package.json.

Curious if you know a way around using both require and import inside a es6 project? Perhaps this could work.

Return categorized components

Discussed in #142

Originally posted by riboher April 3, 2023
Hi there!

First of all thanks for this great library. I've been using it extensively for the last months and it has eased the process of exporting tokens of our Figma files.

One thing that I would like to do in the future is exporting each of my tokens categorized by their parent token name to avoid possible collisions in naming. That doesn't necessarily mean that the components should be returned grouped by this property during the getComponents function, but maybe have an extra property with that name so we can group them later.

I'm guessing this operations should be done when iterating through each of the children of the page. The type of the component could be checked so if it's FRAME, that said property could be added so we know at all times that reference in its children components. Does that make sense to you?

children.forEach((component) => {
        if (component.type === 'COMPONENT' && filter(component)) {
            components.push({
                ...component,
                svg: '',
                figmaExport: {
                    id: component.id,
                    dirname: dirname(component.name),
                    basename: basename(component.name),
                },
            });
            return;
        }

        if ('children' in component) {
            components = [
                ...components,
                ...getComponents((component.children), filter),
            ];
        }
    });

Sorry in advanced if I'm not explaining myself in great detail, I'd be glad to provide more insights to this if you find this feedback useful and are open to implement it (I'm glad to provide the changes myself in a PR if that suits you).

Thank you!

Noob question :-(

Hi there,

Sorry if I'm asking a totally obvious question but, how do you use this? It looks really cool.

I made a personal access token, like the readme says. After that though, I'm kinda lost.

I get the feeling this is for people who know how to code. Right?

sanitize variable names for target output

I am trying to output my tokens into css variables but the token names are not valid variable names

ex:

--Grey/900: rgba(26, 26, 26, 1);

I'd either want the ability to customize how the names are created or just have the tool output a usable name

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.