Token Parser is a tool for generating runnable code for any language from your Figma Variables or Figma Studio Tokens (you can even use both at the same time). It is written in Rust so you have the freedom to use it anywhere you would like without having node.js or anything else installed other than the executable on your system. The full configuration is happening through a configuration yaml file from which you can customize to build for as many different languages as you want from a single place.
You can get the whole project and build it yourself or if you don't have Rust or just don't want to deal with the builds yourself, go in the Release section and get the executables from there.
- Setup the assts/design_tokens_config.yaml file
- Run with: for windows (WIN_design_token_parser.exe) for MAC (MAC_design_token_parser) you can find them in Release section
.\WIN_design_token_parser.exe --generate --config "path/design_tokens_config.yaml"
That's all, your files will be generated and ready to use
The process for generating the usable tokens is split into two.
-
Converting the Figma tokens to usable json files (similar to style-dictionary)
-
Generating the end files for the langages from the previously generated json files
If you have already generated the usable json files you can just run the end code generation by running.
WIN_design_token_parser.exe --config "path/design_tokens_config.yaml"
- brew tap vrrashkov/tokenparser
- brew install tokenparser
- Configure the yaml config file
- design_token_parser --generate --config "design_tokens_config.yaml"
global:
# Figma variables source paths
figma_variables_source_paths:
- "assets/figma/variables/light_variables.json"
# Figma studio source paths
figma_studio_source_paths:
- "assets/figma/studio/core.json"
- "assets/figma/studio/typography.json"
- "assets/figma/studio/global.json"
- "assets/figma/studio/mobile.json"
- "assets/figma/studio/dark.json"
- "assets/figma/studio/light.json"
# Figma output calculated files,
# This will output the files
# dark.json
# light.json
# core.json - (merged with typography, global)
# mobile.json
figma_output_paths:
- combine:
- "assets/figma/variables/light_variables.json"
- combine:
- "assets/figma/studio/dark.json"
- combine:
- "assets/figma/studio/light.json"
- combine:
- "assets/figma/studio/core.json"
- "assets/figma/studio/typography.json"
- "assets/figma/studio/global.json"
- combine:
- "assets/figma/studio/mobile.json"
# Different themes path
# The available paths are the ones created from figma_output_paths
# In this case we can only access dark.json, light.json, core.json, mobile.json, light-variables.json
output_paths:
- "dark.json"
- "light.json"
- "light-variables.json"
# Output path
style_output_path: "assets/generated_styles"
templates:
- settings_general:
# Path where the template should be created
generate_file_path: "generated_templates"
file_name:
# Special keyword {style}
# it will be replaced with the specific style
# In this case dark/light
format: "cds-{style}"
extension: "css"
case: "kebab"
settings_custom:
header: ":root {"
#sub_header: "test sub header"
#sub_footer: "test sub footer"
footer: "}"
# Only if class is set, class_name will be displayed
#class: "public class"
#class_name: "SomeNameCore{style}"
template_type:
- type: color
value: "{{variable_name | kebab}} {{color | color: 'rgb_r_v1, rgb_g_v2'}}"
- type: composition
value: "{% if verticalPadding != '' %} test1: {{verticalPadding | optional: 'vertical-padding-test-first: %value'}} {% endif %}"
- type: composition
value: "{% if verticalPadding != '' %} test2: {{verticalPadding | optional: 'vartical-padding-test-second: %value'}} {% endif %}"
- type: boxShadow
value:
- "{{variable_name}} {{color-0 | color: 'hex'}} blur: {{blur-0}} x: {{x-0}}"
- "{{variable_name}} {{color-0 | color: 'hex'}} {{color-1 | color: 'hex'}} blur: {{blur-0}} x: {{x-0}} blur: {{blur-1}} x: {{x-1}}"
In the above scenario 3 files are going to be generated cds-dark, cds-light and cds-light-variables they will be containing tokens which we set through template_type in this case composition, boxShadow and color, in this case we are using 2 different methods together, just for the example tokens from Figma Variables and from Figma Studio. Every different type contains specific keys you can use to create the template that you want. See below the list of special keywords you can use.
You can use every type multiple times for more clean way of creating your values. There are many filters that can help you create the template you want (check them bellow). Also because this tool is using Liquid you can expect every filter/tags/blocks to be usable in your templates. As you can see from the above code there are if statements that check if a variable is present and if it is display something.
Optional values can be added with the optional filter. Instead of using if statements sometimes it's easier to just use the optional filter and display the value only if it exists.
Both type of jsons are valid, you can have infinite amount of nesting or no nesting at all.
{
"size/XL": {
"type": "float",
"value": "56",
"description": ""
},
"text/fr": {
"type": "string",
"value": "Some Text",
"description": ""
},
"color/bg": {
"type": "color",
"value": "#000000",
"description": ""
}
}
{
"size": {
"XL": {
"type": "float",
"value": "56",
"description": ""
}
},
"text": {
"fr": {
"type": "string",
"value": "Some Text",
"description": ""
}
},
"color": {
"bg": {
"type": "color",
"value": "#000000",
"description": ""
}
}
}
type | value |
---|---|
GLOBAL VALUES | variable_name description |
color | color |
float | float |
string | string |
boolean | boolean |
typography | fontFamily fontSize fontWeight spacing lineHeight paragraphSpacing paragraphIndent textCase textDecoration |
paragraphSpacing | paragraphSpacing |
paragraphIndent | paragraphIndent |
textCase | textCase |
textDecoration | textDecoration |
spacing | spacing |
borderWidth | borderWidth |
borderRadius | borderRadius |
letterSpacing | spacing |
lineHeights | lineHeight |
fontSizes | fontSize |
fontWeights | fontWeight |
fontFamilies | fontFamily |
boxShadow | color blur spread type x y |
composition | paddingBottom paddingTop paddingLeft paddingRight sizing height width borderRdius borderWidth borderRadiusBottomLeft border_radiusBottomRight borderRadiusTopLeft borderRadiusTopRight spacing verticalPadding horizontalPadding |
You can use the keywords in the following way: {{variable_name | kebab }} name of the keyword and next to it you can add a filter, or multiple filters by separating them with | lie this {{variable_name | kebab | no_space }}.
type | variant |
---|---|
added to GLOBAL | no_space, pascal, kebab, camel |
color | rgb_r_v1, rgb_g_v1, rgb_b_v1, rgb_a_v1 rgb_r_v2, rgb_g_v2, rgb_b_v2, rgb_a_v2 hex v1 - values from 0 to 255 v2 - values from 0 to 1 |
You can get example of full configuration from the assets folder
boxShadow has a bit different take on how you shuld template it. Because we can expect array values with uknown length here is how you can handle them.
# All the color related values from above
# For every new line of the boxShadow value, a new index can be used. For example:
# On line 1 you have only values with index 0
# On line 2 you have values with index 0 and 1
# On line 3 you have values with index 0, 1 and 2 and etc..
# All possible variants should be made with a template
# If there is a missing one you will be notified with an error to add it
- type: boxShadow
value:
- "{{variable_name}} {{color-0 | color: 'hex'}} blur: {{blur-0}} x: {{x-0}}"
- "{{variable_name}} {{color-0 | color: 'hex'}} {{color-1 | color: 'hex'}} blur: {{blur-0}} x: {{x-0}} blur: {{blur-1}} x: {{x-1}}"
For any ideas or issues please don't hasitate to ask/report.