igor.milhit/content/blog/les-dates-avec-hugo.md

162 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

---
title: "Les dates avec hugo"
date: 2019-08-25T13:11:00+02:00
publishdate: 2019-08-26
draft: false
categories: ["publication numérique"]
tags: ["hugo", "dates", "configuration"]
slug: les-dates-avec-hugo
---
*[Mis à jour à la fin du billet](#mise-à-jour).
[Une deuxième fois](#une-mise-à-jour-supplémentaire).*
Ces derniers jours, je me suis un peu cassé la tête avec la manière dont
[*hugo*](https://gohugo.io/) conçoit et traite les dates. Ce que je cherchais à
réaliser ne me semblait pourtant pas si exotique. Lorsque l'on crée un nouveau
contenu, par exemple un nouveau billet de blog, à l'aide de la commande `hugo
new` (et en utilisant l'`archetype` par défaut), *hugo* ajoute dans les
métadonnées (le *FrontMatter*) une valeur au champ date. Ce qui donne pour le
fichier du texte que je rédige à l'instant: `date: 2019-08-25T13:11:00+02:00`.
Dans le *template* qui permet d'afficher la date du billet de blog une fois le
site généré, on peut trouver du HTML simplissime:
```
<li>Publié le&#x202F;: {{ .date.Format "2006-01-02" }}</li>
```
Jusqu'ici, tout va bien. Pourtant, le plus souvent cette date ne correspond pas
à la date effective de publication du billet, parce qu'entre le moment où je
crée le fichier et le moment où il est suffisamment prêt pour être publié, il
peut se passer plusieurs jours. Ça tombe bien, *hugo* propose une autre
variable à ajouter, manuellement, dans les métadonnées, `publishdate`. Enfin,
il peut également arriver qu'après la publication, il soit nécessaire de
modifier un billet. Là aussi, il existe une variable, `lastmod`. Celle-ci
peut-être ajoutée à la main ou renseignée par la date du dernier
[*commit*](https://fr.wikipedia.org/wiki/Commit) de modification du fichier, si
`enableGitInfo` est activé dans le fichier de configuration du site.
Tout va bien dans le meilleur des mondes? Presque. Assez logiquement, je
trouve, je voulais afficher d'abord une date de publication, par exemple `date`
ou `publishdate` si cette dernière date existe, et, le cas échéant, la date de
la dernière modification. Ce faisant, j'ai été confronté à deux difficultés. La
première était que toutes mes méthodes de tests logiques (si `publishdate`
existe, alors affiche cette date, sinon affiche `date`, par exemple),
provoquaient des erreurs lors de la génération du site. Pour avancer quand
même, chaotiquement comme c'est mon habitude, j'ai fait abstraction des tests
et tenter d'afficher toutes les dates.
D'abord, j'ai été surpris de constater que si l'une d'elle n'existe pas, elle
n'est simplement pas affichée. Il y a là un mécanisme qui m'échappe, mais
pourquoi pas. L'autre point déroutant, est que les valeurs des dates affichées
ne correspondaient pas à ce que j'avais imaginé. Souvent, `date` et
`publishdate` étaient identiques, parfois `lastmod` également, parfois
`lastmod` avait bien la valeur du dernier *commit* correspondant à la dernière
modification du billet concerné~~, mais pas lorsqu'il s'agissait du premier
*commit*~~.
J'ai essayé de nombreuses choses, tenté de comprendre la documentation de
*hugo*, fouillé dans les forums… de m'arracher mes cheveux, de jurer et
d'insulter le Web, en vain. Avant de tomber sur une discussion sur le forum de
*hugo* dans laquelle était signalée la section suivante de la documentation:
[*Configure
dates*](https://gohugo.io/getting-started/configuration/#configure-dates). Je
l'ai lue attentivement et j'ai fini par comprendre ce qui se passait, à défaut
de tout à fait comprendre la logique à l'œuvre. Pour obtenir un comportement
qui correspond à ce que je voudrais, il faut que dans le fichier de
configuration de mon site (`config.toml`), je redéfinisse à ma guise la manière
dont les variables de dates sont renseignées.
```
[frontmatter]
date = ["date", "publishDate"]
lastmod = [":git", "lastmod"]
```
Avec cette méthode, j'évite que le champ `date` puisse récupérer la valeur de
`lastmod` et que celui-ci puisse obtenir la valeur de `date` ou `publishdate`.
Du coup, je peux les distinguer, pour avoir une date de publication et/ou une
date de dernière mise à jour. Si la date de publication est différente de la
date de création du fichier, je dois manuellement, soit modifier la valeur de
`date` dans le *FrontMatter*, soit y ajouter la variable `publishdate`.
`lastmod` par contre, peut-être inférée de l'historique `git`, pour autant que
`enableGitInfo` soit bien à `true` dans la configuration.
Au niveau des *template*, ça peut donner ceci:
```
<li>Publié le&#x202F;: {{ dateFormat "2006-01-02" (default .Date (.PublishDate)) }}</li>
{{ if isset .Params "lastmod" }}
<li>Dernière mise à jour&#x202F;: {{ .Lastmod.Format "2006-01-02" }}</li>
{{ end }}
```
Il n'est pas du tout invraisemblable que cette solution puisse être améliorée.
Ce que je retiens de cette aventure, c'est que *hugo* est décidément très
puissant, le résultat d'une réflexion plutôt poussée et que j'ai encore
beaucoup de travail avant d'arriver à un niveau suffisant de compréhension de
son fonctionnement.
## Mise à jour
Visiblement la logique ci-dessus est incomplète (et risque bien de l'être après
cette mise à jour, mais c'est ainsi). Sur ce même billet, lors de la
publication, enfin un peu après, j'ai constaté que la date de modification
était plus récente que la date de publication, ce qui est logique, parce que la
date du commit est plus ancienne que `publishdate`, contrairement à ce que je
prétends plus haut.
{{< figure src="/images/wrong-dates.png"
caption="Première publication, avec la mauvaise date" >}}
Aussi, j'ai rajouté un test dans le *template* :
```
{{ if (and (isset .Params "lastmod") (gt .Lastmod .PublishDate)) }}
```
D'abord, on vérifie que la variable `lastmod` est bien renseignée, puis que sa
date est plus récente que `publishdate`, avant de l'afficher. Voilà, j'espère
que désormais je vais obtenir le comportement que je souhaite.
## Une mise à jour supplémentaire
> «Voilà, j'espère que désormais je vais obtenir le comportement que je
> souhaite. »
Hé bien non. Souvent, la `lastmod` est affichée, alors qu'elle est du même jour
que la `publishdate`, et en fait, c'est logique. Il se trouve que je renseigne
la `publishdate` manuellement, parce que je veux qu'elle soit différente de la
date de création du fichier (le résultat de la commande `hugo new`) et qu'elle
ne soit pas modifiée par les dates des commits qui viendraient après, puisque
ces modifications sont des mises à jour, pas un changement de la date de
publication. Or, je ne m'amuse pas à créer une date de publication à la seconde
près, une date du type `2020-05-22` me suffit.
Par contre, pour la `lastmod`, la date vient de `git`, et là c'est précis, à la
seconde près. Ce qui a pour conséquence qu'une comparaison d'une date de
publication et et la date du dernier commit qui tombent le même jour, donnera
toujours la `lastmod` comme plus grande que la `publishdate`. Mon gabarit va
dont l'afficher.
La solution, évidente pour des gens dont c'est le métier, j'imagine, est de
traiter ces dates pour pouvoir les comparer de manière sensée:
```
{{ $LastmodFormatted := dateFormat "2006-01-02" (.Lastmod) }}
{{ $PublishdateFormatted := dateFormat "2006-01-02" (.PublishDate) }}
```
On compare ces dates formatées et on affiche la dernière modification si elle
est plus récente que le jour de publication:
```
{{ if (and (isset .Params "lastmod") (gt $LastmodFormatted $PublishdateFormatted)) }}
<li>Dernière mise à jour&#x202F;: {{ .Lastmod.Format "2006-01-02" }}</li>
{{ end }}
```
Et si on fait des mises à jour le même jour, ça ne sera pas affiché, mais
peut-être bien que c'est sensé, au fond.