跳转到内容

构树层 tree.ts

把扁平的 path -> ResolvedToken 构造成嵌套树,供各 target 按命名空间层级输出。

令牌在 JSON 里是嵌套的(color.primary.default),但装载与解析阶段都是扁平的 Map<path, ResolvedToken>(方便查重、ref 解析、暗色合并)。到了生成阶段,Kotlin 的 object Color { object Primary { ... } }、Swift 的 enum Color { enum Primary { ... } }、C 的分节注释都需要嵌套结构——所以先构树。

interface TokenTreeGroup {
name: string
tokens: { name: string; token: ResolvedToken }[] // 分组下的直接令牌(按原名保留)
children: TokenTreeGroup[] // 子分组
}

转换示例:

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

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

Section titled “buildTokenTree(tokens: ResolvedToken[]): TokenTreeGroup[]”

入口。建一个虚拟根,对每个令牌调 insert(root, segments, token, 0),最后返回 root.children(虚拟根本身不出现)。

insert(group, segments, token, depth): void

Section titled “insert(group, segments, token, depth): void”

内部递归函数:

const name = segments[depth]
if (depth === segments.length - 1) {
group.tokens.push({ name, token }) // 末段:入 tokens
return
}
let child = group.children.find((c) => c.name === name)
if (!child) {
child = { name, tokens: [], children: [] }
group.children.push(child) // 不存在则建子分组
}
insert(child, segments, token, depth + 1)

同名子分组只建一次,后续同前缀的令牌复用。

组名转 PascalCase,用于 Kotlin object / Swift enum / ArkTS class 的分组命名:

return name.charAt(0).toUpperCase() + name.slice(1)
端 用法
Android emitTree 递归输出 object PascalCase { ... },成员 val name = literal
iOS emitTree 递归输出 public enum PascalCase,成员 public static let name = ...
鸿蒙 emitTree 递归输出 class PascalCase(嵌套类不带 export),成员 static readonly name: T = ...
C 扁平 #define 风格,树只用来生成分节注释 /* --- group.path --- */

详见 五个 target。

Copyright © 2024-2026 风默文学 | 宁ICP备2024006574号 | 公安备案徽标苏公网安备32040002010537