Files
archicratie-edition/docs/anchors.md
Archicratia b78eb4fc7b
All checks were successful
CI / build-and-anchors (push) Successful in 1m52s
SMOKE / smoke (push) Successful in 11s
docs: normalisation md + diagnostics dedup + LEGACY strict
2026-02-02 12:08:53 +01:00

4.5 KiB
Raw Blame History

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
  1. 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 : src/anchors/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) : src/anchors/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 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.