Aller au contenu principal
divagations - Retour à l'accueil

La continuité de l'espace-temps est en péril !

Guillaume Barbier

Temps de lecture : ~ 5 minutes

Alors que je travaillais sur mon projet depuis une nouvelle machine, j'ai réalisé un souci bien embêtant : Mes articles étaient dans le désordres avec des dates qui ne correspondaient pas !

L'espace-temps de mon journal était rompu !

Explication de l'incident

Passé le temps de la stupeur, il a fallu que je me rende à l'évidence : j'avais été laxiste dans ma gestion des dates.

En effet, je m'étais permis de me reposer sur la gestion par défaut des dates d'eleventy (qui se base sur la date de création du fichier), en ajoutant juste une méthode pour pouvoir corriger à la main dans certains cas[1] :

// Dans _data/eleventyComputed.js
export default {
  date: (data) => data.date || data.page.date
}

Tant que je restais sur le même ordinateur, pas de soucis, mes articles s'affichaient dans l'ordre chronologique en se basant sur leur date de création ou celle que j'avais défini manuellement.

C'est quand j'ai repris le travail sur une autre machine que mon journal a perdu les pédales : sur cette machine, tous les fichiers étaient nouveaux, avec la même date de création, celle du téléchargement du projet !

Comment sauver l'espace-temps quand on est flemmard ?

J'aurais pû simplement repasser sur tous mes articles pour définir à la main les dates, mais il faut savoir deux choses :

  • Je suis un peu psychorigide : Pour m'assurer que mes entrées apparaissent dans mon dossier source dans le même ordre que sur le blog, je les ai nommés selon un motif strict :
    <date d'écriture au format "yyyymmdd">-<thème de l'entrée>.md
    Exemple : 20251227-journal-dates.md
  • Je suis fainéant : Je n'ai pas envie de saisir systématiquement deux fois la date de mes articles (une fois dans le titre et une fois dans le front matter)

J'ai donc décidé de réécrire ma propriété calculée pour récupérer la date du nom de fichier (quand disponible).

Pas de grosse difficulté ici, un peu de regex et c'est parti :

export default {
  date: (data) => {
    // If a date is manually set, return it
    if (data.date) return data.date
    // check for date in the filename and if found, return it
    let fileNameDateComposite = /^(\d{4})(\d{2})(\d{2})/.exec(data.page.fileSlug)
    if(fileNameDateComposite) return fileNameDateComposite.slice(1).join('-')
    // And if nothing is found, then OK, use the default page.date, even if it isn't reliable
    return data.page.date
  }
}

Jusque là tout va bien, j'ai même pris le temps d'ajouter une petite alerte dans la console (que je n'ai pas incluse dans l'extrait de code précédent) pour alerter si un article n'a pas de dates explicites et fiable (mais uniquement les articles)

L'espace-temps réduit à l'état de bouillie

Mais quand je teste ma correction, tout s'effondre ! Toutes mes dates sont remplacées par cet affreux message : Invalid DateTime.

En essayant de corriger les dates de mes articles, je les ai complètement annihilées  !!

S'en est suivi une longue et douloureuse recherche, qui a tout de même aboutie sur une série de réponses :

  • Les propriétés date et page.date d'eleventy ne se contentent pas de transmettre une bête chaîne de caractère formatée comme une date (même si c'est bien exactement ce que l'on saisi dans le front matter : une bête chaîne de caractère)
  • Ce sont des objets Date(S'ouvre dans un nouvelle fenêtre)
  • Je ne peux pas simplement générer un de ces objets à partir des méthodes des objets Date : je n'ai pas d'autre choix que d'utiliser la bibliothèque Luxon(S'ouvre dans un nouvelle fenêtre) pour :
    1. D'abord, convertir mon texte en Datetime (Objet date de Luxon)
    2. puis convertir cet objet en Date javascript

La solution

Voici le code avec lequel j'ai finalement réussi à renvoyer une date valide (et sauver l'espace-temps de mon journal) :

import { DateTime } from "luxon";

export default {
  date: (data) => {
    // If a date is manually set, return it
    if (data.date) return data.date
    // check for date in the filename and if found, return it
    let fileNameDateComposite = /^(\d{4})(\d{2})(\d{2})/.exec(data.page.fileSlug)
    if(fileNameDateComposite) {
      return DateTime.fromFormat( 
        fileNameDateComposite.slice(1).join('-'), 
        "yyyy-LL-dd", 
        {zone: "Europe/Paris"}
      ).toJSDate()
    }
    // And if nothing is found, then OK, use the default page.date, even if it isn't reliable
    return data.page.date
  }
}

La piste que je n'ai pas exploré : Git à la rescousse

La doc des dates dans eleventy(S'ouvre dans un nouvelle fenêtre) mentionne qu'il est possible d'utiliser la date du premier commit du fichier pour le dater, en saisissant, à la place d'une date, le texte git Created.

Attention !

Attention ! Git fait chauffer votre ordi

La doc stipule que cette commande est particulièrement intensive. C'est un peu pour ça que je n'ai pas exploré cette option.

Au cas où j'ai tout de même trouvé comment accéder à cette commande depuis les propriétés calculées (car, oui, à cet endroit git Created ne fera pas grand chose). Dans une conversation sur un usage avancé des dates Duong Tam Kien explique comment accéder à cette commande(S'ouvre dans un nouvelle fenêtre) :

import { getCreatedTimestamp, getUpdatedTimestamp } from "../_11ty/git.js";

async function getGitTimestamp(fn, inputPath) {
  const gitDate = await fn(inputPath);
  return !isNaN(gitDate) ? new Date(gitDate) : new Date();
}

export default {
  created: async (data) => getGitTimestamp(getCreatedTimestamp, data.page.inputPath),
  updated: async (data) => getGitTimestamp(getUpdatedTimestamp, data.page.inputPath),
};

L'espace-temps est encore fragile

Je remarque encore des anomalies. Par exemple, j'ai l'impression que les dates que je défini manuellement dans le front matter ne sont pas prise en compte pour définir l'ordre des entrées du journal. Il va falloir que je me penche dessus, mais je pense que cela nécessitera un peu de refactorisation sur les pages "journal" et "articles", voir la création d'une collection personnalisée(S'ouvre dans un nouvelle fenêtre)


  1. Exemple : Un article un peu long écrit sur plusieurs jours. Dans ce cas-là, je préfère que la date de publication soit la date à laquelle je l'ai terminé et pas celle du début de mon écriture. ↩︎