{"id":13727110,"url":"https://github.com/figma-tools/figma-transformer","last_synced_at":"2025-03-21T18:33:11.320Z","repository":{"id":42982862,"uuid":"215745298","full_name":"figma-tools/figma-transformer","owner":"figma-tools","description":"A tiny utility library that makes the Figma API more human friendly.","archived":false,"fork":false,"pushed_at":"2023-01-07T10:47:05.000Z","size":944,"stargazers_count":56,"open_issues_count":18,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-18T03:51:28.902Z","etag":null,"topics":["api","figma","figma-api","transformer"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/figma-tools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-17T08:46:47.000Z","updated_at":"2025-02-28T17:03:17.000Z","dependencies_parsed_at":"2023-02-06T23:01:01.534Z","dependency_job_id":null,"html_url":"https://github.com/figma-tools/figma-transformer","commit_stats":null,"previous_names":["braposo/figma-transformer"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figma-tools%2Ffigma-transformer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figma-tools%2Ffigma-transformer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figma-tools%2Ffigma-transformer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figma-tools%2Ffigma-transformer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/figma-tools","download_url":"https://codeload.github.com/figma-tools/figma-transformer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244849345,"owners_count":20520694,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","figma","figma-api","transformer"],"created_at":"2024-08-03T01:03:39.767Z","updated_at":"2025-03-21T18:33:10.716Z","avatar_url":"https://github.com/figma-tools.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cbr/\u003e\n    \u003cimg width=\"100\" src=\"./figma-transformer.svg\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003e\nfigma-transformer\n\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n\nA tiny utility library that makes the Figma API more human friendly. \n\n[![npm version][version-badge]][npm]\n[![npm downloads][downloads-badge]][npm]\n[![gzip size][size-badge]][size]\n![modules][modules-badge]\n[![MIT License][license-badge]][license]\n[![PRs Welcome][prs-badge]][prs]\n\n\u003c/div\u003e\n\n## How to use `figma-transformer`?\n\n```js\nimport { processFile } from \"figma-transformer\";\n\n// Fetch the file you want using your favourite method\nconst originalFile = fetchFigmaFile();\n\nconst file = processFile(originalFile);\n\n// ✨ You can now use `file` for whatever you need! ✨\n\n// Let's get the styles for a component named \"Test\"\nconst testStyles = file.shortcuts.components.find(\n    component =\u003e component.name === \"Test\"\n).shortcuts.styles;\n```\n\n## Why use `figma-transformer`?\n\nThe Figma API is great but sometimes it feels like it's built for machines, not humans. The more you use it, the more you'll end up wasting a lot of time to get to the information that you want.\n\nThese are the most common problems:\n\n-   Code needs to change if file structure changes\n-   Incomplete information about styles and components\n-   No type safety\n\nWith `figma-transformer` you get the file structure that you wished the Figma API had.\n\n## How does `figma-transformer` solve these problems?\n\n### Break free from the file structure\n\nThe Figma API response is very strict in terms of the file structure. To get to a specific node you have to navigate through the entire tree of nodes and it's really easy for your code to break if there's a change in the design file that changes the initial hierarchy.\n\nWe break from that rigid structure by creating shortcuts that are grouped by node type, making it a lot easier to access the nodes that we want irrespective of their placement in the file.\n\n```js\n{\n    \"children\": [{...}, {...}],\n    \"shortcuts\": {\n        \"CANVAS\": [...],\n        \"INSTANCE\": [...],\n        \"RECTANGLE\": [...],\n        \"STYLE\": [...],\n        \"TEXT\": [...],\n        \"FRAME\": [...],\n        \"COMPONENT\": [...],\n        \"GROUP\": [...]\n    }\n}\n```\n\nWe can see that even though this node just has two direct children, it actually contains a lot more elements down the tree, which are surfaced in the shortcuts.\n\nEach node of the document tree contains the shortcuts to all their respective child nodes, which reduces the amount of work needed to get to the information we need.\n\n### Missing information from nodes\n\nFrom the API we can get the information about the styles and components that are present in the file, which is great, but it doesn't contain all the information so we need to parse the entire file to get the additional information that we usuallly need.\n\nLet's look at how the Figma API describes the styles in a document:\n\n```js\nstyles: {\n    \"1:12\": {\n        key: \"ea017aed6616af00f3c4d59e3d945c8c3e47adca\",\n        name: \"Green\",\n        styleType: \"FILL\",\n        description: \"\",\n    },\n    \"1:11\": {\n        key: \"e234400b962ffafce654af9b3220ce88857523ec\",\n        name: \"Red\",\n        styleType: \"FILL\",\n        description: \"\",\n    },\n    \"97:6\": {\n        key: \"cc806814e1b9b7d20ce0b6bed8adf52099899c01\",\n        name: \"Body\",\n        styleType: \"TEXT\",\n        description: \"\",\n    },\n},\n```\n\nand this is how it's represented after being processed (note the populated styles from the associated nodes)\n\n```js\n[\n    {\n        id: \"1:12\",\n        key: \"ea017aed6616af00f3c4d59e3d945c8c3e47adca\",\n        name: \"Green\",\n        styleType: \"FILL\",\n        description: \"\",\n        styles: [\n            {\n                blendMode: \"NORMAL\",\n                type: \"SOLID\",\n                color: {\n                    r: 0.047774821519851685,\n                    g: 0.9563318490982056,\n                    b: 0.02923285961151123,\n                    a: 1,\n                },\n            },\n        ],\n        type: \"STYLE\",\n    },\n    {\n        id: \"1:11\",\n        key: \"e234400b962ffafce654af9b3220ce88857523ec\",\n        name: \"Red\",\n        styleType: \"FILL\",\n        description: \"\",\n        styles: [\n            {\n                blendMode: \"NORMAL\",\n                type: \"SOLID\",\n                color: {\n                    r: 0.8515284061431885,\n                    g: 0.11155396699905396,\n                    b: 0.11155396699905396,\n                    a: 1,\n                },\n            },\n        ],\n        textStyles: {\n            fontFamily: \"Roboto\",\n            fontPostScriptName: null,\n            fontWeight: 400,\n            fontSize: 12,\n            textAlignHorizontal: \"LEFT\",\n            textAlignVertical: \"TOP\",\n            letterSpacing: 0,\n            lineHeightPx: 14.0625,\n            lineHeightPercent: 100,\n            lineHeightUnit: \"INTRINSIC_%\",\n        },\n        type: \"STYLE\",\n    },\n    {\n        id: \"97:6\",\n        key: \"cc806814e1b9b7d20ce0b6bed8adf52099899c01\",\n        name: \"Body\",\n        styleType: \"TEXT\",\n        description: \"\",\n        textStyles: {\n            fontFamily: \"Roboto\",\n            fontPostScriptName: null,\n            fontWeight: 400,\n            fontSize: 12,\n            textAlignHorizontal: \"LEFT\",\n            textAlignVertical: \"TOP\",\n            letterSpacing: 0,\n            lineHeightPx: 14.0625,\n            lineHeightPercent: 100,\n            lineHeightUnit: \"INTRINSIC_%\",\n        },\n        type: \"STYLE\",\n    },\n];\n```\n\nThe same happens with the components, this is what we get from the API:\n\n```js\ncomponents: {\n    \"1:5\": { key: \"\", name: \"Rectangle\", description: \"\" },\n},\n```\n\nand this is the processed data:\n\n```js\n{\n    \"id\": \"1:5\",\n    \"parentId\": \"7:0\",\n    \"fileId\": \"cLp23bR627jcuNSoBGkhL04E\",\n    \"name\": \"Rectangle\",\n    \"type\": \"COMPONENT\",\n    \"blendMode\": \"PASS_THROUGH\",\n    \"absoluteBoundingBox\": {\n        \"x\": -232,\n        \"y\": -208,\n        \"width\": 201,\n        \"height\": 109\n    },\n    \"constraints\": {\n        \"vertical\": \"TOP\",\n        \"horizontal\": \"LEFT\"\n    },\n    \"clipsContent\": false,\n    \"background\": [\n        {\n            \"blendMode\": \"NORMAL\",\n            \"visible\": false,\n            \"type\": \"SOLID\",\n            \"color\": {\n                \"r\": 1,\n                \"g\": 1,\n                \"b\": 1,\n                \"a\": 1\n            }\n        }\n    ],\n    \"backgroundColor\": {\n        \"r\": 0,\n        \"g\": 0,\n        \"b\": 0,\n        \"a\": 0\n    },\n    \"effects\": [],\n    \"children\": [...],\n    \"shortcuts\": {...}\n}\n```\n\nNot only we have the complete node definition but we also have its child nodes and shortcuts so we can easily navigate through the component tree if needed.\n\n### Improved type safety\n\nThe Figma API doesn't have official type definitions, but fortunately we can provide a better developer experience by extending the TypeScript type definitions provided by the awesome [figma-js](https://github.com/jongold/figma-js) library.\n\nThis means that you can continue to use your preferred way of fetching the data from the Figma API and `figma-transformer` will provide the types for you.\n\n## Examples\n\nLet's see more specific examples where the benefits of the library really stand out.\n\n**Getting all text used in a document**\n\n```js\nconst text = file.shortcuts.texts.map(node =\u003e node.characters);\n```\n\n**Finding the styles applied to a specific component**\n\n```js\nconst styles = file.shortcuts.components\n    .filter(component =\u003e component.name === \"Test\")\n    .map(component =\u003e component.shortcuts.styles);\n```\n\n**Getting the fill colours for all the rectangles in the first page**\n\n```js\nconst fills = file.shortcuts.pages\n    .filter(page =\u003e page.name === \"Page 1\")\n    .map(page =\u003e page.shortcuts.rectangles.fills);\n```\n\n## Projects using `figma-transformer`\n\n-   [figma-graphql](https://github.com/braposo/figma-graphql)\n-   [theme.figma](https://github.com/ds-tools/theme.figma)\n\n---\n\n## Local Development\n\nBelow is a list of commands you will probably find useful.\n\n#### `npm start` or `yarn start`\n\nRuns the project in development/watch mode. Your project will be rebuilt upon changes. TSDX has a special logger for you convenience. Error messages are pretty printed and formatted for compatibility VS Code's Problems tab.\n\nYour library will be rebuilt if you make edits.\n\n#### `npm run build` or `yarn build`\n\nBundles the package to the `dist` folder.\nThe package is optimized and bundled with Rollup into multiple formats (CommonJS, UMD, and ES Module).\n\n#### `npm test` or `yarn test`\n\nRuns the test watcher (Jest) in an interactive mode.\nBy default, runs tests related to files changed since the last commit.\n\n_This project was bootstrapped with [TSDX](https://github.com/jaredpalmer/tsdx)._\n\n[npm]: https://www.npmjs.com/package/figma-transformer\n[license]: https://github.com/braposo/figma-transformer/blob/master/LICENSE\n[prs]: http://makeapullrequest.com\n[size]: https://unpkg.com/figma-transformer/dist/figma-transformer.cjs.production.min.js\n[version-badge]: https://img.shields.io/npm/v/figma-transformer.svg?style=flat-square\n[downloads-badge]: https://img.shields.io/npm/dm/figma-transformer.svg?style=flat-square\n[license-badge]: https://img.shields.io/npm/l/figma-transformer.svg?style=flat-square\n[size-badge]: http://img.badgesize.io/https://unpkg.com/figma-transformer/dist/figma-transformer.cjs.production.min.js?compression=gzip\u0026style=flat-square\n[modules-badge]: https://img.shields.io/badge/module%20formats-cjs%2C%20esm-green.svg?style=flat-square\n[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffigma-tools%2Ffigma-transformer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffigma-tools%2Ffigma-transformer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffigma-tools%2Ffigma-transformer/lists"}