Seed from NAS prod snapshot 20260130-190531
All checks were successful
CI / build-and-anchors (push) Successful in 1m25s
SMOKE / smoke (push) Successful in 11s
CI / build-and-anchors (pull_request) Successful in 1m20s

This commit is contained in:
archicratia
2026-01-31 10:51:38 +00:00
commit 60d88939b0
142 changed files with 33443 additions and 0 deletions

157
docs/anchors.md Normal file
View File

@@ -0,0 +1,157 @@
# Contrat des ancres (paragraphes opposables)
## Source de vérité du sélecteur
Le site garantit la citabilité des paragraphes via des IDs injectés sur les balises `<p>`.
**Sélecteur contractuel :**
- `.reading p[id^="p-"]`
Tout outillage (scripts, tests, docs) doit utiliser ce sélecteur comme référence.
## Ce que le test vérifie
Le test compare, page par page, la liste des IDs de paragraphes présents dans `dist/` contre une baseline versionnée.
- Ajouts dIDs : généralement OK (nouveaux paragraphes).
- Suppressions / churn élevé : alerte (risque de casser des citations existantes).
## Fichier baseline
- `tests/anchors-baseline.json`
## Commandes
1) Générer / mettre à jour la baseline (cas intentionnel) :
- `npm run build`
- `npm run test:anchors:update`
2) Vérifier sans changer la baseline (cas normal) :
- `npm run build`
- `npm run test:anchors`
## Politique déchec (pragmatique)
Le test échoue si le churn dune page dépasse un seuil (défaut : 20%) sur une page “suffisamment grande”.
## Aliases build-time
- `src/anchors/anchor-aliases.json`
- `scripts/inject-anchor-aliases.mjs`
- `scripts/check-anchor-aliases.mjs`
- et rappelle : *alias = compat rétro de liens historiques sans JS*
## Ancres de section (H2) quand on utilise `<details>`
Quand un chapitre est structuré en sections repliables (`<details>`), on utilise une ancre “technique” dédiée pour garantir :
- une cible stable même si le H2 est dans un bloc replié,
- un scroll-offset correct (header + bandeau),
- une détection fiable pour le bandeau “reading-follow”.
Contrat côté HTML rendu :
- présence dun élément de type :
- `<span class="details-anchor" id="..."></span>`
- puis, dans le même `<details>`, un H2 visible dans le body.
Contrat côté CSS :
- `.details-anchor` a `scroll-margin-top: var(--sticky-offset)`.
Contrat côté JS (EditionLayout) :
- `openDetailsIfNeeded(el)` ouvre le `<details>` parent si nécessaire avant de scroller.
## Compat “legacy hash” : `#p-<idx>-<hash>`
Un hotfix de compat existe pour les anciennes ancres de paragraphes au format :
- `#p-<index>-<8 hex>`
Si lID exact nexiste plus :
- on cherche le premier élément dont lid commence par `p-<index>-`
- puis scroll avec offset.
But : éviter les “liens morts” historiques quand une régénération dIDs a eu lieu.
Limite : cest un fallback de dernier recours (moins déterministe quun alias explicite).
Le mécanisme recommandé reste : `docs/anchor-aliases.json` + injection au build.
_______________________________________
Dernière mise à jour : 2026-01-29
Ce document formalise comment on évite de casser les liens profonds (URLs avec `#ancre`).
---
## 1) Principe
Les IDs dancres générés (ou dérivés) peuvent changer :
- réécriture
- insertion/suppression de paragraphes
- re-slug dun titre
➡️ Donc : on ne “devine” pas un fallback par index en runtime.
➡️ On fait un aliasing **déterministe à la build**, versionné.
---
## 2) Le mapping dalias
- Fichier versionné (ex) : `docs/anchor-aliases.json`
- Format : `oldId -> newId` par page
Ex en json :
{
"/archicratie/archicrat-ia/chapitre-4/": {
"p-8-ancien": "p-8-nouveau"
}
}
## 3) Injection à la build (dans dist)
Script : scripts/inject-anchor-aliases.mjs
Moment : postbuild (après astro build, avant pagefind)
Ce script injecte dans dist/**/index.html un <span id="oldId"></span> juste avant lélément portant id="newId".
## 4) Contrôles (incassables)
### A) Vérifier quon na pas dIDs dupliqués en HTML
Script : scripts/audit-dist.mjs
Robustesse :
ignore <script> et <style> (évite faux positifs)
exige un espace avant id= (évite data-id=)
Exécution :
npm run audit:dist
### B) Vérifier que les aliases sont vraiment présents dans dist
Script : scripts/verify-anchor-aliases-in-dist.mjs
Exécuté dans npm test
## 5) Mise à jour assistée (si besoin)
Pour générer/mettre à jour des aliases à partir des deltas dancres :
npm run test:anchors:update
## 6) ⚠️ Artefacts macOS (PaxHeader / ._ / DS_Store)
Quand on transfère une archive depuis macOS, on peut importer des dossiers/fichiers parasites :
PaxHeader/
._*
.DS_Store
Ces artefacts peuvent polluer le build (Astro croit voir un “vrai” contenu MDX).
➡️ Recommandation : .dockerignore strict :
# macOS / archives
.DS_Store
._*
**/._*
PaxHeader
**/PaxHeader
# Node
node_modules
dist
# (Optionnel) Avant build sur NAS : supprimer ces dossiers si présents.