Dev Mode

Генерация кода

Как работает генерация кода в Dev Mode SXL Studio: Vue 3, React, JSON (Design), SwiftUI, UIKit, Kotlin, DivKit, view modes, настройки, секции и отладка.

Архитектура codegen

В SXL Studio один core-пайплайн генерации кода используется в двух местах:

  • нативная панель Code в Figma (figma.codegen.on("generate"))
  • Plugin Dev Inspect → Code (запросы на main thread)

За счёт этого поведение генерации синхронизировано между обеими поверхностями.


Цели генерации и вывод

Поддерживаемые цели:

  • Vue 3
  • React
  • JSON (Design)
  • SwiftUI
  • UIKit
  • Kotlin
  • DivKit

Нативная панель Code в Figma: типовые вкладки

Vue 3

  • All — <ComponentName> (или All — <ComponentSetName> (<variants>))
  • Script Setup
  • Template
  • Styles
  • Variables
  • Reference components
  • Дополнительные вкладки Code Connect (Import & Usage, file tabs и т.д.)
  • Опционально Debug (если есть debug trace)

React

  • All — <ComponentName>.tsx
  • Template
  • Script
  • Styles
  • Variables
  • Reference components
  • дополнительные вкладки Code Connect
  • опционально Debug

JSON (Design)

  • JSON composition — <name>
  • Props
  • Component properties
  • Structure
  • Styles
  • Опционально Transitions
  • Опционально Theme binding
  • Variables
  • Reference components
  • Дополнительные вкладки Code Connect
  • Опционально Debug

SwiftUI / UIKit / Kotlin

  • основной сгенерированный файл (.swift / .kt)
  • Variables (Swift) или Variables (Kotlin)
  • Reference components
  • дополнительные вкладки Code Connect
  • опционально Debug

DivKit

  • All — <name>.divkit.json
  • Template
  • Styles
  • Variables
  • References
  • дополнительные вкладки Code Connect
  • опционально Debug

Секция Code в Plugin Dev Inspect

В Dev Inspect хаба вывод кода показывается в одном editor-блоке с селекторами:

  • Language: Vue 3 / React / SwiftUI / UIKit / Kotlin / DivKit / JSON
  • Section: All, Template, Script, Styles, Variables, References
  • View mode: Styled, Decomposed, Raw

Особенности маппинга секций:

  • Variables и References — кросс-платформенные диагностические секции.
  • Web-цели (Vue 3, React) имеют Script; native mobile и JSON-card цели (SwiftUI, UIKit, Kotlin, DivKit) пропускают script-only вывод и фокусируются на generated file, variables, styles и references.
  • Для JSON секции интерпретируются семантически:
    • Templatestructure
    • Script → root metadata ($type, name, props, componentProperties)
    • Stylesstyles

Настройки codegen

Откройте Inspect → Code → Settings (кнопка с шестерёнкой), чтобы настроить генерацию для текущего Figma-файла. Пустые поля используют дефолты SXL, поэтому команда может переопределять только нужные соглашения.

Основные настройки:

  • Naming: компонент иконки, pattern имени иконки, шаблон boolean prop collision, шаблон swap prop collision.
  • Styling: имя root class, регистр CSS-классов (kebab-case или camelCase), header comments.
  • Imports: шаблон пути импорта компонентов, например @/components/{Name}.
  • Mobile: имя Swift token enum, Android drawable prefix, DivKit profile (Generic по умолчанию), DivKit validation mode и опциональный DivKit profile JSON для проектных mappings.
  • Testing: опциональный test attribute, например data-testid.
  • Icon rules: упорядоченные правила для имён иконок по page, section, set, variant или marker в description.

Токены pattern для иконок:

  • {baseName} / {name} — нормализованное имя иконки/слоя
  • {setName} — имя component set
  • {pageName} — имя страницы Figma
  • {sectionName} — ближайшая section
  • {variant.<axis>} — значение оси variant

Правила проверяются сверху вниз. Первое совпадение выигрывает; если совпадений нет, SXL использует default icon pattern, а затем встроенный icon resolver.

Пример:

TEXT
Icon component: Icon
Icon name pattern: {baseName}
Component import path: @/components/{Name}
Rule: if pageName = Icons and variant.Size = 24 -> ui-{baseName}-{variant.Size}

Режимы отображения (Styled / Decomposed / Raw)

РежимПоведение токенов/стилейКогда использовать
StyledПредпочитает композитные style-ссылки (TextStyle/EffectStyle и т.д.), сохраняет variable-синтаксис.Нужен максимально короткий и DS-ориентированный вывод.
DecomposedРаскладывает композиты на атомарные свойства, при этом сохраняет variable references.Нужна явная структура CSS/стилей, но с токенами.
RawРезолвит значения в литералы (без variable references).Быстрый прототип или дебаг резолвнутых значений.

Примечания:

  • Styled — не "всё или ничего": если валидной композитной ссылки нет, генератор падает обратно на реальные значения ноды и не теряет данные.
  • На больших деревьях возможна усечённая генерация (safety budgets); в коде появляется заметка о truncation.

Поведение для Component Set

Если выделен COMPONENT_SET:

  • Vue и React генераторы строят единый компонентный контракт с variant props и class mapping.
  • DivKit-вывод строит один card с отдельным state на каждый вариант.
  • Вкладка All содержит собранный файл для handoff в разработку.
  • В title вкладки отражается количество вариантов.

Особенности React-вывода

React-вывод рассчитан на проекты React 19:

  • function component в .tsx
  • типизированные props с ReactNode для slots и instance swaps
  • CSS Modules и clsx
  • настраиваемые component imports через template пути
  • опциональный data-testid, если он задан в настройках
  • explicit Figma modes представлены как data-fig-mode-* attributes для web-целей

Слои SLOT мапятся в children. Вложенные component instances становятся импортированными PascalCase tags, когда SXL может вывести имя компонента.


Особенности UIKit-вывода

UIKit-вывод генерирует imperative Swift UIView subclass:

  • UIStackView для auto-layout-like структуры
  • UILabel / UIImageView для text и image/icon nodes
  • token-aware colors, dimensions, typography, borders и effects там, где они поддержаны
  • вложенные component instances разворачиваются в UIKit subtrees
  • explicit Figma modes выводятся комментариями, потому что в UIKit нет web-like data-* attributes

Имя Swift token enum настраивается в Codegen settings. Raw mode резолвит токены в литералы для debugging или быстрых прототипов.


Особенности DivKit-вывода

DivKit-вывод — это copy-ready JSON document для передачи мобильным разработчикам. Профиль по умолчанию — Generic; он нейтрален к проекту и не генерирует fake assets, fake actions, payloads или произвольные custom_type.

Контракт документа

  • All возвращает { card } или { templates, card }.
  • card.log_id есть всегда.
  • card.states всегда непустой.
  • Выделенный COMPONENT_SET даёт один state на каждый variant; выделенный component, variant или обычная node дают один state.
  • Template возвращает diagnostics по templates и извлечённые templates, если безопасная extraction возможна.
  • Variables возвращает тот же фрагмент card.variables, который используется в generated card.
  • References содержит warnings по placeholders, неподдержанным Figma/SXL semantics, fallback для constraints, невалидному profile JSON и host-specific требованиям.

Переменные и modes

DivKit-вывод не содержит CSS-синтаксис переменных вроде var(--token). Figma/SXL token references преобразуются в DivKit variables:

  • простые single-mode значения используют @{token_name};
  • multi-mode collections генерируют mode variable и dictionary variable;
  • чтение из dictionary идёт через typed helpers, например @{getOptIntegerFromDict(12, sxl_tokens_typography, sxl_mode_typography, 'fs_label_sm')};
  • строковые literals внутри expressions используют одинарные кавычки, чтобы вывод оставался совместимым с DivKit expression DSL;
  • integer-поля DivKit вроде font_size, line_height, font_weight_value, max_lines и border.corner_radius используют integer variables/getters.

Маппинг структуры

  • FRAME и COMPONENT мапятся в container.
  • TEXT мапится в text.
  • RECTANGLE и ELLIPSE мапятся в visual containers с background, border, radius, size и opacity там, где это поддержано.
  • LINE мапится в separator.
  • Inline children внутри SLOT компилируются как обычные containers.
  • Reference-mode SLOT, INSTANCE и ICON в Generic остаются безопасными placeholders, пока project mapping не объяснит SXL, какой реальный DivKit node нужно сгенерировать.
  • Для выбранной root-ноды и вложенных нод в overlap-контейнерах live Figma constraints мапятся независимо по каждой оси: MIN сохраняет фиксированный размер у физического левого/верхнего края, MAX — у правого/нижнего края, а STRETCH использует match_parent с физическими отступами от краёв.
  • Точный CENTER мапится в выравнивание по центру. У CENTER с ненулевым смещением и SCALE нет универсального кросс-платформенного эквивалента в DivKit, поэтому SXL сохраняет текущее фиксированное положение, если его можно представить через неотрицательный физический anchor.
  • Координаты вариантов внутри Component Set используются только для организации макета и не смещают root-ноды сгенерированных states.

Предупреждения о constraints в References

  • Проверяйте References, если responsive-маппингу мешают смещение от центра, SCALE, отрицательная геометрия или конфликт с явно заданным margin. Fallback warning сообщает, удалось ли сохранить точное текущее положение через фиксированный физический anchor; degraded warning означает, что безопасно представить это положение не удалось.
  • Absolute child внутри flow-контейнера остаётся в исходном flow и получает в References unsupported warning для позиционирования по main axis и absolute placement. При этом DivKit codegen может безопасно применить constraints по поперечной оси parent — например, horizontal STRETCH превращается в width: match_parent внутри vertical flow — не меняя flow, HUG sizing, z-order или layout Gallery.
  • Геометрия constraints используется только DivKit codegen. Composition JSON, Apply и другие codegen targets сохраняют прежний вывод и поведение.

Profiles и validation

Validation mode контролирует, какие runtime-допущения разрешены:

  • Strict Playground — дефолт для Generic. Он оставляет вывод совместимым с публичным DivKit playground и блокирует host-only schemes/custom blocks.
  • Host App предназначен для project profiles. Он разрешает только schemes и custom blocks, которые явно разрешены активным профилем.

Profiles хранятся в Figma-файле, а не только в локальном browser storage:

  • Generic — дефолт для каждого файла и каждого пользователя.
  • NewMain BDUI включается только явно. Он использует host-provided app_theme для light/dark color modes и разрешает только contract-approved asset/action schemes и custom blocks.
  • Custom подходит командам, которые владеют собственным DivKit host app contract.

Project mappings

DivKit profile JSON задаёт project mappings:

JSON
{
  "icons": {
    "circle-info": { "image_url": "https://cdn.example.com/icons/circle-info.svg" }
  },
  "slots": {
    "slot.class:progress": { "type": "custom", "custom_type": "new_main_story_progress" }
  },
  "actions": {
    "cta": "div-action://open/details"
  },
  "fonts": {
    "SF Pro Display": "display"
  },
  "customTypes": ["new_main_story_progress"]
}

Mappings намеренно явные:

  • icon mappings превращают ICON / icon-like INSTANCE nodes в image nodes с image_url, опциональным tint_color, размером и accessibility metadata;
  • slot mappings могут генерировать container, custom block, gallery, data node или named template reference;
  • action mappings могут выводить tap, longtap, visibility или selected actions из explicit metadata/profile aliases;
  • font mappings могут переводить имена Figma fonts в host font aliases.

Если mapping отсутствует или заблокирован active validation mode, SXL сохраняет валидный placeholder output и пишет причину в References.

Требования к host app

Мобильные приложения, которые используют non-generic output, должны предоставить соответствующий runtime contract:

  • custom fonts, зарегистрированные в DivKit host;
  • asset resolvers для custom image URL schemes;
  • action handlers для project action schemes;
  • custom div implementations для разрешённых custom_type;
  • mode variable вроде app_theme, если профиль использует host-provided theme switching.

Как разбирать неожиданный вывод

Используйте по порядку:

  1. Переключите Styled/Decomposed/Raw, чтобы отделить token- и literal-поведение.
  2. Проверьте Variables — какие bindings реально собраны в текущем subtree.
  3. В нативной панели Code откройте Debug (если появилась) и посмотрите trace последней генерации.
  4. Убедитесь, что выбран правильный scope (component vs nested layer vs component set).

Связанные разделы