Aller au contenu

Couche de construction arborescente — tree.ts

Construire une arborescence imbriquée à partir d’un path -> ResolvedToken aplati, afin que chaque cible puisse émettre selon la hiérarchie des espaces de noms.

Dans le JSON, les jetons sont imbriqués (color.primary.default), mais les étapes de chargement et de résolution travaillent toutes deux sur une Map<path, ResolvedToken> aplatée (pratique pour la détection des doublons, la résolution des refs, la fusion du mode sombre). À l’étape de génération, les object Color { object Primary { ... } } de Kotlin, les enum Color { enum Primary { ... } } de Swift et les commentaires de section de C nécessitent tous une structure imbriquée — d’où la construction préalable d’une arborescence.

interface TokenTreeGroup {
name: string
tokens: { name: string; token: ResolvedToken }[] // Les jetons directs sous le groupe (conservés sous leur nom d'origine)
children: TokenTreeGroup[] // Les sous-groupes
}

Exemple de conversion :

color.primary.default =>
{ name: 'color', children: [
{ name: 'primary', children: [
{ name: 'default', tokens: [{ name: 'default', token }] }
] }
] }

buildTokenTree(tokens: ResolvedToken[]): TokenTreeGroup[]

Section intitulée « buildTokenTree(tokens: ResolvedToken[]): TokenTreeGroup[] »

Le point d’entrée. Crée une racine virtuelle, appelle insert(root, segments, token, 0) pour chaque jeton, et retourne finalement root.children (la racine virtuelle elle-même n’apparaît jamais).

La fonction récursive interne :

const name = segments[depth]
if (depth === segments.length - 1) {
group.tokens.push({ name, token }) // Dernier segment : va dans tokens
return
}
let child = group.children.find((c) => c.name === name)
if (!child) {
child = { name, tokens: [], children: [] }
group.children.push(child) // S'il n'existe pas, on crée le sous-groupe
}
insert(child, segments, token, depth + 1)

Un sous-groupe homonyme n’est créé qu’une seule fois ; les jetons suivants avec le même préfixe le réutilisent.

Convertit les noms de groupe en PascalCase, pour le nommage des groupes dans les object Kotlin / les enum Swift / les class ArkTS :

return name.charAt(0).toUpperCase() + name.slice(1)
Cible Usage
Android emitTree émet récursivement des object PascalCase { ... }, avec des membres val name = literal
iOS emitTree émet récursivement des public enum PascalCase, avec des membres public static let name = ...
HarmonyOS emitTree émet récursivement des class PascalCase (les classes imbriquées sans export), avec des membres static readonly name: T = ...
C Un style aplati en #define ; l’arborescence ne sert qu’à générer les commentaires de section /* --- group.path --- */

Voir Les cinq cibles.

Copyright © 2024-2026 FengMo WenXue