Pelican, Python, Markdown et les images sont dans un bateau ...

De base, avec le paquet Markdown d'installé, Pelican permet d'insérer des images. Mais le code HTML généré ne comprend qu'une simple balise <img> dans un paragraphe. Voici une méthode pour insérer automatiquement et proprement une image avec sa légende.

En général, Pelican et le Markdown forment un combo gagnant. On rédige rapidement ce que l'ont veut, le rendu est propre, et les éléments à disposition sont assez nombreux.

La problématique

Cependant, je suis tombé sur un cas limite : les images. De base, elles sont supportées1, mais dans le HTML final, il n'y a qu'une simple balise <img>. Par exemple, ce code markdown :

![Une légende pour préciser]({static}/images/image.png)

Va produire le HTML suivant :

<img alt="Une légende pour préciser" src="../images/image.png">

Le rendu final peut être suffisant, et va l'être dans la plupart des cas. Mais je veux afficher le contenu de la propriété title directement sous l'image, pour faire une légende. Il existe même, depuis HTML5, les balises <figure>2 et <figcaption>3, alors pourquoi se priver ?

La solution choisie

Il existe de nombreux plugins pour Pelican, mais la plupart me semblent bien trop gros pour mon besoin. J'ai fini par trouver une petite extension au paquet markdown pour python : figureAltCaption.

Elle permet, via le même markdown de générer un HTML différent :

<figure>
    <img alt="Une légende pour préciser" src="./images/image.png">
    <figcaption>Une légende pour préciser</figcaption>
</figure>

Ce qui est exactement ce que je recherche. Mais elle n'est pas packagée sur Pypi. Voilà pourquoi j'ai écrit cet article, au lieu de juste mettre le lien dans la page de choses en vrac.

L'installation

Simple, mais un peu brutal. J'ai copié le fichier figureAltCaption.py dans le dossier site-packages du virtualenv de mon installation de Pelican. Ensuite, j'ai modifié mon pelicanconf.py et ajouté figureAltCaption dans le dictionnaire des extension markdown.

Attention, si vous n'avez aucun paramétrage particulier pour le markdown et ses extensions, il faut bien penser à mettre le dictionnaire complet (valeurs par défaut4 plus la nouvelle extension) :

MARKDOWN = {
    'extension_configs': {
        'figureAltCaption': {},
        'markdown.extensions.codehilite': {'css_class': 'highlight'},
        'markdown.extensions.extra': {},
        'markdown.extensions.meta': {},
    },
    'output_format': 'html5',
}

Et pas juste paramétrer la nouvelle :

MARKDOWN = {
    'extension_configs': {
        'figureAltCaption': {},
    },
    'output_format': 'html5',
}

Et voilà ! C'est ce que je voulais, quelque chose de léger au niveau de mon installation et une solution propre au niveau du rendu final.

Un poil de CSS dans le thème pour peaufiner l'affichage image / légende, rien de plus5. Et je trouve que ça permet de faire quelque chose de bien plus lisible.

Subtilité : les images cliquables

A la base, l'extension ne permet pas de faire d'imbriquer les images dans un lien. Par exemple :

[![Légende pour l'image]({static}/images/image.png)]({static}/images/image.png)

Ne Fonctionne pas. Dommage quand on essaye de faire du responsive. Pour y arriver j'ai modifié le script de cette manière :

--- /home/moi/Downloads/figureAltCaption.py 2019-01-30 18:24:40.556922742 +0100
+++ .venv/lib/python3.7/site-packages/figureAltCaption.py   2019-01-30 18:35:11.274165578 +0100
@@ -38,8 +38,8 @@
 import logging
 logger = logging.getLogger('MARKDOWN')

-FIGURES = [u'^\s*'+IMAGE_LINK_RE, u'^\s*'+IMAGE_REFERENCE_RE] #is: linestart, any whitespace (even none), image, any whitespace (even none), line ends.
-CAPTION = r'\[(?P<caption>[^\]]*)\]' # Get the contents within the first set of brackets
+FIGURES = [u'\s*'+IMAGE_LINK_RE, u'\s*'+IMAGE_REFERENCE_RE] #is: any whitespace (even none), image, any whitespace (even none), line ends.
+CAPTION = r'\!\[(?P<caption>[^\]]*)\]' # Get the contents within the first set of brackets
 ATTR = r'\{(?P<attributes>[^\}]*)\}'

 # This is the core part of the extension

J'ai fait sauter la restriction de début de ligne pour les regex déclarées dans FIGURES, puis j'ai rajouté un \! au début de la détection du bloc qui va faire CAPTION.

A l'occasion il faudra que j'envoie cette modification à l'auteur, ça pourrait lui servir ...

Petite astuce bonus

Pour savoir où se trouve le dossier site-packages depuis un virtualenv : ouvrir une console python et faire :

import site; site.USER_SITE

En dehors, la commande suivante est disponible :

import site; site.getsitepackages()

Après avoir placé le fichier, faire un simple

import figureAltCaption

ne doit pas renvoyer d'erreur.


  1. Daring Fireball : markdown 

  2. w3 schools : tag figure 

  3. w3 schools : tag figcaption 

  4. La doc de Pelican, voir 'MARKDOWN' 

  5. En vrai si, j'ai corrigé mes sources où j'avais utilisé les attributs étendus.