Pipeline Overview
pnpm codegen executes codegen/src/index.ts. The complete pipeline:
package.json version │ ▼loadTokenFiles() Load tokens/*.json, Ajv structural validation, flatten │ Returns LoadedTokenFile[] (each file carries namespace / isDark / flat) ▼resolveTokens() ref resolution (with cycle detection) + dark-mode merging │ Returns { tokenSet, orphanDarkPaths, refMap } ▼loadSpecs() Load specs/*.json (schema validation)loadCases() Load cases/*.json (schema validation) │ ▼Assemble CodegenInput { tokens: tokenSet, specs, cases, version } │ ▼Delete the entire dist/ and rebuild │ ▼Run the 5 targets in order ──► android → ios → harmony → c → docs │ Each target.generate(input) returns GeneratedFile[] ▼Write each file to dist/<outDir>/<relativePath>Entry file codegen/src/index.ts
Section titled “Entry file codegen/src/index.ts”Constants
Section titled “Constants”| Constant | Value |
|---|---|
ROOT |
Repository root (two levels up from import.meta.dirname) |
DIST |
<ROOT>/dist |
targets |
[androidTarget, iosTarget, harmonyTarget, cTarget, docsTarget], order fixed |
main()
Section titled “main()”function main(): voidThe only entry point (index.ts exports nothing; main() is an internal function called at the bottom of the file). Steps:
readVersion()reads thepackage.jsonversion numberloadTokenFiles()loads the tokensresolveTokens(files)resolves them and takes thetokenSetloadSpecs()/loadCases()load the contracts and cases- Assemble the
CodegenInput - When
existsSync(DIST),rmSync(DIST, { recursive: true })— delete-then-build, guaranteeing no stale artifacts - Call
generate(input)per target, writing files todist/<outDir>/<relativePath>and printing a[target] pathlog line for each artifact - A final summary line with the target count, file count, and version
The file-header comment declares red line 1 explicitly: generate token skeletons only, never any UI implementation.
Core interfaces (codegen/src/types.ts)
Section titled “Core interfaces (codegen/src/types.ts)”Below are the four most commonly used interfaces of the pipeline; the complete reference for all 16 exported types is in Type Definitions — types.ts.
CodegenTarget
Section titled “CodegenTarget”interface CodegenTarget { name: string // Log prefix, e.g. 'android' outDir: string // Subdirectory under dist/, e.g. 'android' generate(input: CodegenInput): GeneratedFile[]}Every platform target implements this interface. Adding a platform = adding a target and appending it to the targets array.
CodegenInput
Section titled “CodegenInput”interface CodegenInput { tokens: TokenSet // The resolved light token set + dark overrides specs: ComponentSpec[] // Currently consumed by no target (reserved for future component docs / test generation) cases: ComponentCases[] // Same as above version: string // The package.json version number, written into the header comment of every artifact}GeneratedFile
Section titled “GeneratedFile”interface GeneratedFile { relativePath: string // Output path relative to dist/<outDir>/ content: string}TokenSet
Section titled “TokenSet”interface TokenSet { tokens: ResolvedToken[] // Light tokens (path lexicographic order) byPath: Map<string, ResolvedToken> // Fast lookup by path dark: DarkOverrides // path -> dark override value}Total artifact count
Section titled “Total artifact count”| target | Files |
|---|---|
| android | 2 (LhTokens.kt + LhDarkTokens.kt) |
| ios | 2~3 (+ LhShadow.swift, when shadow tokens exist) |
| harmony | 2~3 (+ LhShadow.ets) |
| c | 2 |
| docs | 3 |
The ios / harmony shadow files are only generated when shadow tokens exist, so the total file count changes with the token content; dist/ is authoritative.
Related modules
Section titled “Related modules”| Module | Responsibility |
|---|---|
| load.ts | Loading and structural validation |
| resolve.ts | Reference resolution and dark-mode merging |
| format.ts | Neutral-value parsing and per-target formatting |
| tree.ts | Flat to nested |
| render.ts | Template rendering |
| types.ts | All type definitions |
| targets/ | The five platform targets |
| templates/ | The 7 handlebars templates |
Copyright © 2024-2026 FengMo WenXue