Contribuer
August 22, 2026 · View on GitHub
Démarrer
npm install
npm run build
npm test
npm run typecheck # typage strict, tests inclus
npm run verify:bridge # preuve bout en bout à travers un vrai build Angular AOT
L'application de test vit dans apps/fixture-app. Elle est délibérément
inaccessible : chaque violation y sert de cas de test. Si vous la modifiez,
vérifiez que npm run verify:bridge passe toujours.
Essayer l'outil en local
Trois niveaux, du plus rapide au plus fidèle.
1. Sans rien installer — pour itérer pendant le développement :
npm run build
node packages/cli/dist/index.js check --project /chemin/vers/mon-app --no-fail
2. Comme une vraie commande — pour l'usage quotidien :
npm run build
npm link --workspace @rgaa-source/cli
rgaa-source check --project . --no-fail # depuis n'importe quel dossier
npm unlink -g @rgaa-source/cli pour retirer le lien. Attention : un lien
résout les dépendances à travers l'espace de travail, donc il masque un
files incomplet ou une dépendance oubliée. Il ne remplace pas le niveau 3.
3. Répétition générale sur un registre local — la seule qui prouve que la publication elle-même fonctionne. À refaire avant chaque version.
npm install -g verdaccio
verdaccio --listen 4873 &
Créer un compte sans invite interactive, et écrire un .npmrc local au dépôt
(il contient un jeton ; il est dans le .gitignore, ne le committez jamais) :
TOKEN=$(curl -s -XPUT -H "Content-Type: application/json" \
-d '{"name":"local","password":"local-test-only","email":"local@example.test","type":"user","roles":[],"date":"2026-01-01T00:00:00.000Z"}' \
http://localhost:4873/-/user/org.couchdb.user:local | node -pe "JSON.parse(require('fs').readFileSync(0)).token")
printf '@rgaa-source:registry=http://localhost:4873/\n//localhost:4873/:_authToken=%s\n' "$TOKEN" > .npmrc
Publier dans l'ordre des dépendances — chaque paquet dépend des précédents, et npm refuse une dépendance vers une version absente du registre :
npm run build
for p in core angular fix report cli; do
(cd packages/$p && npm publish --registry http://localhost:4873/)
done
Puis, dans un dossier de test vierge, installer comme un vrai utilisateur :
pas de file:, pas d'overrides, npm résout tout seul.
npm init -y
printf '@rgaa-source:registry=http://localhost:4873/\n' > .npmrc
npm install @rgaa-source/cli
npx rgaa-source check --project /chemin/vers/mon-app --no-fail
Ce niveau vérifie ce que les deux autres masquent : que files embarque bien
rules.bundle.js, que le binaire démarre avec son shebang, que Playwright et
axe-core s'installent chez le consommateur, et que les plages de versions entre
paquets se résolvent réellement.
Pour arrêter le registre, il écoute en IPv6 — netstat -ano | grep 4873 puis
taskkill /F /PID <pid> sous Windows.
Ajouter une option
Une option est trois choses : une entrée dans parseArgs (sans default,
voir plus bas), une clé dans Config avec son validateur, et une ligne dans le
texte d'aide.
Aucune option booléenne ne déclare de valeur par défaut au parseur : avec une,
un drapeau absent et un drapeau explicitement à faux sont indiscernables, et le
fichier de configuration ne pourrait jamais être surchargé dans les deux sens.
Absent vaut undefined, et pick(drapeau, fichier, défaut) tranche.
Ajouter une règle
Une règle est un fichier dans packages/core/src/rules/ et une ligne dans
registry.ts. Le scanner n'est jamais touché.
export const maRegle: AccessibilityRule = {
id: 'rgaa-ma-regle',
severity: 'moderate',
wcag: ['1.3.1'],
rgaa: ['9.3'], // déclaré, jamais déduit
message: '…',
help: '…', // pourquoi ça compte, pour un développeur non-expert
recommendation: '…', // quoi faire
run({ document }) {
const candidats = [...document.querySelectorAll('…')];
return { candidates: candidats.length, findings: [] };
},
};
Quatre points à respecter :
candidatesest le dénominateur du score. Une page sans tableau ne doit être ni récompensée ni pénalisée par une règle sur les tableaux. Renvoyez0quand la règle n'a rien à examiner.- N'ajoutez pas ce qu'axe fait déjà bien. Dupliquer une règle existante n'ajoute que des occasions d'être en désaccord avec elle.
review: truepour ce qui ne peut être que signalé à un humain. Ces règles ne produisent pas d'échecs et n'entrent pas dans le score.- Transmettez ce que vous détectez via
data, pour qu'un correcteur agisse sur la valeur plutôt que de ré-analyser une phrase.
Les règles tournent dans la page : uniquement des API navigateur, rien de Node.
Elles sont empaquetées par scripts/bundle-rules.mjs.
Tests : packages/core/src/rules/rules.test.ts, en environnement happy-dom.
Toute règle doit avoir un cas qui la déclenche et un cas qui ne la déclenche
pas — une règle qui tire sur une page saine tirera partout.
Ajouter un correcteur
Un correcteur est une entrée dans packages/fix/src/fixers.ts. Le niveau
safe est réservé à ce qui est correct sans rien savoir du sens de la page.
Tout ce qui consiste à écrire un texte descriptif est suggested : une
alternative fausse est pire que l'attribut manquant, parce que le lecteur
d'écran la croit.
Principes non négociables
Ces quatre points ont chacun été payés par un bug ou une mauvaise décision rattrapée. Les remettre en cause demande un argument, pas une préférence.
-
Exact ou absent, jamais deviné. Un développeur envoyé à la mauvaise ligne perd plus de temps qu'un développeur envoyé nulle part. Les localisations viennent d'un attribut posé au build, jamais d'une correspondance approchée.
-
Ne jamais déclarer un critère conforme. Un contrôle automatique couvre une fraction des tests d'un critère. La grille n'émet que
NCetNT. -
Ne jamais laisser un arbre de travail modifié. Les templates sont réécrits en place ; l'original est déposé sur disque avant, et restauré dans un
finally. Un garde-fou qui se déclenche à tort finit désactivé — d'où la récupération automatique plutôt qu'un refus de tourner. -
Dire ce qui n'a pas été vérifié. Chaque rapport affiche les critères sur lesquels il ne s'est pas prononcé. C'est ce qui empêche le score d'être lu comme un taux de conformité.
Publier une version
Les métadonnées des cinq paquets — version, dépôt, licence, mots-clés,
publishConfig — se régénèrent depuis une seule source, pour qu'elles ne
divergent jamais :
npm run build:packages
Avant de publier, la répétition générale sur registre local décrite plus haut. Puis :
npm login
npm run build && npm test && npm run typecheck
npm publish --workspace @rgaa-source/core --access public
npm publish --workspace @rgaa-source/angular --access public
npm publish --workspace @rgaa-source/fix --access public
npm publish --workspace @rgaa-source/report --access public
npm publish --workspace @rgaa-source/cli --access public
L'ordre compte : chaque paquet dépend des précédents, et npm refuse une
dépendance vers une version absente du registre. Le --access public est déjà
dans publishConfig, mais le répéter évite d'avoir à diagnostiquer l'échec —
un scope npm publie en privé par défaut, et l'erreur ressemble à un problème de
facturation plutôt qu'à un problème de permission.
Le référentiel RGAA
packages/core/src/mapping/rgaa-criteria.generated.ts est généré. Ne
l'éditez pas : lancez npm run build:rgaa, qui le reconstruit depuis la source
officielle DINUM et échoue s'il ne retrouve pas exactement 106 critères sur
13 thématiques. Relisez le diff — un changement ici change ce que tout audit cite.
Le mapping règle → critères dans rgaa.ts se justifie contre l'intitulé
officiel du critère, pas de mémoire. Un test vérifie qu'aucune règle ne cite un
critère absent du référentiel.