├── .prettierignore ├── .gitignore ├── jest.config.js ├── .prettierrc ├── manifest.json ├── .vscode └── tasks.json ├── src ├── index.ts ├── fallbackFonts.ts ├── figmaState.ts ├── genDefaults.ts ├── updateImageHashes.test.ts ├── updateImageHashes.ts ├── applyOverridesToChildren.ts ├── readBlacklist.test.ts ├── components.test.ts ├── readBlacklist.ts ├── fonts.test.ts ├── read.ts ├── styles.test.ts ├── figma-default-layers.ts ├── write.ts └── figma-json.ts ├── .github └── workflows │ └── tests.yaml ├── tsconfig.json ├── scripts └── build.js ├── plugin ├── toolbar.tsx ├── pluginMessage.ts ├── plugin.ts └── ui.tsx ├── examples ├── basic.figma.json └── dump-1.json └── package.json /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | examples 3 | .vscode 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | plugin/**/*.js 2 | node_modules 3 | dist 4 | 5 | yarn-error.log 6 | 7 | .DS_Store -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transform: { 3 | "^.+\\.tsx?$": "esbuild-jest", 4 | }, 5 | roots: ["./src"], 6 | }; 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false, 4 | "semi": true, 5 | "trailingComma": "all", 6 | "singleQuote": false, 7 | "printWidth": 80 8 | } 9 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JSON Plugin", 3 | "id": "763482362622863901", 4 | "api": "1.0.0", 5 | "main": "dist/plugin.js", 6 | "editorType": ["figma"], 7 | "ui": "dist/ui.js" 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "dev", 9 | "problemMatcher": ["$tsc-watch"] 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Andrew Pouliot 2 | export { 3 | type DumpOptions as Options, 4 | type DumpOptions, 5 | dump, 6 | isVisible, 7 | } from "./read"; 8 | export { insert, fontsToLoad } from "./write"; 9 | 10 | // Expose types for our consumers to interact with 11 | export * from "./figma-json"; 12 | 13 | export { default as defaultLayers } from "./figma-default-layers"; 14 | -------------------------------------------------------------------------------- /.github/workflows/tests.yaml: -------------------------------------------------------------------------------- 1 | name: Jest Tests 2 | 3 | # Run on every push to the repository on any branch 4 | on: 5 | push: 6 | branches: 7 | - "**" 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v2 16 | 17 | - name: Install dependencies 18 | run: yarn install 19 | 20 | - name: Run Jest tests 21 | run: yarn test 22 | -------------------------------------------------------------------------------- /src/fallbackFonts.ts: -------------------------------------------------------------------------------- 1 | import * as F from "./figma-json"; 2 | 3 | export const fallbackFonts: F.FontName[] = [ 4 | { family: "Inter", style: "Regular" }, 5 | { family: "Inter", style: "Thin" }, 6 | { family: "Inter", style: "Extra Light" }, 7 | { family: "Inter", style: "Light" }, 8 | { family: "Inter", style: "Medium" }, 9 | { family: "Inter", style: "Semi Bold" }, 10 | { family: "Inter", style: "Bold" }, 11 | { family: "Inter", style: "Extra Bold" }, 12 | { family: "Inter", style: "Black" }, 13 | ]; 14 | -------------------------------------------------------------------------------- /src/figmaState.ts: -------------------------------------------------------------------------------- 1 | let skipState: boolean | undefined; 2 | 3 | export function saveFigmaState(skipInvisibleInstanceChildren: boolean) { 4 | if ("figma" in globalThis) { 5 | // Capture original value in case we change it. 6 | skipState = figma.skipInvisibleInstanceChildren; 7 | figma.skipInvisibleInstanceChildren = skipInvisibleInstanceChildren; 8 | } 9 | } 10 | export function restoreFigmaState() { 11 | if ("figma" in globalThis && skipState !== undefined) { 12 | figma.skipInvisibleInstanceChildren = skipState; 13 | skipState = undefined; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | "declarationDir": "dist", 5 | "target": "ES6", 6 | "lib": ["ES2022", "dom"], 7 | "jsx": "react", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "declaration": true, 11 | "emitDeclarationOnly": true, 12 | "isolatedModules": true, 13 | "experimentalDecorators": true, 14 | "typeRoots": ["node_modules/@types"], 15 | "module": "commonjs", 16 | "moduleResolution": "node", 17 | "skipLibCheck": true, 18 | "resolveJsonModule": true 19 | }, 20 | "include": ["src/**/*"], 21 | "exclude": ["dist", "node_modules"] 22 | } 23 | -------------------------------------------------------------------------------- /scripts/build.js: -------------------------------------------------------------------------------- 1 | const { build } = require("esbuild"); 2 | const { dependencies, devDependencies } = require("../package.json"); 3 | 4 | const entryPoints = ["src/index.ts"]; 5 | const settings = { 6 | entryPoints, 7 | platform: "node", 8 | bundle: true, 9 | external: [...Object.keys(dependencies), ...Object.keys(devDependencies)], 10 | }; 11 | 12 | const buildESM = () => 13 | build({ 14 | ...settings, 15 | format: "esm", 16 | outfile: "dist/index.mjs", 17 | }); 18 | 19 | const buildCJS = () => 20 | build({ 21 | ...settings, 22 | format: "cjs", 23 | outfile: "dist/index.js", 24 | }); 25 | 26 | const buildAll = () => Promise.all([buildESM(), buildCJS()]); 27 | buildAll(); 28 | -------------------------------------------------------------------------------- /plugin/toolbar.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | const doNothing = (e: React.MouseEvent) => { 4 | console.log("No event hooked up!"); 5 | }; 6 | 7 | export const InsertButton = ({ 8 | onInsert, 9 | }: { 10 | onInsert: (e: React.MouseEvent) => void; 11 | }) => ( 12 | 24 | ); 25 | 26 | const Toolbar: React.FunctionComponent = ({ children }) => ( 27 |
Inserting...
; 144 | } else if (showInsert) { 145 | return ( 146 |Waiting for data...
; 153 | } else { 154 | return ( 155 |
176 | {JSON.stringify(
177 | dump,
178 | (key: string, value: any) =>
179 | value instanceof Uint8Array ? `<${value.length} bytes>` : value,
180 | 2,
181 | )}
182 |
183 | {/*