Ce document définit le cycle normal d’une modification du framework Drake.css, les gates obligatoires et la définition de « terminé ». Il complète la charte sans l’assouplir.
Le produit s’appelle officiellement « Drake.css framework » (forme courte : Drake.css). Les
espaces publics suivent la table de renommage de D-012 : API globale Drake (window.Drake),
types Drake*, classes .drk-*, attributs drk-* et data-drk-*, custom properties
--drk-*, artefacts dist/css/drake*.css et dist/js/drake*.js. Le projet amont n’est
désigné ici que comme « l’amont » (voir FORK.md).
La chaîne de référence est :
- Node.js 24.18.0 exact ;
- pnpm 11.4.0 ;
- installation depuis le lockfile avec
pnpm install --frozen-lockfile; - navigateur(s) de validation compatibles avec la cible maintenue par le build.
Une autre version locale peut servir à explorer un problème, mais ses résultats ne suffisent pas à valider une contribution.
fork/mainest la branche stable et doit toujours rester publiable au regard des gates déjà atteints par la feuille de route.- Une modification ordinaire utilise une branche courte :
feat/*,fix/*,refactor/*,test/*,docs/*ouchore/*. - Une intégration amont utilise une branche
sync/*nommée conformément àUPSTREAM.mdet suit ce document. - Une branche ne doit pas mélanger synchronisation amont, port Panda.css, changement d’asset et redesign.
Les commits DEVRAIENT être atomiques et suivre les préfixes conventionnels hérités de
l’amont : build:, chore:, ci:, docs:, feat:, fix:, perf:, refactor:,
style: ou test:.
Le contributeur identifie :
- le besoin vérifiable ;
- la catégorie ordinaire, sensible ou constitutionnelle ;
- les surfaces C0 à C3 concernées ;
- les sources canoniques et sorties générées touchées ;
- les licences ou versions épinglées éventuellement affectées ;
- l’impact HTML initial, mobile-first, SEO, accessibilité et Core Web Vitals.
Un changement constitutionnel s’arrête ici jusqu’à acceptation d’un amendement.
Avant de modifier le code :
- relever
git status; - exécuter ou documenter le test qui caractérise l’état actuel ;
- conserver un exemple minimal de la régression ou du comportement ;
- pour un changement de compatibilité, identifier l’équivalent dans la référence de parité
D-012 : le dernier état vert de
fork/mainantérieur au renommage (voirDECISIONS.md). La parité C0 à C3 se mesure contre cette référence interne, pas contre l’amont ; - capturer le HTML avant runtime et caractériser le comportement sans JavaScript lorsque le composant expose du contenu, une navigation ou une action essentielle.
- Modifier
panda.config.tset les modules de styles TypeScript soussrc/styles/(section 6) ; le port Panda.css est achevé,src/less/etsrc/scss/n’existent plus. - Modifier les générateurs pour les CSS Tabler ou Inter.
- Modifier exclusivement le TypeScript pour le runtime navigateur. Le port TypeScript est achevé : aucune source JavaScript navigateur NE DOIT être introduite, ni aucune coexistence JavaScript/TypeScript recréée.
- Rendre le contenu et la navigation dans le HTML serveur ou prérendu ; réserver le TypeScript à l’amélioration progressive.
- Écrire la mise en page de base pour 320 pixels CSS, puis les enrichissements avec
min-width. - Ne jamais corriger directement
dist/,src/styles/tabler.tsni une CSS générée par Panda. - Ne jamais ajouter de mixin Less ou SCSS (section 6.4).
Le test le plus petit qui reproduit le comportement est ajouté ou mis à jour. Pour un composant interactif, il couvre selon le cas :
- création par attribut
drk-*et par APIDrake; - ajout, retrait et reconnexion dans le DOM ;
- options initiales et mutation d’attribut ;
- souris, tactile et clavier ;
- focus, rôles, noms et états ARIA ;
- LTR et RTL ;
- réduction de mouvement ou autres préférences pertinentes ;
- exécution désactivée : contenu, liens et actions essentielles ;
- reflow à 320 pixels CSS, cibles tactiles et parité mobile/bureau ;
- HTML initial, métadonnées, données structurées et statuts HTTP lorsque applicables ;
- impact LCP, INP et CLS ou leurs mesures de laboratoire applicables ;
- destruction sans listener, observer ou nœud résiduel.
Les gates applicables sont exécutés dans l’ordre de la section 9. Une erreur est corrigée à sa source ; un test ou un contrôle n’est pas neutralisé pour obtenir un résultat vert.
Avant livraison :
- distinguer sources et sorties générées ;
- rechercher un changement hors périmètre ;
- vérifier les bannières de licence ;
- confirmer l’absence de fichiers
.svgTabler et.woff/.woff2autonomes distribués ; - confirmer l’absence de source JavaScript navigateur et de registre SVG JavaScript ;
- confirmer l’absence de résurgence du préfixe hérité (
uk-,data-uk-,--uk-, classes.uk-*) et des noms amont dans les sources, les tests et la distribution — contrôle automatisé par l’audit d’identité depnpm check-frontend(G10), allowlist des zones autorisées danstests/fixtures/frontend-policy-allowlist.json, bannières légales dedist/décomptées ; - confirmer l’absence de nouveau mixin Less ou SCSS ;
- relire le HTML sans runtime, la cascade mobile-first et les signaux SEO applicables ;
- exécuter un second build et vérifier l’absence de diff inexpliqué.
Le compte rendu indique le contrat concerné, les gates exécutés, les divergences connues et les décisions éventuellement ajoutées.
Le port TypeScript est achevé. Cette section ne décrit plus une migration mais les règles de maintenance qui empêchent toute régression.
- TypeScript strict est l’unique langage source du runtime navigateur. Aucun fichier JavaScript source navigateur NE DOIT exister ni réapparaître, y compris dans les tests exécutés par un navigateur.
- esbuild produit le JavaScript compilé exclusivement sous
dist/;tsc --noEmitest l’autorité de type. Le build sépare transpilation et contrôle de types. - Les entrées canoniques sont
src/js/drake.tsetsrc/js/drake-core.ts; les composants compilés sont livrés sousdist/js/components/. - Le dépôt DOIT conserver les options compatibles avec la compilation isolée par esbuild,
notamment
isolatedModules. Les imports de types restent explicites etallowJsNE DOIT PAS couvrir le runtime navigateur. - L’API globale exposée est
Drake(window.Drake) ; les types internes et publics suivent l’espaceDrake*. - L’audit G10 vérifie mécaniquement l’absence de source JavaScript navigateur hors
dist/.
Les types centraux du modèle de composants DOIVENT rester fidèles : props et
constructeurs de coercition, data initiale, computed et watchers, méthodes et leur this,
hooks de cycle de vie, événements, observers et updates, mixins, extends, composants
fonctionnels et instance attachée au nœud DOM.
Les helpers du type defineComponent et defineMixin DOIVENT continuer de fournir le
contexte ThisType et de composer les interfaces. Une maintenance qui dégrade cette
modélisation vers Record<string, any> n’est pas conforme.
Un refactor de types ou de structure :
- conserve les exports, chemins logiques et noms publics ;
- ne change ni algorithme, ni valeur par défaut, ni CSS ;
- ne remplace pas une API dynamique par une nouvelle abstraction runtime ;
- produit un bundle dont le comportement est caractérisé contre la référence de parité.
Les corrections découvertes pendant un refactor sont faites dans un commit séparé avec un test d’échec.
Le port est achevé depuis le 2026-07-21 : panda.config.ts et les modules TypeScript
de src/styles/ (tokens dans tokens.ts, fragments ordonnés core/ et theme/,
module généré tabler.ts) sont l’unique source canonique des styles. src/less/ et
src/scss/ ont été supprimés ; la preuve de parité du port est consignée dans
tests/fixtures/panda-parity-proof.json.
- la CSS distribuée reste statique, générée par
build/panda.jset déterministe ; @pandacss/devest épinglée en version exacte (1.11.4) et suit la même discipline de lockfile que le reste de la chaîne ;- l’ordre des fragments dans
core/index.tsettheme/index.tsEST l’ordre de cascade : tout déplacement est un changement sensible.
Le port initial a été réalisé cascade entière, avec un diff CSS normalisé vide sur les
quatre artefacts (drake.css, drake-core.css et leurs variantes RTL) face à la
référence pré-Panda. L’outil de comparaison est conservé : build/fork/css-parity.js
compare deux feuilles par séquence (contexte, sélecteur, propriété, valeur) avec tri
canonique commutatif. Tout refactor de la génération ou des fragments DOIT fournir un
diff de parité vide (G15) face à la dernière sortie verte, ou documenter les écarts
acceptés dans DECISIONS.md.
Un changement de styles ne modifie ni comportement runtime, ni HTML, ni valeur par défaut ; toute évolution visuelle voulue est un commit séparé postérieur à la parité.
La génération Panda DOIT être déterministe : deux générations successives sur le même arbre produisent des sorties bit-à-bit identiques. Ce contrôle est intégré à G9 et s’exécute avant toute comparaison de parité ; une génération non reproductible bloque le port du composant concerné.
- Aucune source Less ou SCSS (mixin compris) NE DOIT être réintroduite.
- La CSS générée par Panda n’est jamais éditée à la main.
- Aucun doublon de cascade hors
src/styles/NE DOIT exister.
@tabler/icons reste une dépendance de développement épinglée à 3.45.0. Le générateur :
- lit l’intégralité des 5 112 icônes Outline,
brand-*incluses ; - exclut les variantes filled ;
- s’appuie sur le catalogue versionné
src/icons/drake-tabler.json; - normalise et percent-encode les tracés en masques CSS
data:image/svg+xml; - produit
dist/css/drake-tabler-icons.css; - génère la classe de base
.drk-tiet les classes.drk-ti-{nom}; - conserve la bannière MIT ;
- ne copie aucun fichier SVG dans la distribution ;
- produit, exclusivement en CSS, les alias de compatibilité des noms d’icônes hérités ;
- remplace les icônes internes sans registre, bundle ou injection SVG JavaScript.
Un changement de tri doit produire une sortie déterministe.
La migration des consommateurs et les divergences d’alias suivent ICON_MIGRATION.md.
Le générateur Inter :
- part des deux fichiers officiels 4.1 intacts, roman et italic ;
- vérifie leur empreinte ;
- les encode en WOFF2
data:URI dans deux règles@font-facededist/css/drake-inter.css; - configure Inter comme police par défaut du framework via les tokens Panda
(
src/styles/tokens.ts) et la cascade desrc/styles/; - conserve la notice SIL OFL 1.1 ;
- ne copie aucun fichier WOFF ou WOFF2 autonome dans la distribution.
Le sous-ensemblage, la modification des contours ou le renommage sont hors cycle ordinaire.
Les points d’entrée attendus sont :
pnpm build-icons-css
pnpm build-inter-css
pnpm build-assets
pnpm check-assets
La CSS générée n’est jamais éditée à la main.
La commande canonique avant revue est :
pnpm verify
Elle contrôle le formatage, exécute le lint JavaScript/TypeScript et le typecheck strict sans émission, puis la génération des assets CSS, la génération Panda des feuilles LTR/RTL, les contrôles d’assets et les gates frontend dans Chrome aux largeurs 320 et 1 440 pixels. Le serveur utilisé par ce dernier contrôle écoute uniquement sur une adresse locale et est arrêté après la mesure.
La reproductibilité G9 reste un contrôle séparé : repartir d’un arbre Git propre, exécuter
pnpm verify une seconde fois, puis exiger un git diff --exit-code vide. Ce contrôle
couvre la génération Panda au même titre que les autres sorties (section 6.3).
Les seuils, viewports et allowlists sont versionnés dans tests/fixtures/. Les mesures
Chrome propres à une machine (*.metrics.json) et les rapports détaillés de reports/ sont
des preuves locales régénérées et ignorées par Git : leurs temps bruts ne sont pas bit-à-bit
reproductibles. G9 porte sur les sources et artefacts déterministes suivis, tandis que G13
réévalue les budgets à chaque exécution.
Pendant le développement, pnpm watch maintient en parallèle les bundles issus des sources
TypeScript et la CSS compilée depuis les sources de styles, Less ou Panda selon l’avancement
du port. Le watcher ne remplace jamais pnpm verify : il privilégie la vitesse, ne minifie
pas le runtime et ne lance pas les gates navigateur.
pnpm check-compat exécute la matrice de compatibilité contre la référence de parité
D-012 :
- C0/C1 —
build/fork/compat-snapshot.jscapture un snapshot structurel (balises, classes triées, attributs normalisés, ARIA, texte direct) de chaque page du cataloguetests/en LTR et RTL après boot, et le compare aux fixtures detests/fixtures/compat/. Les valeurs volatiles (ids générés, pixels de styles en ligne, horodatages, compteurs de lecteurs vidéo) sont neutralisées ; les images distantes ne sont pas attendues hors ligne. - C2 —
build/fork/compat-scenarios.jsrejoue les scénarios d'interaction typés detests/js/compat/scenarios/(clic, clavier, focus, ARIA, destruction sans résidu), chaque scénario partant d'une page rechargée. - C3 —
build/fork/compat-api.jsinstancie et détruit programmatiquement chaque composant du registre public et vérifie l'expando__drake__. - Sans runtime —
build/fork/compat-noruntime.jsrecharge chaque page avec le JavaScript désactivé et compare les attentes du HTML initial (titres, liens avechref, texte, alternatives, contrôles natifs) àtests/fixtures/compat/no-runtime.json; la lecture humaine par composant vit dansdocs/fork/NO_RUNTIME.md.
pnpm audit-heritage (hors gate) inventorie la dette mobile-first/SEO héritée du
catalogue à 320 px (tests/fixtures/heritage-audit.json) ; une correction de dette est un
changement ordinaire qui met à jour l'inventaire.
Les fixtures de tests/fixtures/compat/ ont été capturées depuis la référence de parité
(fork/main antérieur à D-012) via un worktree Git, la table de renommage étant appliquée
aux traces (--write --map --root <worktree>). Une recapture n'est légitime qu'après une
divergence décidée (nouvelle décision ou correction acceptée) et se fait alors depuis
le dernier état vert de fork/main, jamais pour faire taire un écart inexpliqué.
Les pages de tests/ constituent le catalogue historique, renommé selon D-012. Elles doivent
être validées au minimum dans les modes suivants pour une release candidate :
| Axe | Cas minimaux |
|---|---|
| Direction | LTR et RTL |
| Entrée | souris, clavier et tactile lorsque pertinent |
| Cycle DOM | présent au chargement, ajouté, retiré, reconnecté |
| API | attribut drk-*, initialisation programmatique Drake, destruction |
| Accessibilité | focus, nom, rôle, état, ordre clavier |
| Responsive | petit et grand viewport, resize |
| Assets | icône courante, brand-* Outline, roman, italic |
| Sans runtime | HTML, contenu, liens, navigation et replis natifs |
| Mobile-first | reflow 320 px, zoom 400 %, cibles et enrichissements min-width |
| SEO | metadata, canonical, robots, statuts, href, titres, images et données structurées |
| Performance | LCP, CLS, proxy INP en laboratoire et données terrain disponibles |
La comparaison visuelle ne remplace pas les assertions de comportement et d’accessibilité.
| Gate | Commande ou preuve | Bloquant pour |
|---|---|---|
| G0 — Périmètre | git status et diff relu |
toute contribution |
| G1 — Dépendances | pnpm install --frozen-lockfile sous Node.js 24.18.0 |
build et release |
| G2 — Lint | pnpm exec eslint . |
code et scripts |
| G3 — Types | pnpm typecheck : tsc --noEmit + test de consommation des déclarations (tests/types/) |
runtime TypeScript |
| G4 — Build | pnpm compile : drake.css, drake.min.css, drake.js, drake.min.js, dist/types/ |
code, styles et release |
| G5 — RTL | pnpm compile-rtl : drake-rtl.css, drake-rtl.min.css |
styles, composants et release |
| G6 — Assets | pnpm build-assets puis pnpm check-assets : drake-tabler-icons.css, drake-inter.css |
assets, packaging et release |
| G7 — Compatibilité | pnpm check-compat : snapshots C0/C1 du catalogue (LTR/RTL), scénarios C2, boucle C3 |
runtime et release |
| G8 — Légal | versions, empreintes et notices contrôlées | assets et release |
| G9 — Reproductibilité | second build, génération Panda comprise, puis git diff --exit-code |
release |
| G10 — Sources frontend | audit automatisé : TypeScript source uniquement, JavaScript navigateur seulement dans dist/ |
runtime et release |
| G11 — HTML et SEO | HTML HTTP/prérendu, sans runtime, statuts, liens, métadonnées et données structurées | composants, exemples et release |
| G12 — Mobile-first | reflow 320 px/400 %, cibles, LTR/RTL et parité mobile/bureau | styles, composants et release |
| G13 — Performance | comparaison LCP/CLS/TBT laboratoire et revue LCP/INP/CLS terrain disponible | composants et release |
| G14 — Icônes héritées | aucun registre SVG JS ; toutes les icônes livrées résolues vers Tabler CSS .drk-ti |
assets, composants et release |
| G15 — Parité Panda | introduit par D-013 : diff CSS normalisé vert pour tout composant porté (section 6.2) | styles, port Panda et release |
Un changement documentaire seul exécute G0 et une revue de cohérence. Il n’a pas à régénérer les artefacts s’il ne modifie aucune règle consommée par un générateur.
Une modification est terminée lorsque :
- son besoin et son périmètre sont explicites ;
- sa source canonique, et non sa sortie, a été modifiée ;
- elle possède les tests proportionnés au risque ;
- tous les gates applicables sont verts ;
- les sorties sont déterministes ;
- la parité C0 à C3 avec la référence D-012 est préservée ou la divergence est acceptée et documentée ;
- le HTML initial reste complet, indexable et utilisable sans runtime ;
- le reflow mobile-first, le SEO technique et les budgets de performance applicables sont démontrés ;
- aucun nouveau mixin Less ou SCSS n’est introduit et tout composant porté vers Panda présente un diff CSS normalisé vert (G15) ;
- les licences sont intactes ;
- aucun commentaire
TODOnon suivi ni contournement de type n’est ajouté ; - le compte rendu permet à une autre personne de reproduire la validation.
Les scripts de publication de l’amont sont volontairement absents : aucun automatisme local
ne doit pousser vers le dépôt du projet amont (voir FORK.md) ni créer une release GitHub.
Le manifeste npm porte le nom drake.css, le titre « Drake.css framework » et la version
propre au fork 0.1.0 ; la base amont est conservée en métadonnée de provenance. Tant qu’un
dépôt distant et une autorité de publication propres au fork n’ont pas été décidés, le
manifeste reste private: true et la préparation s’arrête à un paquet local audité.
Une release candidate exige en plus :
- checkout propre depuis
fork/main; - installation gelée sous la chaîne officielle ;
- suite complète des gates G1 à G14, plus G15 pour tout composant déjà porté vers Panda.css (D-013) ;
- validation du catalogue historique LTR et RTL ;
- inventaire de
dist/sans*.svgTabler,*.woffni*.woff2; - vérification des 5 112 icônes Outline, des deux faces Inter et de l’absence de registre SVG JavaScript ;
- audit sans source JavaScript navigateur hors
dist/; - audit sans résurgence du préfixe hérité
uk-ni des noms amont dans les sources, tests etdist/(audit d’identité G10 automatisé) ; - validation sans runtime, à 320 pixels CSS, des signaux SEO et du budget de performance ;
- notes de migration pour toute divergence ;
- version propre au fork, distincte de tout tag amont ;
- tag annoté et immuable après acceptation.
Une release finale exige en outre l’achèvement du port Panda.css : plus aucun mixin Less ni
source Less/SCSS résiduelle, panda.config.ts et les modules de styles TypeScript étant
alors l’unique source canonique des styles (section 6).