npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sxl-studio/token-transformer

v3.1.2

Published

Transform DTCG design tokens to CSS/SCSS, Swift, Kotlin, Android XML, and JSON manifests

Downloads

1,025

Readme

SXL Token Transformer

YAML-first утилита для преобразования дизайн-токенов в:

  • CSS custom properties
  • SCSS variables
  • Swift-константы (SwiftUI)
  • Kotlin-константы (Compose)
  • Android XML ресурсы (colors.xml, dimens.xml, strings.xml, bools.xml, integers.xml)

Установка

npm install @sxl-studio/token-transformer

Команды

# трансформация в smart incremental режиме (по умолчанию)
npx tsx src/cli.ts sync --config ./sxl-transform.config.yaml

# принудительный полный rebuild
npx tsx src/cli.ts sync --config ./sxl-transform.config.yaml --force

# только выбранные outputs
npx tsx src/cli.ts sync --config ./sxl-transform.config.yaml --only-output css-root --only-output swift-root

# только выбранные файлы (glob)
npx tsx src/cli.ts sync --config ./sxl-transform.config.yaml --only-file "modes/dark.css"
npx tsx src/cli.ts sync --config ./sxl-transform.config.yaml --only-file "css-root:modes/dark.css"

# валидация конфига
npx tsx src/cli.ts validate-config --config ./sxl-transform.config.yaml

# генерация стартового конфига
npx tsx src/cli.ts init --path ./sxl-transform.config.yaml

# help по конкретной команде
npx tsx src/cli.ts help sync
npx tsx src/cli.ts validate-config --help

Smart vs force

  • smart (по умолчанию): пересобирает только затронутые output-файлы на основе изменённых/удалённых source-файлов и state предыдущего запуска.
  • force: пересобирает все output-файлы из конфига безусловно.

Дополнительные флаги:

  • --mode smart|force
  • --force (сокращение для --mode force)
  • --state-file <path> (переопределить путь state-файла, по умолчанию <config-name>.state.json)
  • --only-output <id> (можно повторять, выбор output id)
  • --only-file <glob> (можно повторять, выбор output-файлов по шаблону)

Формат конфига

Поддерживается только YAML. JSON-конфиг умышленно не поддерживается.

Минимальная структура:

version: 1
source:
  tokenDir: ../../Plugin/test/tokens_project_new
  configFile: config.json
  include: ["**/*.json"]
  exclude: ["config.json", "**/diff-id*.json"]

options:
  remBase: 16
  collisionStrategy: error # error | suffix | namespace-by-file | namespace-by-mode
  unsupportedTypes:
    default: error
    types:
      template: skip
      composition: skip
      grid: skip

tokenSets:
  - id: root
    selectors:
      - collection: Core
        mode: Default
      - collection: Themes
        mode: Dark
        refModeMap:
          Projects: AUI
          Core: Default
      - files: ["projects/aui/*.json"]

outputs:
  - id: css-root
    platform: css # css | scss | swift | uikit | kotlin | xml | manifest
    outputDir: ./dist/css/adminui
    prefix: ds
    suffix: v2
    resolveAliases: false
    splitEffects: true
    showDescriptions: true
    files:
      - tokenSet: root
        output: root.css
        # prefix/suffix можно переопределить для конкретного mapping:
        # prefix: cmp
        # suffix: beta

  - id: tokens-manifest
    platform: manifest
    outputDir: ./dist/manifest/adminui
    files:
      - tokenSet: root
        output: tokens-manifest.json
        options:
          schemaVersion: "1.0"
          includeResolvedValue: true
          includeOriginalValue: true
          includeReferences: true
          includeSource: true
          includeExtensions: false
          includePrivate: true
          groupBy: flat # flat | collection | mode | file

Каждый output должен содержать минимум один generation-блок: files, bundles, bundlesFromCollections или indexes.

CSS / SCSS Output Contract

CSS-файлы по умолчанию оборачиваются в :root. Wrapper selector можно переопределить для статичного файла, split-файла или bundle:

outputs:
  - id: css-app
    platform: css
    outputDir: ./dist/css
    files:
      - tokenSet: root
        output: root.css
        selector: ":root"
      - tokenSet: dark
        output: themes/dark.css
        selector: "[data-theme='dark']"
      - tokenSet: components
        splitBySourceFile:
          include: ["components/**/*.style.json"]
          outputPattern: "{component}/{component}.css"
        selector:
          - ":root"
          - "[data-component='{component}']"

selector работает только для CSS. Если указать его для scss, swift, uikit, kotlin, xml или manifest, Transformer выдаст warning и проигнорирует настройку.

CSS/SCSS entrypoint-файлы генерируются через indexes:

outputs:
  - id: css-app
    platform: css
    outputDir: ./dist/css
    files:
      - tokenSet: root
        output: root.css
    indexes:
      - output: index.css
        imports:
          - ./root.css
        includeGenerated:
          - components/**/*.css
        exclude:
          - index.css
          - "**/*.internal.css"
        sort: generated-order # generated-order | alpha
        skipMissing: true
        strict: false
  • CSS indexes генерируют @import "...";.
  • SCSS indexes генерируют @use "..." as *;.
  • Indexes поддержаны только для css и scss.
  • Явные imports резолвятся относительно index-файла.
  • includeGenerated матчится по файлам того же output, включая файлы из state в smart-mode.
  • Index-файлы хранятся в state и участвуют в stale cleanup как обычные generated files.

bundles нужны, когда несколько source token files нужно собрать в один output без создания отдельного tokenSet под каждую группу:

outputs:
  - id: css-components
    platform: css
    outputDir: ./dist/components
    files:
      - tokenSet: components
        splitBySourceFile:
          include: ["components/**/*.style.json"]
          exclude: ["components/WBanner/**/*.style.json"]
          outputPattern: "{component}/{component}.css"
    bundles:
      - tokenSet: components
        output: WBanner/WBanner.css
        include:
          - components/WBanner/**/*.style.json
        selector: ":root"

Bundles используют тот же token graph, filtering, unsupported-type policy, aliases, custom formatters и platform emitters, что и обычные files. selector внутри bundle всё равно применяется только к CSS.

bundlesFromCollections нужен, когда группы bundle уже описаны в source.configFile или top-level projectConfig:

outputs:
  - id: css-components
    platform: css
    outputDir: ./dist/components
    resolveAliases: false
    files:
      - tokenSet: components
        splitBySourceFile:
          include: ["components/**/*.style.json"]
          excludeBundledSources: true
          outputPattern: "{fileName}.css"
    bundlesFromCollections:
      - tokenSet: components
        mode: Default
        include:
          - WBanner
          - WInput
        fileInclude:
          - components/**/*.style.json
        fileExclude:
          - "**/__draft__/*.json"
        outputPattern: "{collection}.css"
        selector: ":root"
        strict: true
    indexes:
      - output: index.css
        includeGenerated:
          - "**/*.css"
        exclude:
          - index.css

bundlesFromCollections читает enabled mode.files из config.json / projectConfig, фильтрует их через fileInclude / fileExclude и генерирует один bundle на matched collection. Поддержанные placeholders: {collection}, {mode}, {collectionKebab}, {collectionSnake}, {collectionLower}, {modeKebab}, {modeSnake}, {modeLower}.

Чтобы избежать двойной генерации, используйте splitBySourceFile.excludeBundledSources: true. Для явного контроля без генерации bundles используйте splitBySourceFile.excludeFromCollections.

Quality gates

npm run eslint
npm run typecheck
npm run test
npm run build
npm run check

Важно

  • Запрещённые к трансформации типы: template, composition, grid (рекомендуемый профиль: template/composition/grid -> skip, остальные unsupported -> error).
  • Поддержан figma.modify, включая chain и alias-based параметры модификаторов.
  • Поддержана безопасная математика (+ - * / %, round, floor, ceil, clamp, и др.) без eval.
  • Для selector по collection/mode можно управлять зависимостями:
    • includeRefs: true|false — подключать ли ref-цепочки из token config.json в resolver scope.
    • refModeMap — принудительно выбрать mode для зависимых коллекций (например Projects: AUI).
  • Аффиксы имен настраиваются в YAML:
    • outputs[].prefix / outputs[].suffix — для всего output
    • outputs[].files[].prefix / outputs[].files[].suffix — переопределение на уровне mapping
    • splitBySourceFile.prefixPattern / splitBySourceFile.suffixPattern — для split-генерации по файлам
  • В режиме --only-file утилита не делает stale-cleanup вне выбранных файлов: точечная генерация безопасна для остального output.
  • SCSS-выгрузка ориентирована на token-first подключение: root-файлы нужно подключать до component-файлов в entrypoint, чтобы межфайловые $token-ссылки резолвились детерминированно.
  • CSS selector поддерживает статичные селекторы и split placeholders вроде {component}. CSS/SCSS indexes генерируют entrypoints и участвуют в smart state/stale cleanup. bundles и bundlesFromCollections группируют source-файлы в один output через тот же emitter pipeline, а не через конкатенацию готовых строк.
  • Android XML: если color токен содержит CSS linear-gradient(...), transformer генерирует нативный drawable/*.xml, а не невалидное значение в colors.xml.
  • platform: manifest генерирует JSON-артефакт из того же resolved token graph, что и CSS/native outputs. Manifest содержит name, cssVar, path, type, value, resolvedValue, originalValue, references, sourceFile и source metadata для документации, Storybook/devtools и аудита миграций.
  • Manifest level и weight читаются из token extensions (level, sxl.level, sxl.weight), если они есть; они не выводятся из path или названия collection.
  • Manifest options можно задавать на уровне outputs[].options или конкретного outputs[].files[].options. Поддержаны cssVarPrefix, cssVarSuffix, includePrivate, includeSource, includeExtensions, groupBy, schemaVersion.

Матрица Поддержки Типов (CSS / SCSS / Swift / UIKit / Kotlin)

Поддерживаются:

  • color, gradient, img, fill, opacity
  • dimension, number, spacing, sizing
  • border, borderWidth, borderRadius, strokeStyle
  • typography, fontFamily, fontWeight, fontStyle, fontSize, lineHeight, letterSpacing, paragraphSpacing, paragraphIndent, textCase, textDecoration
  • shadow, backdrop-blur, blur, glass, effects
  • boolean, text
  • transition, duration, cubicBezier (как токены значений/spec, без auto-apply к UI-элементам)

Исключены из трансформации:

  • template, composition, grid

Manifest поддерживает те же разрешённые типы токенов и намеренно не эмитит запрещённые template, composition, grid.

Политика no-hallucination:

  • Если токен невалиден для платформы, он не “додумывается”: фиксируется error, токен не эмитится.
  • Если алиас неразрешим, поведение строго по unresolvedAliases (error | warn | ignore).
  • Для прод-профиля рекомендуется unsupportedTypes.default: error.