Capa de árbol tree.ts
Construye un árbol anidado a partir del
path -> ResolvedTokenplano, para que cada target pueda emitir la salida según la jerarquía de espacios de nombres.
Por qué hace falta un árbol
Sección titulada «Por qué hace falta un árbol»Los tokens están anidados en el JSON (color.primary.default), pero las fases de carga y de resolución trabajan con un Map<path, ResolvedToken> plano (práctico para detectar duplicados, resolver refs y fusionar el modo oscuro). Al llegar a la fase de generación, el object Color { object Primary { ... } } de Kotlin, el enum Color { enum Primary { ... } } de Swift y los comentarios de sección de C necesitan todos ellos una estructura anidada — de ahí que primero se construya el árbol.
interface TokenTreeGroup { name: string tokens: { name: string; token: ResolvedToken }[] // los tokens directos bajo el grupo (se conservan los nombres originales) children: TokenTreeGroup[] // los subgrupos}Ejemplo de la transformación:
color.primary.default => { name: 'color', children: [ { name: 'primary', children: [ { name: 'default', tokens: [{ name: 'default', token }] } ] } ] }Funciones
Sección titulada «Funciones»buildTokenTree(tokens: ResolvedToken[]): TokenTreeGroup[]
Sección titulada «buildTokenTree(tokens: ResolvedToken[]): TokenTreeGroup[]»La entrada. Se crea una raíz virtual, se llama a insert(root, segments, token, 0) para cada token y, por último, se devuelve root.children (la propia raíz virtual no aparece).
insert(group, segments, token, depth): void
Sección titulada «insert(group, segments, token, depth): void»Función recursiva interna:
const name = segments[depth]if (depth === segments.length - 1) { group.tokens.push({ name, token }) // el último segmento: entra en tokens return}let child = group.children.find((c) => c.name === name)if (!child) { child = { name, tokens: [], children: [] } group.children.push(child) // si no existe, se crea el subgrupo}insert(child, segments, token, depth + 1)Los subgrupos con el mismo nombre solo se crean una vez; los siguientes tokens con el mismo prefijo reutilizan el subgrupo ya creado.
pascalCase(name: string): string
Sección titulada «pascalCase(name: string): string»Convierte el nombre del grupo a PascalCase, para la nomenclatura de los grupos en los object de Kotlin / los enum de Swift / las class de ArkTS:
return name.charAt(0).toUpperCase() + name.slice(1)Cómo usa el árbol cada plataforma
Sección titulada «Cómo usa el árbol cada plataforma»| Plataforma | Uso |
|---|---|
| Android | emitTree emite recursivamente object PascalCase { ... }, con miembros val name = literal |
| iOS | emitTree emite recursivamente public enum PascalCase, con miembros public static let name = ... |
| HarmonyOS | emitTree emite recursivamente class PascalCase (las clases anidadas no llevan export), con miembros static readonly name: T = ... |
| C | Estilo plano de #define; el árbol solo sirve para generar los comentarios de sección /* --- group.path --- */ |
Para más detalles, véanse Las cinco plataformas objetivo.
Copyright © 2024-2026 FengMo WenXue