-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(tokens): add Figma sync script (#1532)
* feat(tokens): add Figma sync script * feat: support modes * feat: use env var * fix: use built-in * fix: typecheck * fix: remove root to avoid redundancy
- Loading branch information
Showing
12 changed files
with
533 additions
and
78 deletions.
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
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,23 @@ | ||
import type { RGB, RGBA } from '@figma/rest-api-spec'; | ||
|
||
/** | ||
* Compares two colors for approximate equality since converting between Figma RGBA objects (from 0 -> 1) and | ||
* hex colors can result in slight differences. | ||
*/ | ||
const colorApproximatelyEqual = (colorA: RGB | RGBA, colorB: RGB | RGBA) => { | ||
return rgbToHex(colorA) === rgbToHex(colorB); | ||
}; | ||
|
||
const rgbToHex = ({ r, g, b, ...rest }: RGB | RGBA) => { | ||
const a = 'a' in rest ? rest.a : 1; | ||
|
||
const toHex = (value: number) => { | ||
const hex = Math.round(value * 255).toString(16); | ||
return hex.length === 1 ? `0${hex}` : hex; | ||
}; | ||
|
||
const hex = [toHex(r), toHex(g), toHex(b)].join(''); | ||
return `#${hex}${a !== 1 ? toHex(a) : ''}`; | ||
}; | ||
|
||
export { colorApproximatelyEqual, rgbToHex }; |
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,44 @@ | ||
import type { | ||
GetLocalVariablesResponse, | ||
PostVariablesRequestBody, | ||
PostVariablesResponse, | ||
} from '@figma/rest-api-spec'; | ||
|
||
import axios from 'axios'; | ||
|
||
class FigmaApi { | ||
private baseUrl = 'https://api.figma.com'; | ||
private token: string; | ||
|
||
constructor(token: string) { | ||
this.token = token; | ||
} | ||
|
||
async getLocalVariables(fileKey: string) { | ||
const resp = await axios.request<GetLocalVariablesResponse>({ | ||
url: `${this.baseUrl}/v1/files/${fileKey}/variables/local`, | ||
headers: { | ||
Accept: '*/*', | ||
'X-Figma-Token': this.token, | ||
}, | ||
}); | ||
|
||
return resp.data; | ||
} | ||
|
||
async postVariables(fileKey: string, payload: PostVariablesRequestBody) { | ||
const resp = await axios.request<PostVariablesResponse>({ | ||
url: `${this.baseUrl}/v1/files/${fileKey}/variables`, | ||
method: 'POST', | ||
headers: { | ||
Accept: '*/*', | ||
'X-Figma-Token': this.token, | ||
}, | ||
data: payload, | ||
}); | ||
|
||
return resp.data; | ||
} | ||
} | ||
|
||
export { FigmaApi }; |
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,52 @@ | ||
import type { Variable } from './types'; | ||
|
||
import darkTokens from '../dist/figma.dark.json'; | ||
import defaultTokens from '../dist/figma.default.json'; | ||
import { FigmaApi } from './figma'; | ||
import { generatePostVariablesPayload } from './variables'; | ||
|
||
// https://github.com/gerard-figma/figma-variables-to-styledictionary | ||
const main = async () => { | ||
const fileKey = process.env.FIGMA_FILE_KEY ?? ''; | ||
const api = new FigmaApi(process.env.FIGMA_TOKEN ?? ''); | ||
|
||
const localVariables = await api.getLocalVariables(fileKey); | ||
|
||
const tokens = { | ||
Default: Object.groupBy(defaultTokens, ({ collection }) => collection), | ||
Dark: Object.groupBy(darkTokens, ({ collection }) => collection), | ||
}; | ||
const postVariablesPayload = generatePostVariablesPayload( | ||
tokens as unknown as Record<string, Record<string, Variable[]>>, | ||
localVariables, | ||
); | ||
|
||
if (Object.values(postVariablesPayload).every((value) => value.length === 0)) { | ||
console.log('%c ✅ Tokens are already up to date with the Figma file', 'color:green;'); | ||
return; | ||
} | ||
|
||
const apiResp = await api.postVariables(fileKey, postVariablesPayload); | ||
|
||
console.log('POST variables API response:', apiResp); | ||
|
||
if (postVariablesPayload.variableCollections?.length) { | ||
console.log('Updated variable collections', postVariablesPayload.variableCollections); | ||
} | ||
|
||
if (postVariablesPayload.variableModes?.length) { | ||
console.log('Updated variable modes', postVariablesPayload.variableModes); | ||
} | ||
|
||
if (postVariablesPayload.variables?.length) { | ||
console.log('Updated variables', postVariablesPayload.variables); | ||
} | ||
|
||
if (postVariablesPayload.variableModeValues?.length) { | ||
console.log('Updated variable mode values', postVariablesPayload.variableModeValues); | ||
} | ||
|
||
console.log('%c ✅ Figma file has been updated with the new tokens', 'color:green;'); | ||
}; | ||
|
||
main(); |
Oops, something went wrong.