Слой загрузки load.ts
Загрузка JSON + валидация схемы Ajv + уплощение.
load.ts выполняет только структурную валидацию (JSON Schema). Семантическая валидация (соответствие типов значениям, целостность ссылок, обнаружение циклов) происходит в resolve.ts.
interface LoadedTokenFile { fileName: string namespace: string // Префикс пространства имён (color / radius / zIndex; пустая строка означает, что ключи верхнего уровня — это пространства имён) isDark: boolean defaultType?: TokenType // Файловый $type description?: string flat: Map<string, RawToken> // path -> RawToken (после уплощения, с префиксом пространства имён)}Перечень функций
Заголовок раздела «Перечень функций»readJson<T>(filePath: string): T
Заголовок раздела «readJson<T>(filePath: string): T»Читает JSON-файл и выполняет JSON.parse. Внутренняя вспомогательная функция.
listJsonFiles(dir: string): string[]
Заголовок раздела «listJsonFiles(dir: string): string[]»Перечисляет файлы .json в каталоге, исключая schema.json, сортирует и приводит к абсолютным путям. Сортировка гарантирует стабильный порядок загрузки (он влияет на сообщения об ошибках и воспроизводимость артефактов).
namespaceFromFileName(fileName: string): string
Заголовок раздела «namespaceFromFileName(fileName: string): string»Вывод пространства имён из имени файла (запасная логика для случая, когда $namespace не объявлен): отбрасывается суффикс .json, строка разбивается по -, первый сегмент остаётся как есть, а остальные пишутся с заглавной первой буквой, после чего сегменты соединяются.
| Имя файла | Результат |
|---|---|
color.json |
color |
z-index.json |
zIndex |
color-dark.json |
colorDark |
flatten(obj, prefix, out, inheritedType?): void
Заголовок раздела «flatten(obj, prefix, out, inheritedType?): void»Рекурсивно сворачивает вложенный JSON в плоское Map<path, RawToken>:
- Пропускаются все ключи, начинающиеся с
$(мета-свойства) - Сращивание путей:
prefix ? prefix + '.' + key : key - Узел, не являющийся ни листом, ни объектом → ошибка
Путь токена X не является ни токеном-листом, ни группой
Ключевая логика наследования типов: $type, объявленный группой (включая корень файла), распространяется вниз по дереву, но запекается только в листья-литералы:
// Токены-литералы наследуют тип группы; ref-токены сохраняют undefined,// оставляя выбор типа за resolve — он возьмёт его у цели ссылкиif (node.type === undefined && node.ref === undefined && groupType !== undefined) { out.set(path, { ...node, type: groupType })}ref-листья намеренно не «запекаются» — решение о типе откладывается до этапа resolve (первый шаг трёхуровневого приоритета типов; см. Система типов).
isRawToken(node: unknown): node is RawToken
Заголовок раздела «isRawToken(node: unknown): node is RawToken»Предикат типа: узел с ключом value или ref считается листовым токеном; иначе — группой.
loadTokenFiles(tokensDir = <root>/tokens): LoadedTokenFile[]
Заголовок раздела «loadTokenFiles(tokensDir = <root>/tokens): LoadedTokenFile[]»Загружает каталог токенов:
- Читает
tokens/schema.jsonи компилирует его с помощью Ajv (allErrors: true, strict: false) - Читает и валидирует каждый JSON-файл; при неудаче выбрасывается
Ошибка валидации файла токенов: <path>+ отформатированный список ошибок - Пространство имён:
raw.$namespace(если это строка) имеет приоритет, иначе —namespaceFromFileName flatten(raw, namespace, flat)выполняет уплощение- Сборка
{ fileName, namespace, isDark: raw.$dark === true, defaultType: raw.$type, description: raw.$description, flat }
loadSpecs(specsDir = <root>/specs): ComponentSpec[]
Заголовок раздела «loadSpecs(specsDir = <root>/specs): ComponentSpec[]»Тем же образом загружает specs/*.json; при неудаче валидации выбрасывается Ошибка валидации контракта компонента.
loadCases(casesDir = <root>/cases): ComponentCases[]
Заголовок раздела «loadCases(casesDir = <root>/cases): ComponentCases[]»Тем же образом загружает cases/*.json; при неудаче валидации выбрасывается Ошибка валидации золотых сценариев.
formatErrors(errors: ErrorObject[]): string
Заголовок раздела «formatErrors(errors: ErrorObject[]): string»Форматирует объекты ошибок Ajv в список с отступами (instancePath + message).
readVersion(): string
Заголовок раздела «readVersion(): string»Читает version из package.json; используется как часть заголовочного комментария каждого артефакта («источник: @lh-ui/core tokens @ v0.0.1»).
Слои валидации
Заголовок раздела «Слои валидации»| Слой | Где | Что делает |
|---|---|---|
| Структурная валидация | load.ts |
JSON Schema: обязательные поля, значения перечислений, регулярные выражения для имён, additionalProperties: false |
| Семантическая валидация | resolve.ts |
Соответствие типов значениям (assertTypedValue), существование ссылок, обнаружение циклов в ссылках |
| Проверка согласованности | scripts/verify-specs.mts |
Перекрёстная согласованность specs и cases |
Слои выделены потому, что JSON Schema не способна выразить межфайловые и межузловые ограничения вроде «цель ref должна существовать» или «тип должен соответствовать значению».
Copyright © 2024-2026 FengMo WenXue