Skip to content

Commit 27cb44f

Browse files
Variables (#249)
* working on exporting variables * initial version of variables * fixing tests * fixing tests * add references * fixes & beta label * rm log
1 parent fc7fcad commit 27cb44f

25 files changed

+322
-7290
lines changed

dist/plugin.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ui.html

Lines changed: 9 additions & 9 deletions
Large diffs are not rendered by default.

dist/ui.js

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 5 additions & 7171 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"devDependencies": {
2727
"@ctrl/tinycolor": "^3.4.0",
2828
"@emotion/css": "^11.1.3",
29-
"@figma/plugin-typings": "^1.47.0",
29+
"@figma/plugin-typings": "^1.70.0",
3030
"@types/jest": "^28.1.1",
3131
"@types/react": "^18.0.13",
3232
"@types/react-dom": "^18.0.5",

src/config/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export default {
2020
settings: 'settings',
2121
extensionPluginData: 'org.lukasoppermann.figmaDesignTokens',
2222
extensionFigmaStyleId: 'styleId',
23+
extensionVariableStyleId: 'variableId',
2324
extensionAlias: 'alias',
2425
authType: {
2526
token: 'token',

src/config/defaultSettings.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const defaultSettings: Settings = {
1616
authType: 'token',
1717
reference: 'main',
1818
exclusionPrefix: '',
19+
excludeExtensionProp: false,
1920
alias: 'alias, ref, reference',
2021
keyInName: false,
2122
prefixInName: true,
@@ -47,6 +48,7 @@ export const defaultSettings: Settings = {
4748
size: true,
4849
spacing: true,
4950
motion: true,
50-
opacity: true
51+
opacity: true,
52+
variables: true
5153
}
5254
}

src/config/tokenTypes.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
/* istanbul ignore file */
2-
export const tokenTypes = {
2+
export const tokenTypes: Record<string, {
3+
label: string;
4+
key: string;
5+
exclude?: string[];
6+
}> = {
37
color: {
48
label: 'Colors',
59
key: 'color'
@@ -52,5 +56,10 @@ export const tokenTypes = {
5256
opacity: {
5357
label: 'Opacity',
5458
key: 'opacity'
59+
},
60+
variables: {
61+
label: 'Figma Variables (BETA)',
62+
key: 'variables',
63+
exclude: ['original']
5564
}
5665
}

src/transformer/originalFormatTransformer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ const valueTransformer: {} | undefined = {
169169
opacity: opacityValueTransformer
170170
}
171171

172-
const transformer = (token: internalTokenInterface): OriginalFormatTokenInterface => {
172+
const transformer = (token: internalTokenInterface, _settings): OriginalFormatTokenInterface => {
173173
return {
174174
name: token.name,
175175
category: token.category,

src/transformer/standardTransformer.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,25 @@ const valueTransformer = {
256256
opacity: opacityValueTransformer
257257
}
258258

259+
const transformVariable = ({ values, category }): StandardTokenDataInterface => {
260+
if (category === 'color') {
261+
return {
262+
type: 'color' as StandardTokenTypes,
263+
value: rgbaObjectToHex8(values.fill.value),
264+
blendMode: values.fill.blendMode?.toLowerCase() || 'normal'
265+
}
266+
}
267+
if (['size', 'boolean', 'string', 'alias'].includes(category)) {
268+
return {
269+
type: category as StandardTokenTypes,
270+
value: values
271+
}
272+
}
273+
}
274+
259275
const transformTokens = (token: internalTokenInterface): StandardTokenDataInterface | StandardTokenGroup => valueTransformer[token.category](token)
260276

261-
const transformer = (token: internalTokenInterface): StandardTokenInterface | StandardTokenGroup => {
277+
const transformer = (token: internalTokenInterface, settings): StandardTokenInterface | StandardTokenGroup => {
262278
if (token.category === 'typography') {
263279
// @ts-ignore
264280
return {
@@ -267,12 +283,21 @@ const transformer = (token: internalTokenInterface): StandardTokenInterface | St
267283
...typographyValueTransformer(token)
268284
}
269285
}
286+
// variable
287+
if (token.extensions[config.key.extensionPluginData].exportKey === 'variables') {
288+
return {
289+
name: token.name,
290+
description: token.description,
291+
...transformVariable(token),
292+
...tokenExtensions(token, settings)
293+
}
294+
}
270295
// @ts-ignore
271296
return {
272297
name: token.name,
273298
description: token.description,
274299
...transformTokens(token),
275-
...tokenExtensions(token)
300+
...tokenExtensions(token, settings)
276301
}
277302
}
278303

src/transformer/tokenExtensions.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { internalTokenInterface } from '@typings/propertyObject'
22
import { StandardTokenExtensionsInterface } from '@typings/standardToken'
33

4-
export const tokenExtensions = (token: internalTokenInterface): { extensions: StandardTokenExtensionsInterface; } => {
5-
return {
6-
extensions: {
7-
...token.extensions
4+
export const tokenExtensions = (token: internalTokenInterface, { excludeExtensionProp }): { extensions: StandardTokenExtensionsInterface; } => {
5+
if (excludeExtensionProp !== true) {
6+
return {
7+
extensions: {
8+
...token.extensions
9+
}
810
}
911
}
1012
}

src/ui/components/FileExportSettings.tsx

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -39,61 +39,114 @@ export const FileExportSettings = () => {
3939
event.preventDefault() // Prevent form submit triggering navigation
4040
const exportSettingsForm = event.target
4141
if (exportSettingsForm.checkValidity() === true) {
42-
const { accessToken, ...pluginSettings } = settings
42+
const { accessToken, ...pluginSettings } = settings;
4343
// save settings to local storage
44-
figmaUIApi.postMessage({
45-
pluginMessage: {
46-
command: commands.saveSettings,
47-
payload: {
48-
settings: pluginSettings,
49-
accessToken: accessToken
50-
}
51-
}
52-
// @ts-ignore
53-
}, '*')
44+
figmaUIApi.postMessage(
45+
{
46+
pluginMessage: {
47+
command: commands.saveSettings,
48+
payload: {
49+
settings: pluginSettings,
50+
accessToken: accessToken,
51+
},
52+
},
53+
// @ts-ignore
54+
},
55+
"*"
56+
);
5457
// prepare token json
55-
const tokensToExport = prepareExport(tokens, pluginSettings)
56-
setTokens(tokensToExport)
58+
59+
const tokensToExport = prepareExport(tokens, pluginSettings);
60+
61+
setTokens(tokensToExport);
5762
// download tokes
58-
downloadJson(parent, downloadLinkRef.current, stringifyJson(tokensToExport, pluginSettings.compression))
63+
downloadJson(
64+
parent,
65+
downloadLinkRef.current,
66+
stringifyJson(tokensToExport, pluginSettings.compression)
67+
);
5968
}
6069
}
6170

6271
return (
6372
<form onSubmit={handleFormSubmit} className={style}>
64-
<Title size='xlarge' weight='bold'>File Export settings</Title>
73+
<Title size="xlarge" weight="bold">
74+
File Export settings
75+
</Title>
6576
<Row>
6677
<Checkbox
67-
label='Compress JSON output file'
68-
type='switch'
78+
label="Compress JSON output file"
79+
type="switch"
6980
checked={settings.compression}
70-
onChange={(value) => updateSettings(draft => { draft.compression = value })}
81+
onChange={(value) =>
82+
updateSettings((draft) => {
83+
draft.compression = value;
84+
})
85+
}
86+
/>
87+
<Info
88+
width={240}
89+
label="Compression removes line breaks and whitespace from the json string"
7190
/>
72-
<Info width={240} label='Compression removes line breaks and whitespace from the json string' />
91+
{settings.tokenFormat === "standard" && (
92+
<>
93+
<Checkbox
94+
label="Exclude extension property"
95+
type="switch"
96+
checked={settings.excludeExtensionProp}
97+
onChange={(value) =>
98+
updateSettings((draft) => {
99+
draft.excludeExtensionProp = value;
100+
})
101+
}
102+
/>
103+
<Info
104+
width={240}
105+
label="The extension property holds additional information about the token"
106+
/>
107+
</>
108+
)}
73109
</Row>
74-
<Title size='large' weight='bold'>Include types in export</Title>
75-
<div className='grid-3-col'>
110+
<Title size="large" weight="bold">
111+
Include types in export
112+
</Title>
113+
<div className="grid-3-col">
76114
{Object.entries(tokenTypes)
77115
// @ts-ignore
78-
.map(([, { key, label, exclude = undefined }]) =>
79-
(exclude === undefined || !exclude.includes(settings.tokenFormat)) &&
80-
<Checkbox
81-
key={key}
82-
label={label}
83-
checked={settings.exports[key]}
84-
onChange={value => updateSettings((draft: Settings) => { draft.exports[key] = value })}
85-
/>)}
116+
.map(
117+
([, { key, label, exclude = undefined }]) =>
118+
(exclude === undefined ||
119+
!exclude.includes(settings.tokenFormat)) && (
120+
<Checkbox
121+
key={key}
122+
label={label}
123+
checked={settings.exports[key]}
124+
onChange={(value) =>
125+
updateSettings((draft: Settings) => {
126+
draft.exports[key] = value;
127+
})
128+
}
129+
/>
130+
)
131+
)}
86132
</div>
87133
<Footer>
88-
<WebLink align='start' href='https://github.com/lukasoppermann/design-tokens#design-tokens'>Documentation</WebLink>
134+
<WebLink
135+
align="start"
136+
href="https://github.com/lukasoppermann/design-tokens#design-tokens"
137+
>
138+
Documentation
139+
</WebLink>
89140
<CancelButton />
90-
<Button type='submit' autofocus>Save & Export</Button>
141+
<Button type="submit" autofocus>
142+
Save & Export
143+
</Button>
91144
</Footer>
92145
<a
93146
ref={downloadLinkRef}
94147
download={`${settings.filename}${settings.extension}`}
95148
title={`${settings.filename}${settings.extension}`}
96149
/>
97150
</form>
98-
)
151+
);
99152
}

src/ui/modules/downloadJson.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export const downloadJson = (parent, link: HTMLLinkElement, json: string) => {
66
if (json === '[]') {
77
parent.postMessage({
88
pluginMessage: {
9-
command: commands.closePlugin,
9+
// command: commands.closePlugin,
1010
payload: {
1111
notification: '⛔️ No design token detected!'
1212
}
@@ -33,7 +33,7 @@ export const downloadJson = (parent, link: HTMLLinkElement, json: string) => {
3333
// send success message
3434
parent.postMessage({
3535
pluginMessage: {
36-
command: commands.closePlugin,
36+
// command: commands.closePlugin,
3737
payload: {
3838
notification: '⛔️ Design token failed!'
3939
}

src/utilities/extractTokenNodeValues.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const extractTokenNodeValues = (node: ComponentNode | RectangleNode | FrameNode)
2626
cornerRadius: node.cornerRadius || undefined,
2727
cornerSmoothing: node.cornerSmoothing,
2828
strokes: getSolidStrokes(node.strokes),
29-
strokeWeight: node.strokeWeight,
29+
strokeWeight: node.strokeWeight as number,
3030
strokeStyleId: node.strokeStyleId,
3131
strokeMiterLimit: node.strokeMiterLimit,
3232
strokeJoin: node.strokeJoin,

src/utilities/getTokenJson.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import extractOpacities from '../extractor/extractOpacities'
1212
import { figmaDataType } from '@typings/figmaDataType'
1313
import buildFigmaData from './buildFigmaData'
1414
import { Settings } from '@typings/settings'
15+
import { getVariables } from './getVariables'
1516

1617
const getPrefixArray = (prefixString: string = '') => prefixString.split(',').map(item => item.replace(/\s+/g, ''))
1718

@@ -29,6 +30,7 @@ export const exportRawTokenArray = (figma: PluginAPI, settings: Settings) => {
2930
...extractColors(figmaData.paintStyles, { color: getPrefixArray(settings.prefix.color), gradient: getPrefixArray(settings.prefix.gradient), alias: getPrefixArray(settings.alias) }),
3031
...extractGrids(figmaData.gridStyles, getPrefixArray(settings.prefix.grid)),
3132
...extractFonts(figmaData.textStyles, getPrefixArray(settings.prefix.font)),
32-
...extractEffects(figmaData.effectStyles, getPrefixArray(settings.prefix.effect))
33+
...extractEffects(figmaData.effectStyles, getPrefixArray(settings.prefix.effect)),
34+
...getVariables(figma)
3335
]
3436
}

0 commit comments

Comments
 (0)