Skip to content

Commit 142fa42

Browse files
committed
move PR to other repo
0 parents  commit 142fa42

36 files changed

+11236
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

README.md

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Figma to Angular Converter
2+
3+
This demonstrates using the Figma REST API to convert a Figma document to Angular Components and Figma components module.
4+
Disclaimer: this code is likely incomplete, and may have bugs. It is not intended to be used
5+
in production. This is simply a proof of concept to show what possibilities exist.
6+
7+
## API Usage
8+
9+
We use 2 endpoints in this project:
10+
11+
- `GET /v1/files/:file_key` - Get the JSON tree from a file. This is the main workhorse of this project and lays the skeleton of the React Components.
12+
- `GET /v1/images/:file_key` - When we identify nodes that are vectors or other nodes that can't directly be represented by `div`s, we have to render them as svgs.
13+
14+
## Set up
15+
16+
1. Install [Node](https://nodejs.org/). You'll need a recent version that supports `async / await`
17+
2. In this directory, run `npm install`
18+
3. Run the converter per instructions below
19+
20+
## Usage
21+
22+
By default this project comes with a prerendered component in `src/figmaComponents`. You can see a page that uses this component if you
23+
run `npm start`. This will start a React server and a webpage will open to the root page. This webpage will automatically refresh as
24+
you make changes to the source documents. To follow along with the example component, the source Figma file is located [here](https://www.figma.com/file/VGULlnz44R0Ooe4FZKDxlhh4/Untitled).
25+
26+
When we run the converter, we will convert any *top level frames* in the document to Angular Components *as long as their name starts with `#`*.
27+
In the example document you can see that we have one top level frame named `#Clock`. The component resulting from this will be exported in
28+
`src/components/CFClock.component` as `CFClock`, a `dump component`.
29+
30+
In addition, *any* node with a name starting with a `#` will have a code stub generated for it in `src/components`. These code stubs can be
31+
modified to affect the rendering of those components as well as modifying variables within the component (see variables section below).
32+
33+
To run the converter on a file, you will need a personal access token from Figma. Refer to the [Figma API documentation](https://www.figma.com/developers/docs)
34+
for more information on how to obtain a token. The other piece of information you will need is the file key of the file you wish to convert,
35+
which is located in the file's URL (for example, this is `VGULlnz44R0Ooe4FZKDxlhh4` for the example file). So, an example conversion would look
36+
like:
37+
38+
```
39+
node main.js VGULlnz44R0Ooe4FZKDxlhh4 <API_TOKEN_HERE>
40+
```
41+
42+
where `<API_TOKEN_HERE>` would be repaced with your developer token.
43+
44+
You can also change the .env file and insert your token there
45+
46+
```
47+
//.env
48+
DEV_TOKEN=<YOUR_TOKEN>
49+
```
50+
then you only need to pass the project id
51+
```
52+
node main.js VGULlnz44R0Ooe4FZKDxlhh4
53+
```
54+
55+
56+
57+
*IMPORTANT*: The index.css file is required to be included for components to render completely.
58+
59+
## Variables
60+
61+
The real vision of this converter is to separate design concerns from coding concerns. Toward this end, we introduce the concept of
62+
`variables` in Figma. Variables in a Figma file are denoted by text nodes (this can be expanded in the future) with names starting with
63+
`$`. In the example document there are three variables: `$time`, `$seconds`, and `$ampm`. By setting state in the component stubs defined in
64+
`src/components`, we can *change the text of the variable nodes*. For an example, take a look at `src/app/app.component`. This
65+
allows us to change the design of a component without touching the code at all.
66+
67+
## Why Angular?
68+
69+
Because it's one of the best frameworks
70+
71+
## Examples
72+
73+
Here's an example of using Figma to React to update the style on a sortable list:
74+
75+
![duck-list](https://static.figma.com/uploads/9e647f547b9487af4d879627de3bae84591671c1)
76+
77+
78+
Here's an example of using Figma to React to attach code to a component dragged in from the Team Library:
79+
80+
![clock](https://static.figma.com/uploads/3e4a5e166e295433c29c0e3e78d3a436efc64353)
81+

angular.json

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
{
2+
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3+
"version": 1,
4+
"newProjectRoot": "projects",
5+
"projects": {
6+
"figma-to-angular": {
7+
"projectType": "application",
8+
"schematics": {
9+
"@schematics/angular:component": {
10+
"style": "scss"
11+
}
12+
},
13+
"root": "",
14+
"sourceRoot": "src",
15+
"prefix": "app",
16+
"architect": {
17+
"build": {
18+
"builder": "@angular-devkit/build-angular:browser",
19+
"options": {
20+
"outputPath": "dist/figma-to-angular",
21+
"index": "src/index.html",
22+
"main": "src/main.ts",
23+
"polyfills": "src/polyfills.ts",
24+
"tsConfig": "tsconfig.app.json",
25+
"aot": false,
26+
"assets": [
27+
"src/favicon.ico",
28+
"src/assets"
29+
],
30+
"styles": [
31+
"src/styles.scss"
32+
],
33+
"scripts": []
34+
},
35+
"configurations": {
36+
"production": {
37+
"fileReplacements": [
38+
{
39+
"replace": "src/environments/environment.ts",
40+
"with": "src/environments/environment.prod.ts"
41+
}
42+
],
43+
"optimization": true,
44+
"outputHashing": "all",
45+
"sourceMap": false,
46+
"extractCss": true,
47+
"namedChunks": false,
48+
"aot": true,
49+
"extractLicenses": true,
50+
"vendorChunk": false,
51+
"buildOptimizer": true,
52+
"budgets": [
53+
{
54+
"type": "initial",
55+
"maximumWarning": "2mb",
56+
"maximumError": "5mb"
57+
}
58+
]
59+
}
60+
}
61+
},
62+
"serve": {
63+
"builder": "@angular-devkit/build-angular:dev-server",
64+
"options": {
65+
"browserTarget": "figma-to-angular:build"
66+
},
67+
"configurations": {
68+
"production": {
69+
"browserTarget": "figma-to-angular:build:production"
70+
}
71+
}
72+
},
73+
"extract-i18n": {
74+
"builder": "@angular-devkit/build-angular:extract-i18n",
75+
"options": {
76+
"browserTarget": "figma-to-angular:build"
77+
}
78+
},
79+
"test": {
80+
"builder": "@angular-devkit/build-angular:karma",
81+
"options": {
82+
"main": "src/test.ts",
83+
"polyfills": "src/polyfills.ts",
84+
"tsConfig": "tsconfig.spec.json",
85+
"karmaConfig": "karma.conf.js",
86+
"assets": [
87+
"src/favicon.ico",
88+
"src/assets"
89+
],
90+
"styles": [
91+
"src/styles.scss"
92+
],
93+
"scripts": []
94+
}
95+
},
96+
"lint": {
97+
"builder": "@angular-devkit/build-angular:tslint",
98+
"options": {
99+
"tsConfig": [
100+
"tsconfig.app.json",
101+
"tsconfig.spec.json",
102+
"e2e/tsconfig.json"
103+
],
104+
"exclude": [
105+
"**/node_modules/**"
106+
]
107+
}
108+
},
109+
"e2e": {
110+
"builder": "@angular-devkit/build-angular:protractor",
111+
"options": {
112+
"protractorConfig": "e2e/protractor.conf.js",
113+
"devServerTarget": "figma-to-angular:serve"
114+
},
115+
"configurations": {
116+
"production": {
117+
"devServerTarget": "figma-to-angular:serve:production"
118+
}
119+
}
120+
}
121+
}
122+
}},
123+
"defaultProject": "figma-to-angular"
124+
}

browserslist

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2+
# For additional information regarding the format and rule options, please see:
3+
# https://github.com/browserslist/browserslist#queries
4+
5+
# You can see what browsers were selected by your queries by running:
6+
# npx browserslist
7+
8+
> 0.5%
9+
last 2 versions
10+
Firefox ESR
11+
not dead
12+
not IE 9-11 # For IE 9-11 support, remove 'not'.

e2e/protractor.conf.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// @ts-check
2+
// Protractor configuration file, see link for more information
3+
// https://github.com/angular/protractor/blob/master/lib/config.ts
4+
5+
const { SpecReporter } = require('jasmine-spec-reporter');
6+
7+
/**
8+
* @type { import("protractor").Config }
9+
*/
10+
exports.config = {
11+
allScriptsTimeout: 11000,
12+
specs: [
13+
'./src/**/*.e2e-spec.ts'
14+
],
15+
capabilities: {
16+
'browserName': 'chrome'
17+
},
18+
directConnect: true,
19+
baseUrl: 'http://localhost:4200/',
20+
framework: 'jasmine',
21+
jasmineNodeOpts: {
22+
showColors: true,
23+
defaultTimeoutInterval: 30000,
24+
print: function() {}
25+
},
26+
onPrepare() {
27+
require('ts-node').register({
28+
project: require('path').join(__dirname, './tsconfig.json')
29+
});
30+
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
31+
}
32+
};

e2e/src/app.e2e-spec.ts

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { AppPage } from './app.po';
2+
import { browser, logging } from 'protractor';
3+
4+
describe('workspace-project App', () => {
5+
let page: AppPage;
6+
7+
beforeEach(() => {
8+
page = new AppPage();
9+
});
10+
11+
it('should display welcome message', () => {
12+
page.navigateTo();
13+
expect(page.getTitleText()).toEqual('Welcome to figma-to-angular!');
14+
});
15+
16+
afterEach(async () => {
17+
// Assert that there are no errors emitted from the browser
18+
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
19+
expect(logs).not.toContain(jasmine.objectContaining({
20+
level: logging.Level.SEVERE,
21+
} as logging.Entry));
22+
});
23+
});

e2e/src/app.po.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { browser, by, element } from 'protractor';
2+
3+
export class AppPage {
4+
navigateTo() {
5+
return browser.get(browser.baseUrl) as Promise<any>;
6+
}
7+
8+
getTitleText() {
9+
return element(by.css('app-root h1')).getText() as Promise<string>;
10+
}
11+
}

e2e/tsconfig.json

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"extends": "../tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "../out-tsc/e2e",
5+
"module": "commonjs",
6+
"target": "es5",
7+
"types": [
8+
"jasmine",
9+
"jasminewd2",
10+
"node"
11+
]
12+
}
13+
}

karma.conf.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Karma configuration file, see link for more information
2+
// https://karma-runner.github.io/1.0/config/configuration-file.html
3+
4+
module.exports = function (config) {
5+
config.set({
6+
basePath: '',
7+
frameworks: ['jasmine', '@angular-devkit/build-angular'],
8+
plugins: [
9+
require('karma-jasmine'),
10+
require('karma-chrome-launcher'),
11+
require('karma-jasmine-html-reporter'),
12+
require('karma-coverage-istanbul-reporter'),
13+
require('@angular-devkit/build-angular/plugins/karma')
14+
],
15+
client: {
16+
clearContext: false // leave Jasmine Spec Runner output visible in browser
17+
},
18+
coverageIstanbulReporter: {
19+
dir: require('path').join(__dirname, './coverage/figma-to-angular'),
20+
reports: ['html', 'lcovonly', 'text-summary'],
21+
fixWebpackSourcePaths: true
22+
},
23+
reporters: ['progress', 'kjhtml'],
24+
port: 9876,
25+
colors: true,
26+
logLevel: config.LOG_INFO,
27+
autoWatch: true,
28+
browsers: ['Chrome'],
29+
singleRun: false,
30+
restartOnFileChange: true
31+
});
32+
};

0 commit comments

Comments
 (0)