Chaire de recherche du Canada sur les écritures numériques, Bibliothèque des lettres et des sciences humaines, Ouvroir d'histoire de l'art et de muséologie numérique. — roch.delannay@umontreal.ca ; giulia.ferretti@umontreal.ca ; louis-olivier.brassard@umontreal.ca
pandoc
Une page web, c’est un fichier HTML.
On se rappelle, le HTML consiste le plus souvent en des ensembles de paires de balises ouvrantes/fermantes (par ex. <p> </p>
). C’est le langage de documents inventé par Tim Berners-Lee pour le World Wide Web – ce système hypertexte permettant aux chercheurs du monde entier de partager leurs connaissances.
<body>
<h1>Mon titre</h1>
<nav class="table-des-matieres">
<a href="#section-1">Section 1</a>
<a href="#section-2">Section 2</a>
<a href="#section-3">Section 3</a>
</nav>
<p>Contenu de mon document.</p>
</body>
Il est possible de visiter la première page web : http://info.cern.ch/hypertext/WWW/TheProject.html
Ou comprendre l’activité de publication?
Enseigner l’activité de publication et en faire le pivot de l’apprentissage de l’ensemble des savoirs et des connaissances. Avec la même importance et le même soin que l’on prend, dès le cours préparatoire, à enseigner la lecture et l’écriture. […] Comprendre enfin que l’impossibilité de maîtriser un “savoir publier”, sera demain un obstacle et une inégalité aussi clivante que l’est aujourd’hui celle de la non-maîtrise de la lecture et de l’écriture, un nouvel analphabétisme numérique hélas déjà observable. […] comme le rappelait Bernard Stiegler : “la démocratie est toujours liée à un processus de publication – c’est-à-dire de rendu public – qui rend possible un espace public : alphabet, imprimerie, audiovisuel, numérique.”
— Olivier Ertzscheid, 2012, archivé sur affordance.info
Nous pourrions créer une page avec du contenu comme ceci…
<!DOCTYPE html>
...
<p>
Un premier paragraphe.
</p>
<p>
Un deuxième paragraphe, avec un <a href="http://debugue.ecrituresnumeriques.ca">hyperlien</a>.
</p>
...
… mais éditer un fichier HTML à la main, c’est un peu verbeux.
N’y aurait-il pas un autre format de balisage léger qui nous permettrait d’arriver au même résultat?
Créons plutôt un fichier markdown, avec l’extension .md
:
# dans le terminal, créer un fichier vide
touch page.md
Ajoutons un peu de contenu à ce fichier. Ouvrez page.md
pour édition.
# Titre de mon document
Un premier paragraphe.
1. une
#. liste
#. numérotée
#. automatiquement
Essayons une première conversion avec les options par défaut. Pandoc reconnaîtra les formats avec les extensions de fichier (.md
pour le markdown, .html
pour HTML).
pandoc page.md -o page.html
En examinant le contenu de page.html, ne manque-t-il pas quelques balises?
Où sont passées les éléments obligatoires <html>
, <body>
, etc.?
On peut y remédier en spécifiant à Pandoc l’option --standalone
(ou -s
pour faire court).
pandoc --standalone page.md -o page.html
Et voilà, un fichier HTML valide!
Nous pouvons aller un peu plus loin en spécifiant quelques métadonnées à même le fichier :
---
title: Titre de mon document
author: Louis-Olivier Brassard
date: 2023-05-24
---
Relançons la commande et voyons le résultat!
Aperçu de la page HTML dans le navigateur.
Pandoc permet de spécifier des feuilles de style CSS à appliquer à notre document.
Créons un fichier style.css
et ajoutons-lui quelques styles de base.
/* style.css */
/* Couleur de fond et couleur de police pour l’ensemble du document */
html {
background-color: whitesmoke;
color: midnightblue;
}
/* Style des en-têtes */
h1, h2, h3 {
color: deeppink;
font-family: sans-serif;
}
À présent, nous pouvons référencer style.css
dans les métadonnées de notre page :
---
css:
- style.css
---
Relançons la commande Pandoc :
pandoc --standalone page.md -o page.html
Admirez le résultat avec votre feuille de style appliquée!
Aperçu de la page HTML dans le navigateur.
Pour notre projet, créons une série de pages :
touch accueil.md \
page-1.md \
page-2.md \
page-3.md
N’oublions pas d’ajouter quelques métadonnées, comme le titre, le nom de l’auteur et la date.
---
title: Titre de la page
date: 2023-05-24
---
On peut lancer la conversion Pandoc pour chacun de ces documents :
pandoc --standalone accueil.md -o accueil.html
pandoc --standalone page-1.md -o page-1.html
pandoc --standalone page-2.md -o page-2.html
pandoc --standalone page-3.md -o page-3.html
Un peu fastidieux et répétitif… mais ça fonctionne! (Nous y reviendrons plus loin.)
À présent que nous avons plusieurs pages, essayons d’ajouter un menu pour faciliter la navigation entre elles!
Dans l’en-tête du markdown, ajouter la propriété include-before
, qui permet d’ajouter une liste de choses. Ajoutons un élément dans cette liste (désigné par le trait d’union -
) en permettant la saisie sur plusieurs lignes, grâce au caractère |
(pipe) :
include-before:
- |
<nav class="menu">
<a href="accueil.html" class="courante">Accueil</a>
<a href="page-1.html">Page #1</a>
<a href="page-2.html">Page #2</a>
<a href="page-3.html">Page #3</a>
</nav>
Puisqu’il s’agit d’un site, nous pouvons ajouter du contenu HTML à la fin du document (propriété include-after
) pour les crédits et les droits d’utilisation par exemple :
include-after:
- |
<footer>
<hr>
© 2023 – Tous droits réservés.
</footer>
Aperçu d’une page avec un menu.
Enfin, nous pouvons faire appel à une feuille de style externe, à tout hasard almond.css pour rendre notre document plus joli.
css:
- https://unpkg.com/almond.css@latest/dist/almond.lite.min.css
- style.css
C’est un peu répétitif d’indiquer les mêmes variables dans plusieurs fichiers… par exemple, si nous souhaitons changer le pied de page de 2022 pour 2023, il faudrait le faire à la main dans chaque page! (page-1.html
, page-2.html
, page-3.html
, …)
À moins que…
Nous allons référer nos variables communes dans un nouveau fichier de type YAML. (Vous pouvez utiliser l’extension .yml
ou .yaml
; assurez-vous simplement de conserver le même choix par la suite.)
N’ayez crainte, ce format correspond simplement à celui des métadonnées que vous inscriviez dans l’en-tête d’un fichier markdown.
Créez le fichier variables.yml
:
touch variables.yml
Ouvrez le fichier variables.yml
pour édition. Nous allons y reporter les variables répétées dans nos fichiers markdown.
# ajout du menu dans le HTML
include-before:
- |
<nav class="menu">
<a href="accueil.html">Accueil</a>
<a href="page-1.html">Page #1</a>
<a href="page-2.html">Page #2</a>
<a href="page-3.html">Page #3</a>
</nav>
# pied de page
include-after:
- |
<footer>
<hr>
© 2023 – Tous droits réservés.
</footer>
# feuille de style externe
css:
- https://unpkg.com/almond.css@latest/dist/almond.lite.min.css
- style.css
document-css: true # inclure les styles par défaut de pandoc
Pour faire référence au fichier de métadonnées, il s’agit d’ajouter une option supplémentaire à la commande Pandoc, l’option --metadata-file [fichier]
:
pandoc --metadata-file variables.yml --standalone accueil.md -o accueil.html
# et ainsi de suite pour chaque page...
Utilisez la pleine puissance des variables et des modèles! Ce principe est à la base de tous les générateurs de site web –– statiques ou non.
Modèle HTML de base utilisé par Pandoc
Créez un fichier modèle : _modele.html
.
(Le recours à la barre en bas n’est pas obligatoire; il s’agit d’une petite convention pour distinguer les fichiers HTML à publier des fichiers HTML modèles.)
touch _modele.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<!-- Titre du document -->
<title>$pagetitle$</title>
<!-- Auteur -->
<!-- Note: la variable `author-meta` est géré par pandoc, utilisez `author` dans vos fichiers d’écriture -->
$for(author-meta)$
<meta name="author" content="$author-meta$" />
$endfor$
<!-- Date -->
<!-- Note: la variable `date-meta` est géré par pandoc, utilisez `date` dans vos fichiers d’écriture -->
$if(date-meta)$
<meta name="dcterms.date" content="$date-meta$" />
$endif$
<!-- Description -->
$if(description-meta)$
<!-- Note: la variable `description-meta` est géré par pandoc, utilisez `description` dans vos fichiers d’écriture -->
<meta name="description" content="$description-meta$" />
$endif$
<!-- Styles, chemins spécifiés dans les métadonnées -->
$for(css)$
<link rel="stylesheet" href="$css$" />
$endfor$
<!-- Il est possible d’inclure d’autres éléments dans l’en-tête -->
$for(header-includes)$
$header-includes$
$endfor$
</head>
<body>
<!-- Corps du document -->
$for(include-before)$
$include-before$
$endfor$
<!-- Ours (bannière, menu...) -->
<header class="ours"></header>
<!-- Disposition principale -->
<main>
<!-- Barre latérale -->
<div class="barre-laterale"></div>
<!-- Contenu principal -->
<article class="contenu-principal">
$body$
</article>
</main>
<!-- Pied-de-page -->
<footer class="pied-de-page"></footer>
$for(include-after)$
$include-after$
$endfor$
</body>
</html>
Pour utiliser le fichier modèle avec Pandoc, utilisez l’option --template [fichier]
.
# les barres obliques servent à écrire la même commande sur plusieurs lignes
pandoc --template _modele.html \
--metadata-file variables.yml \
--standalone \
accueil.md \
-o accueil.html
# ... évidemment, répéter pour chaque fichier à transformer en HTML
Toute cette répétition est bien fastidieuse! Ne pourrait-on pas simplifier toutes ces commandes répétitives en une seule?
Créons un fichier shell site.sh
:
touch site.sh
Une première manière simple serait de retranscrire nos commandes pour chaque page que nous souhaitons convertir. Commençons par cela, le gain de temps se fera déjà sentir!
site.sh
#!/bin/bash
# `echo` est utilisé pour avoir un retour de l’activité qui se déroule dans la console
echo "Production du fichier accueil.html..."
pandoc --template _modele.html \
--metadata-file variables.yml \
--standalone \
accueil.md \
-o accueil.html
echo "Production du fichier page-1.html..."
pandoc --template _modele.html \
--metadata-file variables.yml \
--standalone \
page-1.md \
-o page-1.html
# ... et ainsi de suite
C’est un peu long. On pourrait réunir les options passées à Pandoc dans une variable, OPTIONS_PANDOC
:
OPTIONS_PANDOC="--template _modele.html --metadata-file variables.yml --standalone"
… et l’utiliser ainsi dans le script :
pandoc $OPTIONS_PANDOC [source] -o [sortie]
Lorsque vous aurez terminé les substitutions, sauvegardez votre script. Dans votre terminal, essayez de l’appeler comme ceci :
bash site.sh
Vos fichiers devraient avoir être produits!
Nous avons réussi à automatiser la fabrique de nos fichiers accueil.html
, page-1.html
, etc.; sauf que si nous renommons nos fichiers (par exemple : accueil.md
=> index.md
) ou que nous en créons un nouveau (page-4.html
), notre script ne sera plus à jour! Pouvons-nous faire quelque chose?
site.sh
#!/bin/bash
# Aller chercher tous les fichiers source (markdown)
SOURCE=$(find . -iname "*.md" -not -iname "README*" -maxdepth 1)
# Énoncer les contreparties HTML
HTML=$(find . -iname "*.html" -not -iname "README*" -not -iname "_modele*" -maxdepth 1)
# options pour pandoc
OPTIONS_PANDOC="--to html --standalone --metadata-file=variables.yml --template _modele.html --toc --citeproc"
function clean() {
echo "* Nettoyage des fichiers HTML..."
for i in $HTML; do
echo " rm $i"
rm $i;
done
echo "" # produire une ligne vide dans la sortie de la console
}
function html() {
cd $(pwd)
echo "* Fabrication des fichiers HTML..."
for i in $SOURCE; do
echo " Conversion de $i"
pandoc $OPTIONS_PANDOC $i -o ${i/.md/.html};
done;
echo "" # produire une ligne vide dans la sortie de la console
}
function all() {
clean
html
echo "Terminé!"
}
# et on lance la fonction `all` (qui fait tout)
all
En résumé, les fichiers que nous avons :
.
├── _modele.html
├── accueil.html
├── accueil.md
├── page-1.html
├── page-1.md
├── page-2.html
├── page-2.md
├── page-3.html
├── page-3.md
├── site.sh
├── style.css
└── variables.yml
Si vous avez réussi à parcourir toutes les étapes du tutoriel, bravo! Vous avez acquis un savoir exceptionnel qui vous permettra de mettre en place votre propre petit site web statique.
Téléchargez le projet et poursuivez votre aventure à partir du dossier site/
qui se trouve à la racine :
https://github.com/loup-brun/atelier-generateur-site-statique
Il existe un grand nombre de générateurs de sites statiques. Voici une petite liste :
… mais tous produisent du HTML à la fin!
Et il y en a bien d’autres…