19 个稳定版本
3.2.2 | 2023年10月31日 |
---|---|
3.1.8 | 2023年9月13日 |
3.1.7 | 2023年8月28日 |
3.1.5 | 2023年7月10日 |
1.9.0 | 2023年6月27日 |
#41 在 配置
62 每月下载量
135KB
1.5K SLoC
令牌解析器
概述
令牌解析器是一个通用的工具,可以将您的 Figma 令牌转换为任何语言的可运行代码。它是用 Rust 编写的,因此您可以在任何您希望使用的地方使用它,而无需安装除了系统上的可执行文件之外的任何其他东西。完整的配置是通过一个 配置 yaml 文件完成的,您可以从一个地方自定义以构建您想要的任何语言。
测试与
只要它们具有正确的 json 结构,您就可以使用来自多个来源的令牌!
设置
您可以从整个项目中获取整个项目并自行构建,或者如果您没有 Rust 或者不想自己处理构建,请转到“发布”部分并从中获取可执行文件。
- 设置
assts/design_tokens_config.yaml
文件 - 运行:对于 Windows (
WIN_design_token_parser.exe
) 对于 MAC (MAC_design_token_parser
) 您可以在“发布”部分找到它们
.\WIN_design_token_parser.exe --generate --config "path/design_tokens_config.yaml"
这就完成了,您的文件将生成并准备好使用
生成可用令牌的过程分为两个。
-
将 Figma 令牌转换为可用的 json 文件(类似于 style-dictionary)
-
从先前生成的 json 文件生成针对特定语言的最终文件
如果您已经生成了可用的 json 文件,只需运行最终代码生成即可。
WIN_design_token_parser.exe --config "path/design_tokens_config.yaml"
Homebrew
- brew tap vrrashkov/tokenparser
- brew install tokenparser
- 配置 yaml 配置文件
design_token_parser--generate--config"design_tokens_config.yaml"
配置
输入/输出路径,用于加载和生成
global:
# Figma source paths
# These are the pure files from Figma, they can contain aliases
# For example if we have aliases we will need the actual value and not the alias
# Separating different files is necessary in case there are duplicate trees but different values/aliases
# So if we have button-md and button-big with the same trees but different values with aliases that need to be accesed from core.json
# this should be the setup
# Look at the figma/variables and figma/generated_styles for better understanding how it works
figma_source_paths:
- combine:
file_name: "button-lg"
files:
- "assets/figma/variables/button-lg.json"
- "assets/figma/variables/core-.json"
- combine:
file_name: "button-md"
files:
- "assets/figma/variables/button-md.json"
- "assets/figma/variables/core-.json"
- combine:
file_name: "button-sm"
files:
- "assets/figma/variables/button-sm.json"
- "assets/figma/variables/core-.json"
- combine:
file_name: "color-light"
files:
- "assets/figma/variables/color-accent-primary.json"
- "assets/figma/variables/color-accent-secondary.json"
- "assets/figma/variables/color-status-success.json"
- "assets/figma/variables/color-status-danger.json"
- "assets/figma/variables/color-light.json"
- "assets/figma/variables/palette-.json"
- combine:
file_name: "color-dark"
files:
- "assets/figma/variables/color-accent-primary.json"
- "assets/figma/variables/color-accent-secondary.json"
- "assets/figma/variables/color-status-success.json"
- "assets/figma/variables/color-status-danger.json"
- "assets/figma/variables/color-dark.json"
- "assets/figma/variables/palette-.json"
# file_name: If set this will be the name of the merged file
# if not, than the first file name will be used
figma_output_paths:
- combine:
file_name: "button-lg"
merge: ["button-lg"]
files:
- path: "assets/figma/variables/button-lg.json"
- combine:
file_name: "button-md"
merge: ["button-md"]
files:
- path: "assets/figma/variables/button-md.json"
- combine:
file_name: "button-sm"
merge: ["button-sm"]
files:
- path: "assets/figma/variables/button-sm.json"
- combine:
file_name: "color-light"
merge: ["color-light"]
files:
- path: "assets/figma/variables/color-accent-primary.json"
# if mode is set this will wrap the whole json object with a parent of the mode's value
# this helps if you have similar trees in multiple files
mode: "primary"
- path: "assets/figma/variables/color-accent-secondary.json"
mode: "secondary"
- path: "assets/figma/variables/color-status-success.json"
mode: "success"
- path: "assets/figma/variables/color-status-danger.json"
mode: "danger"
- path: "assets/figma/variables/color-light.json"
- combine:
file_name: "color-dark"
merge: ["color-dark"]
files:
- path: "assets/figma/variables/color-accent-primary.json"
mode: "primary"
- path: "assets/figma/variables/color-accent-secondary.json"
mode: "secondary"
- path: "assets/figma/variables/color-status-success.json"
mode: "success"
- path: "assets/figma/variables/color-status-danger.json"
mode: "danger"
- path: "assets/figma/variables/color-dark.json"
#Output path
style_output_path: "assets/generated_styles/"
模板配置
templates:
- settings_general:
generate_file_path: "generated_templates"
file_name:
format: "DS{{style}}"
extension: "swift"
#case: "kebab"
settings_custom:
# For header and footer {{style}} is a secial variable that can be used
header:
- "import SwiftUI"
- "public class DSCore{{style}} {"
footer:
- "}"
template_type:
# For themes
- type: color
value: "public static let {{variable_name | camel}} = {{value | color: 'Color(red: rgb_r_v1, green: rgb_g_v1, blue: rgb_b_v1, opacity: rgb_a_v1)'}} {{description | optional: '// desc = %value'}}"
# For Core
- type: string
value: "public static let {{variable_name | camel}} = {{value}} {{description | optional: '// desc = %value'}}"
- type: float
value: "public static let {{variable_name | camel}} = CGFloat({{value | as_text_or_number}}) {{description | optional: '// desc = %value'}}"
- type: boolean
value: "public static let {{variable_name | camel}} = {{value}} {{description | optional: '// des c = %value'}}"
- 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}}"
您可以使用每种类型多次以创建更清晰的方式创建您的值。有许多 过滤器 可以帮助您创建所需的模板(请查看以下内容)。此外,因为这个工具使用 Liquid,您可以在模板中使用每个过滤器/标签/块。如上所示,代码中有 if 语句检查变量是否存在,如果存在,则显示某些内容。
可以使用“可选”过滤器添加可选值。有时,使用“可选”过滤器而不是if语句更容易,只显示存在的值。
有效的JSON
两种类型的json都有效,因为存在正斜杠,所以可以有无限嵌套或根本不嵌套。
{
"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": ""
}
}
}
JSON值格式
您可以根据需要无限地嵌套树形结构,只要最终节点包含
value
和type
(description
是可选的)
有效示例及其使用JSON -> 模板
"XL": {
"type": "float",
"value": "56",
"description": ""
}
- type: float
value: "public static let {{variable_name | camel}} = CGFloat({{value | as_text_or_number}}) {{description | optional: '// desc = %value'}}"
public static let xl = CGFloat(56)
"bold": {
"type": "typography",
"value": {
"fontFamily": "Noir Pro",
"fontSize": "16",
"fontWeight": "Bold",
"letterSpacing": "-0.41",
"lineHeight": "23"
}
}
- type: typography
value: 'public static let {{variable_name | camel}} = TextStyle(name: "{{fontFamily}}", size: {{fontSize}}, weight: TextStyle.Weight({{fontWeight | as_text_or_number}}), lineHeight: {{lineHeight}})'
public static let bold = TextStyle(name: "Noir Pro", size: 16, weight: TextStyle.Weight("Bold"), lineHeight: 23)
"tabBar": {
"type": "boxShadow",
"value": [
{
"blur": "20",
"color": "rgba(0,0,0,0.1)",
"spread": "0",
"type": "dropShadow",
"x": "0",
"y": "0"
},
{
"blur": "8",
"color": "rgba(0,0,0,0.1)",
"spread": "0",
"type": "dropShadow",
"x": "0",
"y": "4"
}
]
}
- type: boxShadow
value:
- 'public static let {{variable_name | camel}} = Shadow(x: CGFloat({{x-0}}), y: CGFloat({{y-0}}), color: Color(hex: "{{color-0 | color: ''hex''}}"), radius: CGFloat({{blur-0}}))'
- 'public static let {{variable_name | camel}} = [Shadow(x: CGFloat({{x-0}}), y: CGFloat({{y-0}}), color: Color(hex: "{{color-0 | color: ''hex''}}"), radius: CGFloat({{blur-0}})), Shadow(x: CGFloat({{x-1}}), y: CGFloat({{y-1}}), color: Color(hex: "{{color-1 | color: ''hex''}}"), radius: CGFloat({{blur-1}}))]'
public static let shadowTabBar = [Shadow(x: CGFloat(0), y: CGFloat(0), color: Color(hex: "#00000019"), radius: CGFloat(20)), Shadow(x: CGFloat(0), y: CGFloat(4), color: Color(hex: "#00000019"), radius: CGFloat(8))]
"dissolve": {
"description": null,
"type": "custom-transition",
"value": {
"duration": 0.45,
"easingFunction": {
"x1": 0.6968395709991455,
"x2": 0.06683959811925888,
"y1": 0.05232666060328483,
"y2": 0.9323266744613647
},
"transitionType": "dissolve"
}
}
# Object
# {{easingFunction | empty}} use empty filter to initialize variable if you need it in the scope of the template without printing it
- type: "custom-transition"
value: "public static let {{variable_name | camel}} = CustomTransition(duration: {{duration}},
{{easingFunction | empty}}
x1: CGFloat({{easingFunction.x1}}),
x2: CGFloat({{easingFunction.x2}}),
y1: CGFloat({{easingFunction.y1}}),
y2: CGFloat({{easingFunction.y2}}))
"
public static let dissolve = CustomTransition(duration: 0.45, x1: CGFloat(0.6968395709991455), x2: CGFloat(0.06683959811925888), y1: CGFloat(0.05232666060328483), y2: CGFloat(0.9323266744613647))
"gradient": {
"single with multiple color stops": {
"description": "Four color stops from yellow to red",
"type": "custom-gradient",
"value": {
"gradientType": "radial",
"rotation": 180,
"stops": [
{
"color": "#ffb800ff",
"position": 0
},
{
"color": "#ff8a00ff",
"position": 0.34
},
{
"color": "#ff2e00ff",
"position": 0.65
},
{
"color": "#ff0000ff",
"position": 1
}
]
}
}
}
# Array
# {{stops | empty}} use empty filter to initialize variable if you need it in the scope of the template without printing it
- type: "custom-gradient"
value: "public static let {{variable_name | camel}} = CustomGradient(gradientType: {{gradientType}}, rotation: {{rotation}},
{{stops | empty}}
color1: Style1(
{% for stop in stops %}
{{stop.color | color: 'Color(red: rgb_r_v1, green: rgb_g_v1, blue: rgb_b_v1, opacity: rgb_a_v1)'}}
{% if forloop.last == false -%}, {% endif %}
{% endfor -%}
),
color2: Style2(
{% assign colors = stops | map: 'color' %}
{% for item in colors %}
{{item | color: 'Color(red: rgb_r_v2, green: rgb_g_v2, blue: rgb_b_v2, opacity: rgb_a_v2)'}}
{% if forloop.last == false -%}, {% endif %}
{% endfor %}
)
"
public static let defaultGradientSingleWithMultipleColorStops = CustomGradient(gradientType: radial, rotation: 180,
color1: Style1(
Color(red: 1.000, green: 0.722, blue: 0.000, opacity: 1.000) ,
Color(red: 1.000, green: 0.541, blue: 0.000, opacity: 1.000) ,
Color(red: 1.000, green: 0.180, blue: 0.000, opacity: 1.000) ,
Color(red: 1.000, green: 0.000, blue: 0.000, opacity: 1.000) ),
color2: Style2(
Color(red: 255, green: 184, blue: 0, opacity: 184) ,
Color(red: 255, green: 138, blue: 0, opacity: 138) ,
Color(red: 255, green: 46, blue: 0, opacity: 46) ,
Color(red: 255, green: 0, blue: 0, opacity: 0) )
}
使用
{{easingFunction | empty}}
空过滤器来初始化变量而不显示它。这个过滤器是这个库独有的,对于很多由液体模板提供的块是必要的。
关键词
您可以使用以下方式使用关键词: {{variable_name | kebab }}
关键词的名称,旁边您可以添加一个过滤器,或多个过滤器,用|
分隔,如下所示 {{variable_name | kebab | no_space }}
。
特殊过滤器
名称 | 额外选项/信息 |
---|---|
空 |
初始化变量而不显示其值 |
无空格 |
如果值包含空格,则将其删除。例如,“Test No Space ”将变为“TestNoSpace ” |
as_text_or_number |
如果值是文本,则将其添加双引号。 |
pascal , kebab , camel |
不同的案例过滤器 |
颜色 |
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 - 从0到255的值 v2 - 从0到1的值 |
您可以从资源文件夹中获取完整的配置示例
数组在模板化时有不同的处理方式。例如,文件中的boxShadow
类型是这样工作的。因为我们可以预期有未知长度的数组值,所以可以这样处理。
# 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}}"
Liquid过滤器
请从这里检查液体模板的可用过滤器/块等。
更多
对于任何想法或问题,请随时提问/报告。
依赖关系
~13MB
~233K SLoC