Eleventy, comment ça marche ?

Gérer des templates, utiliser un plugin de navigation.

Un site statique

J'en avais parlé dans mon premier post, je veux un site statique : de l'HTML, du CSS, c'est tout.

Sauf que quand même, pas question de récrire à la main, à chaque fois, tout l'HTML dont votre navigateur (ou votre lecteur RSS) a besoin pour lire ces lignes. Et donc 11ty m'offre un framework en JavaScript me permettant de générer automatiquement le contenu HTML du site à partir de templates, ainsi que le flux RSS associé à la sortie de mes blogposts.

Ça peut faire un peu peur au début parce qu'il y a un peu de config à faire (notez que comme d'autres générateurs de site comme Jekyll, j'aurais pu simplement utiliser un template de site et y rajouter mon contenu), donc je vais vous expliquer, en gros, ce que j'ai fait.

Le squelette

Le code source de ce site se trouve ici. Il est sous licence GPLv3.0, comme tout ce que je produis. J'ose espérer qu'il est suffisament simple pour qu'un ou une utisatrice avertie puisse comprendre ce qui se passe, au moins dans les grandes lignes.

Les fichiers de template

La base d'un générateur de site, ce sont les modèles. En gros, il s'agit de fichiers HTML comportant des balises spécifiques qui seront remplacées par le contenu adéquat lors de la génération du site. Un modèle (ou template) ressemble à ça :

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="author" content="David JULIEN">
    <meta name="description" content="Le blog d&#39;un doctorant en informatique... Mais on pourrait parler de cuisine, aussi.">
    <meta name="generator" content="Eleventy v3.0.0">
    <link rel="icon" type="image/x-icon" href="/assets/img/favicon.svg">
    <title>Eleventy, comment ça marche ? - David JULIEN</title>

    <!-- CSS -->
    <link rel="stylesheet" href="/css/main.css" />

    <!-- Feed -->
    <link rel="alternate" href="/feed.xml" title="David JULIEN" type="application/atom+xml">
</head>

Ici, les balises {{ metadata.author.name }}, {{ eleventy.generator }} et autres seront remplacées par (David JULIEN et Eleventy v3.0.0, respectivement) les infos contenues dans les différents fichiers de configuration, par exemple _data/metadata.js : ainsi, je peux mettre à jour tout mon site en changeant une seule ligne.

J'ai donc tout d'abord écrit un modèle de base pour les pages du site. Ce fichier mêle deux langages: l'HTML de départ et des balises Nunjucks. Ce sont ces {{ balise }} qui seront interprétées par le générateur de site pour insérer les bonnes infos au bon endroit, comme montré plus haut. En l'occurence, tout l'intérêt ici n'est pas de simplement récupérer la valeur de petites variables (comme mon nom complet) mais bien d'insérer le contenu complet d'un fichier. C'est ce qui se passe dans le fichier base.njk :

<main id="skip">
    <heading-anchors>
        {{ content | safe }}
    </heading-anchors>
</main>

Il ne reste plus qu'à déclarer ce qui constitue ce {{ content }}, et le tour sera joué. Par exemple, ce fichier (index.njk) peut contenir :

{% block content %}
<div class="c-pageintro">
    <div class="l-container">
        <div class="c-pageintro__inner">
            <p class="c-suptitle">Nantes, France.</p>

            <h1>{{ title }}</h1>

            <p class="c-txtintro">
                Je suis doctorant au sein de Nantes Université / Laboratoire
                des Sciences du Numérique de Nantes (LS2N).
                Je travaille sur la vérification de modèles, en particulier
                les modèles différentiels.
            </p>
            <p>
                Ce site a surtout vocation à compiler mes travaux de
                recherches, ainsi qu'à accueillir mon blog.
            </p>
        </div>
    </div>
</div>
{% endblock %}

Il n'y a plus qu'à créer les fichiers des autres pages (contact.njk, blog.njk, etc.) en réutilisant la même syntaxe, et tout sera généré automatiquement.

Enfin, presque. Il faut quand même spécifier quelque part quel template utiliser. Pour cela, on crée un petit fichier pages.11tydata.js dans le répertoire en question, qui contient simplement

export default {
	layout: "layouts/base.njk",
};

Ceci fait, chaque page du répertoire dans lequel se trouve ce fichier utilisera par défaut le template de base dont je parle juste au-dessus. Bien évidemment, l'en-tête d'un fichier aura toujours la priorité, et il est possible de redéfinir ce comportement à la volée en y paramétrant la balise layout.

L'en-tête du fichier ?

Il y a évidemment plusieurs endroits où le générateur de site va chercher des données, le premier étant le fichier de contenu lui-même, dans son en-tête :

---
title: Accueil
permalink: index.html
eleventyNavigation:
    key: Accueil
    order: -1
---

On y spécifie les caractéristiques propres du fichier final, comme son titre, son permalien, etc. Tous ces champs sont facultatifs, mais sont utiles pour forcer un comportement (comme spécifier le fichier de template à utiliser). Enfin, ces champs permettent aussi aux différentes fonctions du générateur de faire leur œuvre.

Ici, le champ composé eleventyNavigation permet, comme son nom l'indique un peu, de spécifier les attributs de ce fichier pour qu'il apparaisse dans la barre de navigation (en haut à droit du site). Cette fonctionnalité est gérée par ce plugin. On peut y spécifier l'ordre, pour une fois de plus forcer un comportement. Il faut au moins spécifier la composante key pour créer l'élément dans la table du plugin. Il s'active dans le fichier de configuration principal eleventy.config.js qui se trouve normalement à la racine du site, comme ceci :

import pluginNavigation from "@11ty/eleventy-navigation";
export default async function (eleventyConfig) {
	eleventyConfig.addPlugin(pluginNavigation);
};

C'est tout, rien besoin de plus !

It's a wrap!

Voilà pour le premier post. Je m'oriente vers des posts assez courts et ciblés sur une ou deux choses en particulier, pour ne pas noyer l'information.

À plus !


EDITS :

  • réparation des liens internes ;
  • renvoi vers une ligne spécifique pour base.njk ;
  • coquilles.