-
-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #40 from marcomontalbano/i34-svgr
Add new component outputter 'output-components-as-svgr'
- Loading branch information
Showing
11 changed files
with
761 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,7 +69,7 @@ | |
"node": ">= 8.3 <= 13.x" | ||
}, | ||
"lint-staged": { | ||
"*.{js,ts}": [ | ||
"!(*.d).{js,ts}": [ | ||
"npm test" | ||
] | ||
}, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
src | ||
tsconfig.json | ||
tsconfig.tsbuildinfo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# @figma-export/output-components-as-svgr | ||
|
||
> Outputter for [@figma-export](https://github.com/marcomontalbano/figma-export) that exports components as React components. | ||
With this outputter you can export all Figma components as React components into the specified output folder. | ||
|
||
This is a sample of the output from this [Figma file](https://www.figma.com/file/RSzpKJcnb6uBRQ3rOfLIyUs5): | ||
|
||
```sh | ||
$ tree output/ | ||
|
||
# output | ||
# ├── icons | ||
# │ ├── FigmaArrow.jsx | ||
# │ ├── FigmaExport.jsx | ||
# │ ├── FigmaLogo.jsx | ||
# │ └── index.js | ||
# ├── monochrome | ||
# │ ├── FigmaBlue.jsx | ||
# │ ├── FigmaGreen.jsx | ||
# │ ├── FigmaPurple.jsx | ||
# │ ├── FigmaRed.jsx | ||
# │ └── index.js | ||
# └── unit-test | ||
# ├── figma | ||
# │ ├── logo | ||
# │ │ ├── Main.jsx | ||
# │ │ ├── MainBright.jsx | ||
# │ │ └── index.js | ||
# │ ├── Logo.jsx | ||
# │ └── index.js | ||
# ├── FigmaDefaultLogo.jsx | ||
# └── index.js | ||
``` | ||
|
||
> **Tip**: A figma component named `icon/eye` will be exported as `Eye.jsx` inside the `icon` folder. Another `index.js` file will be created inside the `icon` folder and this will export directly the `Eye` component. | ||
## Install | ||
|
||
Using npm: | ||
|
||
```sh | ||
npm install --save-dev @figma-export/output-components-as-svgr | ||
``` | ||
|
||
or using yarn: | ||
|
||
```sh | ||
yarn add @figma-export/output-components-as-svgr --dev | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
declare module '@svgr/core' { | ||
type config = {}; | ||
type state = {}; | ||
function sync(svg: string, config: config, state: state): string; | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"name": "@figma-export/output-components-as-svgr", | ||
"version": "2.0.0-alpha.1", | ||
"description": "Outputter for @figma-export that exports components as React components using svgr", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/marcomontalbano/figma-exporter.git", | ||
"directory": "packages/output-components-as-svgr" | ||
}, | ||
"author": "Marco Montalbano <me@marcomontalbano.com>", | ||
"license": "MIT", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"dependencies": { | ||
"@figma-export/output-components-utils": "^2.0.0-alpha.1", | ||
"@figma-export/types": "^2.0.0-alpha.1", | ||
"@svgr/core": "~5.2.0", | ||
"make-dir": "~3.0.0" | ||
}, | ||
"engines": { | ||
"node": ">= 8.3 <= 13.x" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import sinon from 'sinon'; | ||
import { expect } from 'chai'; | ||
|
||
import * as figmaDocument from '../../core/src/lib/_config.test'; | ||
import * as figma from '../../core/src/lib/figma'; | ||
|
||
import fs = require('fs'); | ||
import outputter = require('./index'); | ||
|
||
describe('outputter as svgr', () => { | ||
afterEach(() => { | ||
sinon.restore(); | ||
}); | ||
|
||
it('should export all components into jsx files plus one index.js for each folder', async () => { | ||
const writeFileSync = sinon.stub(fs, 'writeFileSync'); | ||
const fakePage = figmaDocument.createPage([figmaDocument.component1, figmaDocument.component2]); | ||
const pages = figma.getPages(fakePage); | ||
|
||
await outputter({ | ||
output: 'output', | ||
})(pages); | ||
|
||
expect(writeFileSync).to.be.calledThrice; | ||
expect(writeFileSync.firstCall).to.be.calledWithMatch('output/fakePage/FigmaLogo.jsx', 'function FigmaLogo(props) {'); | ||
expect(writeFileSync.secondCall).to.be.calledWithMatch('output/fakePage/Search.jsx', 'function Search(props) {'); | ||
expect(writeFileSync.thirdCall).to.be.calledWithMatch('output/fakePage/index.js', "export { default as FigmaLogo } from './FigmaLogo.jsx';"); | ||
}); | ||
|
||
it('should create folder if component names contain slashes', async () => { | ||
const writeFileSync = sinon.stub(fs, 'writeFileSync'); | ||
const fakePage = figmaDocument.createPage([figmaDocument.componentWithSlashedName]); | ||
const pages = figma.getPages(fakePage); | ||
|
||
await outputter({ | ||
output: 'output', | ||
})(pages); | ||
|
||
expect(writeFileSync).to.be.calledTwice; | ||
expect(writeFileSync.firstCall).to.be.calledWithMatch('output/fakePage/icon/Eye.jsx'); | ||
expect(writeFileSync.secondCall).to.be.calledWithMatch('output/fakePage/icon/index.js'); | ||
}); | ||
|
||
describe('options', () => { | ||
const fakePage = figmaDocument.createPage([figmaDocument.componentWithSlashedName]); | ||
const pages = figma.getPages(fakePage); | ||
|
||
it('should be able to customize "dirname"', async () => { | ||
const writeFileSync = sinon.stub(fs, 'writeFileSync'); | ||
|
||
await outputter({ | ||
output: 'output', | ||
getDirname: (options) => `${options.dirname}`, | ||
})(pages); | ||
|
||
expect(writeFileSync.firstCall).to.be.calledWithMatch('output/icon/Eye.jsx', 'function Eye(props) {'); | ||
expect(writeFileSync.secondCall).to.be.calledWithMatch('output/icon/index.js', "from './Eye.jsx';"); | ||
}); | ||
|
||
it('should be able to customize "componentName"', async () => { | ||
const writeFileSync = sinon.stub(fs, 'writeFileSync'); | ||
|
||
await outputter({ | ||
output: 'output', | ||
getComponentName: (options) => `${options.basename}`, | ||
})(pages); | ||
|
||
expect(writeFileSync.firstCall).to.be.calledWithMatch('output/fakePage/icon/eye.jsx', 'function eye(props) {'); | ||
expect(writeFileSync.secondCall).to.be.calledWithMatch('output/fakePage/icon/index.js', "from './eye.jsx';"); | ||
}); | ||
|
||
it('should be able to customize "fileExtension"', async () => { | ||
const writeFileSync = sinon.stub(fs, 'writeFileSync'); | ||
|
||
await outputter({ | ||
output: 'output', | ||
getFileExtension: () => '.js', | ||
})(pages); | ||
|
||
expect(writeFileSync.firstCall).to.be.calledWithMatch('output/fakePage/icon/Eye.js', 'function Eye(props) {'); | ||
expect(writeFileSync.secondCall).to.be.calledWithMatch('output/fakePage/icon/index.js', "from './Eye.js';"); | ||
}); | ||
|
||
it('should be able to customize "svgrConfig"', async () => { | ||
const writeFileSync = sinon.stub(fs, 'writeFileSync'); | ||
|
||
await outputter({ | ||
output: 'output', | ||
getSvgrConfig: () => ({ native: true }), | ||
})(pages); | ||
|
||
expect(writeFileSync.firstCall).to.be.calledWithMatch('output/fakePage/icon/Eye.jsx', 'from "react-native-svg"'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
|
||
import { FigmaExport } from '@figma-export/types'; | ||
import { pascalCase } from '@figma-export/output-components-utils'; | ||
import svgr from '@svgr/core'; | ||
|
||
import fs = require('fs'); | ||
import path = require('path'); | ||
import makeDir = require('make-dir'); | ||
|
||
type Options = { | ||
output: string; | ||
getDirname?: (options: FigmaExport.OutputterParamOption) => string; | ||
getComponentName?: (options: FigmaExport.OutputterParamOption) => string; | ||
getFileExtension?: (options: FigmaExport.OutputterParamOption) => string; | ||
getSvgrConfig?: (options: FigmaExport.OutputterParamOption) => svgr.config; | ||
} | ||
|
||
type IndexJs = { | ||
[key: string]: string[]; | ||
}; | ||
|
||
export = ({ | ||
output, | ||
getDirname = (options): string => `${options.pageName}${path.sep}${options.dirname}`, | ||
getComponentName = (options): string => `${pascalCase(options.basename)}`, | ||
getFileExtension = (): string => '.jsx', | ||
getSvgrConfig = (): svgr.config => ({}), | ||
}: Options): FigmaExport.Outputter => { | ||
makeDir.sync(output); | ||
const indexJs: IndexJs = {}; | ||
return async (pages): Promise<void> => { | ||
pages.forEach(({ name: pageName, components }) => { | ||
components.forEach(({ name: componentName, svg, figmaExport }) => { | ||
const options = { | ||
pageName, | ||
componentName, | ||
...figmaExport, | ||
}; | ||
|
||
const reactComponentName = getComponentName(options); | ||
const basename = `${reactComponentName}${getFileExtension(options)}`; | ||
const filePath = makeDir.sync(path.resolve(output, getDirname(options))); | ||
|
||
indexJs[filePath] = indexJs[filePath] || []; | ||
indexJs[filePath].push(`export { default as ${reactComponentName} } from './${basename}';`); | ||
|
||
const svgrConfig = getSvgrConfig(options); | ||
const svgrState = { componentName: reactComponentName }; | ||
|
||
const jsCode = svgr.sync(svg, svgrConfig, svgrState); | ||
|
||
fs.writeFileSync(path.resolve(filePath, basename), jsCode); | ||
}); | ||
|
||
Object.entries(indexJs).forEach(([filePath, exports]) => { | ||
fs.writeFileSync(path.resolve(filePath, 'index.js'), exports.join('\n')); | ||
}); | ||
}); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"rootDir": "src", | ||
"outDir": "dist" | ||
}, | ||
"references": [ | ||
{"path": "../types"}, | ||
{"path": "../output-components-utils"}, | ||
] | ||
} |