Pour utiliser du CSS spécifique aux entrées du journal, il faut que je puisse les cibler en plaçant une classe spécifique sur la balise <body>. Le problème est que la structure des templates que j'ai implémenté ne me permet pas d'ajouter cette classe :
| Élément des pages "Entrées" | Template responsable | Remarques |
|---|---|---|
<html> |
base.html |
|
<head> |
base.html |
|
<body> |
base.html |
Emplacement voulu pour la classe "log-entry" |
<nav> |
base.html |
Menu |
<h1> |
base.html |
|
<p class="date"> |
log-entry.html |
Date de l'entrée |
| … | log-entry.html |
autres contenus |
<nav> |
log-entry.html |
Navigation entre les entrées |
Pour résoudre ce problème, deux options s'offrent à moi :
- Revoir mes templates pour laisser
log-entry.htmlgérer l'intégralité de la balise<body> - Ajouter dans
base.htmlune méthode pour injecter des classes dans la balise<body>
La première approche est assez lourde à implémenter (il faut retravailler plusieurs templates) et m'obligerait à isoler les parties transverses (comme le menu) et à les réinjecter dans chaque template.
C'est pourquoi j'ai opté pour la seconde, qui est au final assez simple à implémenter, avec une seule contrainte (que j'expliquerai plus tard). Cette approche consiste à ajouter dans la balise <body> une expression Liquid pour afficher une liste de tag (J'utilise le filtre join pour éviter que les classes soient collées) :
<body class="{{ classes | join }}">
Il ne me reste plus qu'à ajouter dans mes templates ou mes documents Markdown les classes que je veux ajouter.
Un seul bémol : si je veux bénéficier de la cascade de données d'eleventy pour accumuler des classes (par exemple en ayant une classe "log-entry" pour toutes les entrées de journal, et une classe spécifique à une entrée particulière), il faut que je déclare toutes mes classes sous la forme d'un tableau (Array en javascript) :
---
layout: base.html
classes: ["log-entry"]
---
Si je le déclare "normalement" (sans les crochets), il écrasera les classes déclarées "plus haut" et se fera lui-même écrasé si des classes sont déclarées "plus bas" (même si elles sont déclarées correctement).
Sécuriser les classes liées au template
Si j'aime la versatilité de ce système, il présente trop de risque de faire sauter des styles. Il faut que je base les accroches principale de mon CSS sur des classes qui ne risquent pas de sauter.
J'ajoute donc dans mon template base.html une nouvelle expression Liquid se basant sur le nom du dernier template appliqué. Le problème, c'est que les noms des layout comportent leur extension, et class="log-entry.html", ça ne fait pas très sérieux. Pour éviter ça, j'ajoute un filtre pour supprimer le .html :
<body class="{{ layout | remove: ".html" }} {{ classes | join }}">
Améliorer la robustesse de mon injection de classe
Je n'ai malheureusement pas trouvé de façon de forcer la donnée personnalisée "classes" à se comporter comme la donnée "tags" (quand on ajoute un tag, peut importe qu'il soit déclarer dans un tableau ou non : il est ajouté à la liste des tags générée par la cascade).
Mais en y réfléchissant, le principal risque d'erreur est probablement lors de la rédaction de documents (les templates sont généralement définis une fois et bougent ensuite peu).
J'ai d'abord tenté l'approche suivante :
- Ajouter dans mes front matter une propriété classes sous forme de liste de valeurs (une array, en javascript)
- Ajouter dans d'autres front matter une propriété class avec des valeurs uniques
- Créer une propriété calculée pour fusionner toutes mes sources en une seule propriété classes
Mon hypothèse était que la propriété calculée allait se recalculer à chaque passe sur un fichier et s'enrichir des propriétés class(lang=en) rencontrées (et ainsi émuler le deep merge qu'Eleventy effectue automatiquement sur les listes de valeurs). Mais comme expliqué dans cette doc avancée, mon hypothèse était fausse et la la propriété calculée n'est calculée qu'une fois, à la fin : Order of Operations(S'ouvre dans un nouvelle fenêtre)
Par conséquent, seule la dernière valeur class est prises en compte.
Pour sécuriser cette information, je n'ai pas d'autres choix que de m'astreindre à toujours ajouter mes classes sous forme de liste (et je peux oublier l'usage de class, qui n'est plus intéressant du tout)
Le système obtenu n'est pas aussi robuste que je le souhaitait, mais au moins je peux maintenant styler mes pages individuellement ou en fonction des templates utilisés.