Aller au contenu

Les cinq cibles

Chaque cible implémente l’interface CodegenTarget ({ name, outDir, generate(input): GeneratedFile[] }) et est appelée à tour de rôle par le pipeline.

Le modèle partagé de construction des artéfacts sombres

Section intitulée « Le modèle partagé de construction des artéfacts sombres »

Les quatre cibles de plateforme utilisent le même schéma pour transformer tokenSet.dark (Map<path, value>) en ResolvedToken[] :

const darkTokens = [...tokenSet.dark.entries()]
.map(([path, value]) => {
const base = tokenSet.byPath.get(path)
return {
path,
type: base?.type ?? ('color' as const), // Le type est pris sur la clé claire de même nom, sinon repli sur color
value,
description: base?.description,
}
})
.sort((a, b) => a.path.localeCompare(b.path))

Puis l’émission suit le même arbre, triée par chemin. Les artéfacts clairs portent des commentaires de description ; l’étalement (spread) est ignoré et commenté explicitement sur toutes les cibles.


Artéfacts : dist/android/top/lhgb/ui/tokens/LhTokens.kt + LhDarkTokens.kt

Constante : PACKAGE = 'top.lhgb.ui.tokens' (la convention familiale du nom de domaine inverse, plan directeur D20)

Retourne { literal, features } — features est l’ensemble des types d’exécution utilisés, et détermine la liste des imports :

Type Littéral features
color ComposeColor(0xAARRGGBB) color
dimension (px) ${d.value}.${usesSp(path) ? 'sp' : 'dp'} dimension
dimension (%) 0.50f // 50% (une fraction, convertie par rapport à la taille du conteneur) (après (v/100).toFixed(3), un zéro de fin est retiré) —
duration 200 // 200ms (millisecondes) —
cubicBezier CubicBezierEasing(0.4f, 0f, 0.2f, 1f) bezier
shadow Shadow(color = ..., offset = Offset(xf, yf), blurRadius = bf) color, shadow
number / string Tel quel / JSON.stringify —

Émet récursivement des object PascalCase { ... } imbriqués, avec des membres val name = literal et la description en commentaire en fin de ligne. features est cumulé au cours du parcours.

buildKotlinBody(tokenSet, rootName, features) / buildDarkKotlinBody(tokenSet, features)

Section intitulée « buildKotlinBody(tokenSet, rootName, features) / buildDarkKotlinBody(tokenSet, features) »

Le nom de l’objet racine clair est passé en paramètre (LhTokens), la racine sombre est toujours LhDarkTokens.

La liste des imports est déterminée par les fonctionnalités réellement utilisées ; ce qui n’est pas utilisé n’est pas importé :

feature import
color androidx.compose.ui.graphics.Color as ComposeColor
dimension androidx.compose.ui.unit.dp + .sp
shadow androidx.compose.ui.graphics.Shadow + androidx.compose.ui.geometry.Offset
bezier androidx.compose.animation.core.CubicBezierEasing

Assemble la bannière d’en-tête « ne pas modifier à la main », le bloc des imports généré selon features et le body, en un fichier .kt complet.


Artéfacts : dist/ios/Sources/LhUITokens/LhTokens.swift + LhDarkTokens.swift ; LhShadow.swift est en outre généré lorsque des jetons d’ombre existent

Type Littéral
color (a=1) SwiftUI.Color(red: 0.169, green: 0.298, blue: 0.486)
color (a<1) Identique + .opacity(0.4)
dimension CGFloat(40) ; % émet une fraction + un commentaire
duration 0.200 // 0.2s (secondes) — les animations SwiftUI s’expriment en secondes, conversion à la compilation (millisecondes ÷ 1000, 3 décimales)
cubicBezier (x1: 0.4, y1: 0, x2: 0.2, y2: 1) // Points de contrôle de Bézier, la cible construit elle-même son easing
shadow LhShadow(color:opacity:radius:x:y:)

Lorsqu’un nom de membre est identique à un mot-clé Swift, il est entouré de contre-apostrophes (comme `default`), sinon l’artéfact ne compile pas.

buildSwiftBody(tokenSet, rootName): string / buildDarkSwiftBody(tokenSet): string

Section intitulée « buildSwiftBody(tokenSet, rootName): string / buildDarkSwiftBody(tokenSet): string »

Assemble la structure racine public enum : le nom de la racine claire est passé en paramètre (LhTokens), la racine sombre est toujours LhDarkTokens, et l’intérieur est rempli récursivement par emitTree dans les deux cas. La bannière d’en-tête est assemblée directement dans iosTarget.generate.

L’idiome Swift des espaces de noms sans instance : des public enum PascalCase imbriqués, avec des membres public static let name = ....


Artéfacts : dist/harmony/tokens/LhTokens.ets + LhDarkTokens.ets ; LhShadow.ets est en outre généré lorsque des jetons d’ombre existent

Type Littéral
color '#FF2B4C7C' (ArkUI accepte les chaînes #AARRGGBB, via toArgbHash)
dimension Une valeur vp pure ; % émet une fraction + un commentaire
duration 200 // 200ms (millisecondes)
cubicBezier [0.4, 0, 0.2, 1] // consommé côté composant via curves.cubicBezierCurve
shadow { color: '#...', radius: 8, offsetX: 0, offsetY: 2 }

La seule plateforme avec des annotations de type (ArkTS est fortement typé) :

Type Annotation
color ResourceColor
dimension Dimension | number
duration / number number
shadow LhShadow
cubicBezier number[]
string string

Une export class racine, les classes imbriquées sans export (les déclarations export ne sont pas autorisées dans le corps d’une classe ArkTS), avec des membres static readonly name: T = literal.

buildEtsBody(tokenSet, rootName): string / buildDarkEtsBody(tokenSet): string

Section intitulée « buildEtsBody(tokenSet, rootName): string / buildDarkEtsBody(tokenSet): string »

Assemble la structure racine export class : le nom de la racine claire est passé en paramètre (LhTokens), la racine sombre est toujours LhDarkTokens, et l’intérieur est rempli récursivement par emitTree dans les deux cas. La bannière d’en-tête est assemblée directement dans harmonyTarget.generate.


Artéfacts : dist/windows/Tokens/LhTokens.cs + LhDarkTokens.cs ; LhShadow.cs est en outre généré lorsque des jetons d’ombre existent, et LhEasing.cs lorsque des jetons de Bézier existent

L’espace de noms est Top.Lhgb.Ui.Tokens (nom de domaine inverse, plan directeur D20).

Convertit une couleur en appel de fabrique WinUI : Windows.UI.Color.FromArgb(0xFF, 0x2B, 0x4C, 0x7C).

Ajoute le suffixe .0 aux entiers (8 → 8.0), pour éviter toute ambiguïté de conversion implicite.

Type Littéral C# Type du champ
color Windows.UI.Color.FromArgb(0xFF, 0x2B, 0x4C, 0x7C) Windows.UI.Color
dimension (entière) 40.0 double
dimension (décimale) 0.5 double
dimension (%) 0.500 // 50% (une fraction, convertie par rapport à la taille du conteneur) double
duration 200 // 200ms (millisecondes) int
cubicBezier new LhEasing(0.4, 0, 0.2, 1) LhEasing
shadow new LhShadow(0xFF..., 0.0, 2.0, 8.0) LhShadow
number 400 / 1.8 int / double
string "Source Code Pro, ..." string

La note (explication d’unité / de conversion) et la description sont fusionnées en un seul commentaire inline ; le point-virgule doit se trouver entre le littéral et le commentaire, sinon les littéraux portant un commentaire (fraction / durée / Bézier / ombre) verraient leur point-virgule absorbé par le commentaire (CS1002).

Convertit en PascalCase : default → Default, extraLarge → ExtraLarge. Ce qui évite au passage les mots-clés contextuels C# que sont default / base (les noms de groupe suivent également la convention pascalCase).

Des public static class imbriquées expriment la hiérarchie des jetons (les classes statiques sont l’idiome C# des espaces de noms), avec des membres public static readonly T Name = literal;.

buildCsBody(tokenSet, rootName) / buildDarkCsBody(tokenSet)

Section intitulée « buildCsBody(tokenSet, rootName) / buildDarkCsBody(tokenSet) »

Le nom de la racine claire est passé en paramètre (LhTokens), la racine sombre est toujours LhDarkTokens, et l’intérieur est rempli récursivement par emitTree dans les deux cas. La bannière d’en-tête est rendue dans windowsTarget.generate par windows/LhTokens.cs.hbs.

export { csTokenPath } — convertit un chemin pointillé en LhTokens.Color.Primary.Default, pour les tests et la consommation externe.


docs.ts — les artéfacts de documentation (sans modèle)

Section intitulée « docs.ts — les artéfacts de documentation (sans modèle) »

Artéfacts : dist/docs/tokens.md + tokens.light.json + tokens.dark.json

La seule cible qui n’utilise pas de modèles handlebars ; elle assemble des chaînes de caractères directement en code.

Une couleur est rendue sous la forme valeur brute → #rrggbb (lorsque a<1, → rgba(r, g, b, a)), les autres types passent directement par String(value).

Émet, regroupé par espace de noms de premier niveau du chemin, des tableaux markdown « Jeton | Type | Clair | Sombre | Description » ; nativeOnly est signalé par « ajout natif » ; la colonne sombre contient — en l’absence de surcharge.

La table des surcharges sombres, triée, puis JSON.stringify(..., null, 2).

L’usage des trois artéfacts est décrit dans Artéfacts docs.

Copyright © 2024-2026 FengMo WenXue