JSON-формат токенов
Как писать валидный token JSON в SXL Studio: структура DTCG, основные поля, полный набор типов, алиасы, математика, модификаторы цвета и валидация — каждая секция начинается с таблицы.
Overview
Эта страница описывает JSON-формат token-файлов на вкладке Tokens. Он следует форме DTCG ($value, $type, $extensions, …). Для файлов компонентов ($type: "composition") см. Composition.
Любая нода — это либо токен, либо группа:
| Тип ноды | Правило | Что может содержать |
|---|---|---|
| Token node | Есть $value | $value, $type, $description, $extensions, $id |
| Group node | Нет $value (контейнер) | Дочерние ноды + наследуемые $type / $extensions |
Ключевая идея Любой ключ, начинающийся с $, — это метаполе DTCG. Любой другой ключ — это имя группы или токена. Группы передают $type и $extensions вниз своим детям.
Корень файла
Корень должен быть JSON-объектом (массивы, строки и числа отклоняются валидацией).
{
"colors": {
"brand": {
"primary": {
"$value": "#635BFF",
"$type": "color"
}
}
}
}
Основные поля
| Поле | Обязательно | Описание |
|---|---|---|
$value | Да (для token node) | Значение токена (формы ниже) |
$type | Нет | Тип токена — явный или унаследованный от родительской группы |
$description | Нет | Человекочитаемое описание |
$extensions | Нет | Метаданные Figma (figma.scopes, codeSyntax, hide, modify) |
$id | Нет | Стабильный ID для внешнего тулинга |
Формы $value
| Форма | Пример |
|---|---|
| Строка | "#635BFF", "16px", "Inter" |
| Число / Boolean | 8, true |
| Чистый алиас | "{colors.brand.primary}" |
| Математическое выражение | "{spacing.base} * 2" |
| Объект (композит) | typography, border, grid, … |
| Массив (композит) | effects, слои теней, слои заливок, … |
Строка:
{ "$value": "#635BFF", "$type": "color" }
{ "$value": "16px", "$type": "spacing" }
{ "$value": "Inter", "$type": "fontFamily" }
Число / Boolean:
{ "$value": 8, "$type": "number" }
{ "$value": true, "$type": "boolean" }
Чистый алиас — один dot-notation путь внутри {...}:
{ "$value": "{colors.brand.primary}", "$type": "color" }
Математическое выражение (алиас, встроенный в строку):
{ "$value": "{spacing.base} * 2", "$type": "spacing" }
{ "$value": "clamp(16px, {spacing.base} * 4, 64px)", "$type": "sizing" }
Объект / массив (композитные значения):
{
"$value": { "fontFamily": "Inter", "fontSize": "16px", "fontWeight": 500, "lineHeight": "24px" },
"$type": "typography"
}
{
"$value": [{ "type": "DROP_SHADOW", "x": 0, "y": 2, "blur": 8, "spread": 0, "color": "#00000033" }],
"$type": "shadow"
}
Типы токенов ($type)
SXL Studio поддерживает 38 канонических типов токенов. Понятнее всего группировать их по тому, во что превращается каждый тип при Export Variables & Styles.
Экспортируются как переменные Figma (17) — скалярные токены, которые становятся переменными в коллекции.
| Вид переменной Figma | Типы |
|---|---|
COLOR | color |
FLOAT (число) | opacity, dimension, number, spacing, sizing, borderWidth, borderRadius, fontSize, lineHeight, letterSpacing, paragraphIndent, paragraphSpacing |
STRING | fontFamily, fontWeight, text |
BOOLEAN | boolean |
Экспортируются как стили Figma (10) — композитные токены, которые становятся локальными стилями.
| Вид стиля | Типы |
|---|---|
| Paint | gradient, img, fill |
| Effect | shadow, backdrop-blur, blur, glass, effects |
| Text | typography |
| Grid | grid |
Только внутренние / редактируемые (11) — полностью редактируются в SXL Studio и используются логикой плагина или рендером, но напрямую не экспортируются как переменная или стиль: border, strokeStyle, fontStyle, textCase, textDecoration, transition, duration, cubicBezier, template, composition, custom.
Полное поведение по типам: Token types.
Примечание custom (или чистый проектный $type, например "baseUnit") остаётся редактируемым в SXL Studio. При экспорте SXL выводит безопасную цель из формы $value (#112233 → color, числа → number, булевы → boolean, CSS-градиенты → paint). Значения, которые нельзя вывести безопасно, остаются opaque/внутренними.
Нормализация $type
Легаси- и множественные значения $type автоматически нормализуются к каноническому ключу.
| Ввод | Канонический |
|---|---|
string | text |
size | sizing |
space | spacing |
fontFamilies | fontFamily |
fontWeights | fontWeight |
fontStyles | fontStyle |
fontSizes | fontSize |
lineHeights | lineHeight |
letterSpacings | letterSpacing |
paragraphSpacings | paragraphSpacing |
paragraphIndents | paragraphIndent |
borderRadii | borderRadius |
textCases | textCase |
textDecorations | textDecoration |
backdropBlur / backgroundBlur / background-blur | backdrop-blur |
layerBlur | blur |
boxShadow | shadow |
Экспорты Tokens Studio (легаси value / type / extensions) можно сконвертировать через Migrate from Tokens Studio.
Резолв типа и inference
$type резолвится в таком порядке:
| Приоритет | Источник |
|---|---|
| 1 | $type на уровне токена |
| 2 | $type ближайшей родительской группы |
| 3 | $type на уровне корня |
| 4 | Auto-inference из $value (fallback) |
Если ничего не резолвится, валидация выдаёт ошибку. Когда $type не задан и не унаследован, парсер выводит его из формы $value:
Форма $value | Выведенный тип |
|---|---|
true / false или "on", "off", "yes", "no", "1", "0" | boolean |
Числовой литерал (12, 0.5) | number |
Числовая строка с единицей (16px, 1.5rem, 50%, 200ms) | number |
Строка-цвет (#…, rgb(…), hsl(…), color(…)) | color |
CSS-градиент (linear-gradient(…), radial-…, conic-…) | gradient |
Строковый массив из 4 чисел ("[0.4, 0, 0.2, 1]") | cubicBezier |
Объект с r / g / b | color |
Объект с полями типографики (fontFamily, fontSize, …) | typography |
Объект/массив с полями тени (offsetX/Y, blur+color) | shadow |
Объект/массив с полями сетки (pattern, sectionSize, …) | grid |
| Объект/массив с полями заливки/paint | fill |
Объект только с blur | blur |
Чистый алиас ("{a.b}") | резолвится из цели алиаса |
Рекомендация Inference — это удобный fallback. Для надёжного экспорта задавайте $type явно (на уровне токена, группы или корня).
$extensions
| Ключ | Что делает |
|---|---|
figma.scopes | Подсказки scope для экспорта переменных Figma |
figma.codeSyntax | Сниппеты кода для Dev Mode (Web, Android, iOS) |
figma.hide | Скрыть переменную из публикации |
figma.modify | Модификаторы цвета (lighten, darken, alpha, mix) |
figma.scopes — подсказки scope для экспорта:
{ "$extensions": { "figma.scopes": ["ALL_FILLS", "STROKE_COLOR"] } }
Полный список scope и дефолты по типам — на странице Scopes & Code Syntax.
figma.codeSyntax — сниппеты для Dev Mode. Используйте ключи ровно как показано: Web, Android, iOS.
{
"$extensions": {
"figma.codeSyntax": {
"Web": "var(--color-brand-primary)",
"Android": "@color/brand_primary",
"iOS": "Color.brandPrimary"
}
}
}
figma.hide — скрыть переменную из публикации:
{ "$extensions": { "figma.hide": true } }
figma.modify — модификаторы цвета:
| Поле | Значения |
|---|---|
type | lighten, darken, alpha, mix |
value | Величина (0–1) |
space | srgb, hsl, lch, oklch, p3 (по умолчанию oklch) |
color | Целевой цвет — обязателен для mix |
{ "$extensions": { "figma.modify": { "type": "lighten", "value": 0.2, "space": "oklch" } } }
figma.modify может быть одним объектом или цепочкой-массивом, применяемой по порядку:
{
"$extensions": {
"figma.modify": [
{ "type": "lighten", "value": 0.12, "space": "oklch" },
{ "type": "alpha", "value": 0.6 }
]
}
}
Если space опущен, SXL Studio использует oklch. space также принимает алиас $space.
Наследование. $extensions группы наследуются детьми и мержатся поверхностно — ключ ребёнка перекрывает такой же ключ родителя, а непересекающиеся ключи комбинируются.
{
"brand": {
"$type": "color",
"$extensions": { "figma.scopes": ["ALL_FILLS"] },
"primary": { "$value": "#635BFF" },
"primary-soft": {
"$value": "{brand.primary}",
"$extensions": { "figma.modify": { "type": "alpha", "value": 0.7 } }
}
}
}
Алиасы
| Форма | Синтаксис | Применение |
|---|---|---|
| Чистый | "{colors.brand.primary}" | Всё значение — один референс на токен |
| Встроенный | "{spacing.base} * 3" | Референс внутри math / композитной строки |
Правила: один путь в фигурных скобках, dot-notation для сегментов, без циклических ссылок. Чистый алиас ("{a.b}") трактуется как алиас — не как математика — и его тип резолвится из целевого токена.
Математические выражения
Строка $value, содержащая оператор или функцию, вычисляется после резолва алиасов.
Математика применяется только к числовым типам токенов: dimension, number, spacing, sizing, borderWidth, borderRadius, opacity, fontSize, lineHeight, letterSpacing, paragraphSpacing, paragraphIndent, duration, blur, backdrop-blur — и к числовым полям внутри композитов (offsets/blur/spread у теней, размеры в typography, тайминги transition). Строковые значения никогда не вычисляются: text-токен "37-37" остаётся литералом "37-37", а не 0.
| Категория | Поддерживается |
|---|---|
| Операторы | +, -, *, /, %, скобки |
| Константы | pi, e |
| Округление | round, floor, ceil, trunc |
| Клампинг | min, max, clamp |
| Арифметика | abs, sign, mod, pow, sqrt, hypot |
| Exp / log | exp, log, log2, log10 |
| Тригонометрия | sin, cos, tan, asin, acos, atan, atan2 |
{ "$value": "{spacing.base} * 4", "$type": "spacing" }
{ "$value": "round({spacing.base} * 1.5, 2)", "$type": "spacing" }
Примечания: round(x, n) округляет до n знаков; rem / em и секунды нормализуются при вычислении; нерезолвнутый алиас или неизвестная функция инвалидируют выражение.
Валидация
JSON-редактор проверяет:
- синтаксис JSON;
- ошибки парсинга DTCG (нерезолвимый
$type; неизвестные значения$typeсохраняются как редактируемые opaque-токены custom); - некорректные фигурные скобки алиасов;
- неизвестные ссылки на токены.
Для файлов composition / template строковые ссылки также проверяются по путям токенов воркспейса, включая локальные встроенные namespace'ы composition-токенов.
Полный пример
{
"color": {
"$type": "color",
"brand": {
"primary": {
"$value": "#635BFF",
"$description": "Primary brand color",
"$extensions": {
"figma.codeSyntax": {
"Web": "var(--color-brand-primary)",
"Android": "@color/brand_primary",
"iOS": "Color.brandPrimary"
}
}
},
"primary-soft": {
"$value": "{color.brand.primary}",
"$extensions": {
"figma.modify": [
{ "type": "lighten", "value": 0.1, "space": "oklch" },
{ "type": "alpha", "value": 0.65 }
]
}
}
}
},
"spacing": {
"$type": "spacing",
"base": { "$value": "4px" },
"md": { "$value": "{spacing.base} * 4" }
}
}