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
en utilisant l'identifiant id.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:
<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:
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.