La rédaction de billets sur ce blog m'a récemment amené à vouloir faire
un lien vers non pas une page entière, mais seulement vers un paragraphe
précis, pour éviter d'avoir soit à citer le paragraphe, soit à le
résumer, en laissant à la charge du lecteur d'aller retrouver l'endroit précis.
Je viens d'implémenter une solution assez légère que je détaille ci-dessous.
Lorsque l'on publie un document papier par l'intermédiaire d'un circuit d'édition,
"classique" ou disons normalisé (article, livre, ...), celui-ci a déjà une
référence, et chaque bloc de texte peut être référencé
par sa section, son numéro de page, de ligne, etc. Le travail d'édition
fournit donc déjà un moyen de référence ultérieure, et ce sans que l'auteur
ne s'en occupe. De plus, cette référence ne change à priori pas après la publication.
Cela n'existe que partiellement lorsqu'on publie par exemple
sur un blog, ou chaque billet a automatiquement une url mais pas chaque sous-partie
du texte. De plus, il est possible que le document en ligne change après la
première publication, rendant caducs les types de références usuelles
pour les documents papier. Le moyen que je vais d'exposer permet à nouveau
cette facilité, avec une granularité que j'espère suffisamment fine.
HTML permet déjà d'identifier un bloc à l'aide de l'attribut id.
Cependant, lorsque je rédige du texte, je n'ajoute pas
un identifiant à chaque paragraphe ou bloc ou même chaque mot que je tape.
Du coup, il n'est pas possible d'y faire référence directement par des
liens de la forme
Le problème est qu'il est impossible de générer des identifiants pour toutes les
possibilités de citation d'une partie d'un texte.
Cependant, beaucoup de textes sont structurés en blocs, notamment des paragraphes
(mais aussi exemples de codes, ...). L'idée est donc d'ajouter automatiquement
des identifiants aux balises <p>, <pre>, ...
bref toutes celles qui délimitent des blocs qu'il peut être intéressant de
référencer directement.
Pour ce blog, j'utilise Stog, qui
fonctionne par des règles de réécriture du XML. Concrètement, j'écris les pages
et articles en HTML5 et un moteur passe dessus pour réécrire certaines balises,
par exemple changer les <section> en <div class="section">, ...
J'utilise également le greffon Stog-writing
permettant la génération de tables des matières et de notes de bas de page.
Il m'a donc suffit d'ajouter une nouvelle règle de réécriture pour les balises
<p> pour leur ajouter, lorsqu'il n'y en a pas, un attribut
id dont le contenu est forgé en prenant les premiers caractères
du paragraphe en question. Une mémoire permet de prendre en compte davantage
de caractères si l'identiant forgé existe déjà (par exemple si un autre
paragraphe commence par les mêmes mots).
On obtient donc maintenant des paragraphes référençables depuis d'autres pages
ou même depuis la même page. Pour que le lecteur puisse facilement voir et
surtout utiliser le lien direct, la règle de réécriture ajoute également à la
fin du paragraphe un lien vers justement ce paragraphe.
Concrètement, pour le XML original suivant:
![](https://www.oranadoz.net/paragraph-url.png)
<p id="Portezcevieu">Portez ce vieux whisky au juge blond qui fume. <a class="paragraph-url" href="#Portezcevieu"><img src="http://....paragraph-url.png"/></a> </p>
Pour ne pas encombrer la page avec tous ces liens supplémentaires, un peu
de code dans la feuille de style permet de ne les faire apparaître que lorsque
le curseur de la souris est au-dessus du paragraphe. Essayez et vous devriez voir
une petite image en bas à droite du paragraphe. En cliquant dessus, vous découvrez
le lien direct vers le paragraphe.
Enfin, la feuille de style indique aussi de mettre en évidence le paragraphe
référencé directement par son identifiant. Ainsi, le lecteur
voit directement le paragraphe référencé lorsqu'il suit le lien.
Extrait de la feuille de style correspondant:
![](https://www.oranadoz.net/paragraph-url.png)
a.paragraph-url { float: right ; display:none; } p:hover a.paragraph-url { display: block ; } p:target { .rounded-box () ; background-color: #dddddd; border-width: 1px; border-style: solid; border-color: red ; }
Avantage de cette méthode: Elle est transparente et je n'ai pas à reprendre
mes anciens billets pour ajouter cette possibilité de référencement.
Comme cette méthode fonctionne bien pour les paragraphes, je l'ai également
appliquée pour les blocs <pre>.
Cette méthode est tout de même quelque peu fragile. En effet, il suffit de changer
les premières lettres d'un paragraphe pour que son identifiant change, cassant
ainsi les références vers ce paragraphe.
Un fois le billet publié, il faut donc faire attention, en cas de modification
d'un paragraphe impactant potentiellement son identifiant, à définir explicitement
cet identifiant, qui sera alors utilisé au lieu de l'identifiant automatique
forgé à partir du contenu du paragraphe.
D'autre part, un identifiant doit être unique par page, mais il peut y avoir
plusieurs paragraphes partageant un même identifiant, si ces paragraphes sont
chacun dans des pages séparées. Pour ne pas qu'un conflit d'identifiant apparaisse,
impliquant un identifiant plus long, il ne faut pas que le calcul
des identifiants d'une page dépende des identifiants d'une autre page.
On voudra donc explicitement "remettre à zero" la mémoire des identifiants
connus, pour chaque page.
Pour cela, j'introduis donc une nouvelle règle de réécriture à partir de la
balise <automatic-ids>, remettant à zéro la mémoire
des identifiants et retournant les sous-arbres, de façon à ce que cette balise
ne soit réécrite qu'une seule fois et donc que la réinitialisation n'ait lieu
qu'une seule fois par page, si cette balise est présente une fois par page,
au début.
Une fois la possibilité de référencer des blocs, une multitude de choses deviennent possibles.
Rien qui n'était impossible auparavant, mais pour l'instant la plupart des textes
ne comportent pas de possibilité d'en référencer des paragraphes, tout simplement
car personne ne met un identifiant à chaque paragraphe.
Je ne sais pas si Google le gère avec la recherche "link:", mais il devient
possible de savoir quelles pages référencent un bloc précis d'un texte.
Il devient également possible facilement de gérer des annotations associées
à des parties de texte. Et même d'avoir une application dans son navigateur
affichant ses annotations personnelles en face des paragraphes annotés, lorsqu'on
revient sur une page.
La solution exposée est relativement simple et convient à mes besoins.
Une solution similaire serait applicable à un système de revue scientifique en ligne.
La possibilité d'identifier chaque paragraphe offrant alors la possibilité
pour les pairs d'ajouter des commentaires liés aux paragraphes, voire de rédiger
des articles avec des liens directs vers certaines parties d'autres articles.
On pourrait même aller plus loin, en étendant les possibilités de l'attribut
rel
de la balise <a> pour permettre d'indiquer si on fait un
lien vers un paragraphe pour le réfuter, pour l'approuver ou juste pour s'appuyer
dessus. On pourrait y voir une représentation navigable de discussion scientifique
argumentée.
Encore plus loin, chaque revue pourrait fournir le graphe sémantique
des relations entre les paragraphes, formules et autres blocs des différents articles.
L'aggrégation de ces graphes permettrait des recherches comme "dans quel article
cet argument est-il réfuté ?" ou bien "quelle formule s'appuie sur ce théorème
de cet article ?" C'est ce que j'avais déjà à l'esprit en écrivant
ce paragraphe.