Rendez-vous sur Arrakis

C'est lorsque nous croyons savoir quelque chose qu'il faut justement réfléchir un peu plus profondément. F. Herbert

Mise à jour de swx en version 0.6

Afin de gérer mon site web, j'avais écrit swx. Je me suis penché à nouveau sur son code afin d'accorder plus d'importance au site plutôt qu'au blog. En effet, je délaissais son contenu. Dans cet article, je vais parler des changements apportés à swx.

Principe de fonctionnement

Pour rappel, swx est un ensemble de petits scripts shell permettant de fabriquer un site statique. Il ne doit pas dépendre d'outils ou de bibliothèques tierces, mis à part un éventuel convertisseur de langage markup (markdown, txt2tags, pandoc…).

Il va prendre pour argument un dossier contenant un site web et toute sa structure. Ce dossier et copié dans un répertoire avec l'extension “.static”, après avoir convertit les pages et inséré un menu de navigation.

D'autres scripts peuvent être lancés pour fabriquer un sitemap, un flux atom ou une page de type “blog”.

Le dossier final n'a plus qu'à être envoyé sur un serveur pour être accessible (ftp, sftp…)

Le tout s'utilise avec un fichier Makefile pour simplifier le processus.

Les modifications récentes

Dans cette nouvelle version, j'ai revu la logique de certains scripts, notamment pour la liste des nouvelles pages.

Ces changements n'ont pas été détaillés sur le dépôt. Je dois m'occuper de rédiger les pages de documentation auparavant… Par ailleurs, certains éléments sont propres à OpenBSD, il faut les tester sous GNU avant (commandes find, date et stat avec des options différentes).

Détection des changements

Au lieu d'utiliser rsync ou de copier tout le contenu du “dossier modèle”, swx va désormais comparer la date de modification des fichiers avec un fichier-repère créé automatiquement à la fin de chaque génération. Ce fichier est .swx.last et se trouve dans le dossier du site généré.

Pour refabriquer l'ensemble d'un site, il suffit de le supprimer.

Utilisation d'un template

Afin de personnaliser l'apparence des pages, l'utilisateur peut désormais utiliser un fichier modèle (template). Ce fichier ressemble à ceci :

<!doctype html>
<html lang="fr">
<head>
${_PAGETITLE_}
<link rel="icon" href="/favicon.png" type="image/png">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<link rel="stylesheet" type="text/css" href="/style.min.css">
<link href="/atom.xml" type="application/atom+xml" rel="alternate" title="Atom feed of yeuxdelibad.net" />
</head>

<body>
<header>
${_HEADER_}
<nav id="menubar">
${_NAVPATH_}
${_MENU_}
</nav>
</header>
<aside id="sidebar">
    <div class="tooltip">
        <a href="/atom.xml" class="icon">📰</a>
        <span class="tooltiptext">
            Flux ATOM pour s'abonner
        </span>
    </div> 
</aside>
<main>
<div id="article">
${_MAIN_}
</div>
</main>
<footer>
Le 
${_GENDATE_}
avec <a href="https://3hg.fr/Scripts/swx">swx</a>
</footer>
</body>
</html>

On remarque dans ce fichier des éléments comme ${_PAGETITLE_}. Il s'agit de variables qui seront remplacées par la fonction générant les pages. On remarquera notamment :

Ainsi, l'utilisateur peut plus facilement gérer l'apparence de ses pages.

Une nouvelle option fait son apparition si on souhaite changer la syntaxe désignant une variable. Il s'agit d'une expression régulière :

TOREPLACE='^\${_.*_}$'

Par défaut, ce sont les lignes commençant par $, suivies d'une accolade et d'un underscore, terminant par un underscore, accolade en bout de ligne.

Séparation du code

Les fonctions et variables communes à tous les petits scripts sont rassemblés dans un fichier swx.functions.

Création d'un flux atom

Au lieu d'un flux RSS, c'est le format ATOM plus rigoureux que je privilégie. Le script swx_atom va rechercher les fichiers les plus récents puis ajouter son contenu dans un fichier atom.xml.

Afin de trouver les fichiers plus récents, c'est find qui est utilisé :

Sous GNU :

RECENTS=$(find "${1}" -type f -name "*${EXT}" -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head -n "${MAX}")

Avec OpenBSD, c'est un poil plus court :

RECENTS=$(find "${1}" -type f -name "*${EXT}" -exec stat -f "%m %N" {} \; | sort -nr | head -n "${MAX}" | cut -d' ' -f2-)

Le nombre maximum d'entrées est définit avec la variable MAX présente dans le fichier de configuration.

Afin de savoir à quelle date la page a été créée pour la mettre dans le flux atom, on se sert de stat :

Sous GNU :

    UPDATED="$(date -ud @`stat -t ${i}|cut -f13 -d\ ` +%Y-%m-%dT%TZ)"

Avec OpenBSD :

    UPDATED=$(date -ur $(stat -f %m "${i}") +%Y-%m-%dT%TZ)

Gestion d'une page de nouveauté

Afin d'utiliser swx comme moteur de blog, j'ai voulu améliorer cet aspect. Un script swx_blog est capable de détecter les fichiers les plus récents avec find.

Ces fichiers sont analysés pour en retirer le titre (première ligne) et le lien.

Deux nouvelles options font leur apparition pour la suite :

NEWSSTR="%%%BLOOOOG%%%"
NEWSPAGE="/index.md"

La première correspond à un bout de texte que l'on met dans une page et qui sera remplacé par la liste des nouveautés. La seconde correspond à la page du site qui servira d'entrée dans le blog, et qui contient justement le bout de texte précédent.

swx_blog va convertir cette page et remplacer $NEWSSTR par une liste de lien vers les nouvelles pages.

J'ai hésité à inclure directement le contenu des pages en utilisant les balises <summary> et <details>, mais pour l'instant ça me convient ainsi.

Autres changements

Ci et là des corrections de bugs et amélioration de syntaxe. Les variables sont protégées, et normalement le tout doit tourner sur les systèmes de type UNIX.

Démonstration ?

Ce site 😁

Sinon, j'utilise ce fichier Makefile pour générer l'ensemble de mon site écrit en markdown :

SOURCEDIR=/home/xavier/Documents/site/epicededune/Rendez-vous_sur_Arrakis/
DESTDIR=/home/xavier/Documents/site/epicededune/Rendez-vous_sur_Arrakis.static/

all:
    @echo "Generate website"
    @./swx $(SOURCEDIR)
    @echo "Remove .swp"
    @find $(DESTDIR) -name '*.swp' -exec rm '{}' \;
    @echo "Generate sitemap and gzip it"
    @./swx_sitemap  $(DESTDIR) > $(DESTDIR)/sitemap.xml
    @gzip --best -c $(DESTDIR)/sitemap.xml > $(DESTDIR)/sitemap.gz
    @echo "Generate website plan"
    @./swx_plan $(DESTDIR) > $(DESTDIR)/Divers/Plan_du_site.html
    @echo "Generate atom feed"
    @./swx_atom $(SOURCEDIR) > $(DESTDIR)/atom.xml
    @echo "Generate blog news entry"
    @./swx_blog $(SOURCEDIR) 
clean:
    rm -rf *.static
force:
    rm $(DESTDIR)/.swx.last
    make all
regen:
    find Rendez-vous_sur_Arrakis -name *.md -exec touch {} \;
    make all
serve:
    sleep 1 && surf http://localhost:8000 &
    cd $(DESTDIR) && python3 -m http.server 

Un make serve me permet de voir mon site dans un navigateur après avoir généré le tout avec make. Un rsync avec un tunnel SSH envoie le tout sur mon serveur sous OpenBSD bien sûr ☺️.

Et ça ressemble à ça :

$ make
Generate website
> Load configuration
> Prepare output directory
> Generating html pages and copying files
[##################################################] 4/4

> Done! :)
Remove .swp
Generate sitemap and gzip it
Generate website plan
Generate atom feed
Generate blog news entry