<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="https://www.dioptre.fr/blog/rss.xml" rel="self" type="application/rss+xml" />
<title>Les dernières nouvelles sur dioptre.fr</title>
<description>Ici sont regroupés les derniers articles publiés sur dioptre.fr. Ils sont disponibles dans un fil [RSS](http://www.dioptre.fr/blog/rss.xml).</description>
<link>https://www.dioptre.fr/blog/</link>
<lastBuildDate>Fri, 12 Jun 2026 00:00:00 +0000</lastBuildDate>
<item>
<guid>https://www.dioptre.fr/blog/2025-1-boire-en-periode-de-fortes-chaleurs.html</guid>
<link>https://www.dioptre.fr/blog/2025-1-boire-en-periode-de-fortes-chaleurs.html</link>
<pubDate>Sun, 22 Jun 2025 00:00:00 +0000</pubDate>
<title>Boire en période de fortes chaleurs</title>
<description><![CDATA[
<h1>Boire en période de fortes chaleurs</h1>
<p>Boire est une des actions les plus importantes à réaliser en période de fortes chaleurs. En revanche, se procurer de l'eau peut être difficile, c'est pourquoi avoir une carte des points d'eau de sa région est utile.</p>
<h2>Dans la région Île-de-France</h2>
<p>La <a href="https://fr.wikipedia.org/wiki/%C3%8Ele-de-France">région Île-de-France</a> a publié une <a href="https://data.iledefrance.fr/explore/dataset/points-eau-potable-en-ile-de-france/map/">liste et une carte</a> des points d'eau sur son territoire. Ils sont nombreux à Paris, moins dans les départements aux alentours, mais cela constitue un bon point de départ.</p>
<h2>En France et dans le monde</h2>
<p>Si on part loin de chez soi, on peut utiliser l'application <a href="https://freetaps.earth/">FreeTaps</a> (disponible sur <a href="https://play.google.com/store/apps/details?id=earth.freetaps.freetaps">Android</a> et <a href="https://apps.apple.com/fr/app/freetaps/id1407952259">iOS</a>). Toutes les régions ne sont pas bien couvertes, il y a des faux positifs, mais cette application m'a déjà été fort utile.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2024-1-hello-world-en-piet.html</guid>
<link>https://www.dioptre.fr/blog/2024-1-hello-world-en-piet.html</link>
<pubDate>Mon, 11 Nov 2024 00:00:00 +0000</pubDate>
<title>Hello world en Piet</title>
<description><![CDATA[
<h1>Hello world en Piet</h1>
<p>Le programme <a href="https://fr.wikipedia.org/wiki/Hello_world">Hello world</a> est souvent un des premiers programmes que l'on code lors de l'apprentissage d'un langage de programmation. Ici, nous allons recoder le programme en Piet qui est proposé sur la <a href="https://fr.wikipedia.org/wiki/Piet">page Wikipédia</a> de ce langage de programmation peu commun.</p>
<h2>Un mot sur Piet</h2>
<p>Ce langage de programmation est basé sur l'exploitation d'une image colorée, inspirée des travaux de <a href="https://fr.wikipedia.org/wiki/Piet_Mondrian">Piet Mondrian</a>. C'est un langage exotique du fait de l'absence d'intérêt industriel à exploiter un programme codé à l'aide d'un langage interprété et qui, vu que c'est une image, est particulièrement lourd.</p>
<h2>Hello world en Piet</h2>
<p>Il existe plusieurs formes du programme Hello world en Piet, dont une proposée par Thomas Schoch décrite dans un <a href="https://retas.de/thomas/computer/programs/useless/piet/explain.html">article</a> très détaillé. C'est une grille 13x13, avec chaque tuile possédant une largeur de 11 pixels et surtout très esthétique.</p>
<p>Cette image, un gif de 16 ko, est lourde, faiblement résolue et le format choisi pour l'enregistrement produit une déformation des couleurs. Dans cet article, nous allons nous pencher sur la création d'une nouvelle image qui n'aurait pas ces défauts.</p>
<h2>Le format choisi</h2>
<p>Pour ne plus avoir les défauts de la précédente image, le format devra soit être vectoriel, à savoir <a href="https://fr.wikipedia.org/wiki/Scalable_Vector_Graphics">svg</a>, soit permettre de beaux aplats de couleur, à savoir <a href="https://fr.wikipedia.org/wiki/Portable_Network_Graphics">png</a>. Nous allons donc créer une image vectorielle que nous convertirons en fichier png.</p>
<h2>Réemploi des données de la précédente image.</h2>
<p>L'analyse nécessaire de la précédente image pourrait être faite à la main, mais le caractère fastidieux de la tâche encourage à employer un <a href="https://piet-editor.github.io/">interpréteur</a> qui nous renseignera sur les couleurs de chaque tuile. Le tout est placé sous la forme d'une liste de liste dans un script python.</p>
<pre><code>tile_color_names = [
    ["yellow","light blue","blue","dark blue","dark magenta","dark cyan","dark yellow","dark green","cyan","yellow","magenta","dark magenta","light green"],
    ["light red","dark blue","cyan","dark cyan","light cyan","light blue","blue","magenta","dark magenta","magenta","dark magenta","light green","light red"],
    ["dark cyan","yellow","green","red","light yellow","light magenta","light red","light blue","blue","dark blue","light yellow","light red","dark yellow"],
    ["light cyan","light yellow","light magenta","dark green","yellow","light red","light blue","dark cyan","light cyan","red","yellow","light blue","dark green"],
    ["dark green","green","dark magenta","magenta","light magenta","black","black","black","light magenta","dark red","green","blue","yellow"],
    ["light blue","blue","dark yellow","light magenta","black","black","light green","black","black","light red","red","dark blue","dark yellow"],
    ["light yellow","red","dark red","light blue","black","light green","light green","light green","black","light yellow","yellow","dark magenta","light yellow"],
    ["light magenta","green","dark green","magenta","black","black","cyan","black","black","yellow","magenta","light cyan","light green"],
    ["light cyan","yellow","dark blue","dark red","light yellow","black","dark blue","black","light yellow","dark yellow","cyan","light blue","light cyan"],
    ["cyan","dark red","dark cyan","dark magenta","light magenta","magenta","dark green","magenta","light magenta","light blue","dark cyan","light green","light yellow"],
    ["light blue","dark magenta","light cyan","light blue","dark yellow","yellow","dark green","light cyan","light green","light yellow","light red","green","light magenta"],
    ["yellow","dark yellow","dark cyan","red","light red","red","light red","dark red","red","green","dark cyan","dark magenta","magenta"],
    ["cyan","dark cyan","red","light red","light magenta","dark magenta","magenta","yellow","dark green","dark yellow","yellow","cyan","dark green"],
]
</code></pre>
<h2>Les couleurs de Piet</h2>
<p>Le langage de programmation Piet utilise des couleurs très précises, recensées sur la <a href="https://fr.wikipedia.org/wiki/Piet">page Wikipédia</a> de Piet, qui seront donc placées dans un dictionnaire python.</p>
<pre><code>piet_colors = {
    "black": "#000000",
    "white": "#FFFFFF",
    "light red": "#FFC0C0",
    "light yellow": "#FFFFC0",
    "light green": "#C0FFC0",
    "light cyan": "#C0FFFF",
    "light blue": "#C0C0FF",
    "light magenta": "#FFC0FF",
    "red": "#FF0000",
    "yellow": "#FFFF00",
    "green": "#00FF00",
    "cyan": "#00FFFF",
    "blue": "#0000FF",
    "magenta": "#FF00FF",
    "dark red": "#C00000",
    "dark yellow": "#C0C000",
    "dark green": "#00C000",
    "dark cyan": "#00C0C0",
    "dark blue": "#0000C0",
    "dark magenta": "#C000C0",
}
</code></pre>
<h2>Création du fichier svg</h2>
<p>Il ne reste plus qu'à créer un fichier svg, à l'aide d'une fonction de traduction des couleurs en code couleur.</p>
<pre><code>def color_name_to_hex(color_name, piet_colors):
    return piet_colors[color_name]
</code></pre>
<p>Et à l'aide d'une boucle for, il n'y a plus qu'un remplissage du fichier svg à faire, avec des tuiles de 300 pixels de large.</p>
<pre><code># Dimensions of each tile
square_size = 300

# SVG beginning
svg_content = f'&lt;svg width="{13 * square_size}" height="{13 * square_size}" xmlns="http://www.w3.org/2000/svg"&gt;\n'

for row in range(13):
    for col in range(13):
        color = color_name_to_hex(tile_color_names[row][col], piet_colors)
        x = col * square_size
        y = row * square_size
        svg_content += f'  &lt;rect x="{x}" y="{y}" width="{square_size}" height="{square_size}" fill="{color}" /&gt;\n'

# SVG ending
svg_content += '&lt;/svg&gt;'

# SVG to a file
svg_filename = "output.svg"
with open(svg_filename, "w") as file:
    file.write(svg_content)
</code></pre>
<p><img src="https://www.dioptre.fr/img/13-hello-world-piet.svg" alt="hello world en Piet" class="img-responsive"></p>
<p>Le fichier obtenu est vectoriel et donc de résolution infinie, et ne pèse que 11 ko, le contrat est rempli.</p>
<h2>Et l'image au format png ?</h2>
<p>Nous laisserons le soin au lecteur de télécharger le fichier précédent et de le convertir en utilisant, par exemple, la commande ci-dessous qui fait appel à Inkscape.</p>
<pre><code>inkscape --export-type=png --export-filename={13-hello-world-piet.svg}"
</code></pre>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2021-3-les-packages-de-base-pour-latex-en-francais.html</guid>
<link>https://www.dioptre.fr/blog/2021-3-les-packages-de-base-pour-latex-en-francais.html</link>
<pubDate>Fri, 15 Jan 2021 00:00:00 +0000</pubDate>
<title>Les packages de base pour LaTeX en français</title>
<description><![CDATA[
<h1>Les packages de base pour LaTeX en français</h1>
<p>Comme nous l'avons vu dans l'<a href="https://www.dioptre.fr/blog/2020-23-creation-d-un-fichier-tex-minimal.html">article</a> présentant un exemple minimal pour tester notre installation LaTeX, il est utile de charger quelques bibliothèques spécifiques.</p>
<p>Nous pouvons citer, au premier rang :</p>
<ul>
<li><a href="https://ctan.org/pkg/babel">babel</a>, pour prendre en compte les spécificités de la typographie dans une langue donnée ;</li>
<li><a href="https://ctan.org/pkg/fontenc">fontenc</a> avec l'argument T1, pour assurer que la police de caractères est la bonne, avec des ligatures correctes.</li>
</ul>
<p>Au deuxième rang, si le package tikz est utilisé, il faudra placer dans le préambule du fichier la ligne suivante :</p>
<pre><code>\usetikzlibrary{babel}
</code></pre>
<p>Enfin, et au troisième rang, il est possible de faire un ensemble de modification à la mise en page du fichier, de manière à le rendre plus agréable à l'œil, comme :</p>
<ul>
<li>changer la police de caractères pour une plus légère que celle fournie par défaut avec <a href="https://www.ctan.org/pkg/lm">lmodern</a> ;</li>
<li>assurer une bonne mise en forme des entêtes et des pieds de pages avec <a href="https://ctan.org/pkg/fancyhdr">fancyhdr</a> ;</li>
<li>prendre en charge les références et les urls avec <a href="https://ctan.org/pkg/hyperref">hyperref</a>.</li>
</ul>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2021-2-installation-d-une-distribution-latex.html</guid>
<link>https://www.dioptre.fr/blog/2021-2-installation-d-une-distribution-latex.html</link>
<pubDate>Fri, 08 Jan 2021 00:00:00 +0000</pubDate>
<title>Installation d'une distribution LaTeX</title>
<description><![CDATA[
<h1>Installation d'une distribution LaTeX</h1>
<h2>LaTeX sous Windows</h2>
<p>La distribution phare sous Windows est <a href="https://miktex.org/">MiKTeX</a>. Elle est connue pour une chose : être capable de télécharger à la volée des bibliothèques manquantes pour la compilation d'un document. Pour le reste, elle est complète, et est mise à jour très régulièrement.</p>
<p>On a le choix de l'installation, locale ou globale sur le système, du répertoire d'installation et des paramètres format de papier.</p>
<p>Un ensemble d'éditeurs sont disponibles, on laissera le choix au lecteur de les découvrir.</p>
<h2>LaTeX sous GNU/Linux, version packagée</h2>
<p>Il est possible d'installer une distribution LaTeX sur toutes les machines GNU/Linux, la distribution <a href="https://www.tug.org/texlive/">TeX Live</a>, créée par le groupe des utilisateurs de TeX (<a href="https://www.tug.org/">TUG</a>). Il est possible de l'installer également sur Windows, comme MiKTeX peut-être installée sur GNU/Linux, mais ces choix sont plus anecdotiques. Sur un système dérivé de Debian, on utilisera la commande suivante :</p>
<pre><code>sudo apt install texlive texlive-lang-french
</code></pre>
<p>pour une installation minimale, ou bien, pour une installation complète :</p>
<pre><code>sudo apt install texlive-full
</code></pre>
<p>Dans ce dernier cas, l'installation est relativement longue et consommatrice d'espace disque, de l'ordre de 5 Go. C'est malgré tout la solution qui est habituellement préconisée, vu qu'elle permet de télécharger l'intégralité des bibliothèques une fois pour toutes.</p>
<h2>LaTeX sous GNU/Linux, installation manuelle</h2>
<p>L'installation avec un package est sensible aux mises à jour des packages de votre distribution GNU/Linux. Cela n'est généralement pas un problème pour des <a href="https://fr.wikipedia.org/wiki/Rolling_release">rolling release</a>, mais pour des distributions figées avec numéro de version, on peut avoir une version de TeX Live datée, et incompatible avec les autres utilisateurs. C'est le cas en particulier pour les utilisateurs de Debian et des versions LTS d'Ubuntu.</p>
<p>Dans ces cas, on pourra privilégier une installation manuelle de TeX Live, qui peut être faite pour le seul utilisateur ou pour le système entier. Nous choisirons ici d'installer la dernière version de TeX Live (2020 à la date d'écriture de l'article) dans le répertoire de l'utilisateur, et on suivra le <a href="https://www.tug.org/texlive/quickinstall.html">guide officiel</a> disponible en anglais, qui comprend les points suivants :</p>
<ol>
<li>Télécharger l'<a href="https://www.tug.org/texlive/acquire-netinstall.html">installeur</a> en veillant à bien choisir <code>install-tl-unx.tar.gz</code> ;</li>
<li>Supprimer toute trace d'une précédente installation de TeX Live, mais nous considérons ici que TeX Live n'a jamais été installé auparavant ;</li>
<li><p>Extraire le contenu de l'archive là où l'archive a été téléchargée :</p>
<pre><code>tar -xf install-tl-unx.tar.gz
</code></pre></li>
<li><p>Exécuter l'installeur :</p>
<pre><code>cd install-tl-YYYYMMDD/
perl install-tl
</code></pre></li>
<li><p>Sélectionner <code>O</code> puis <code>P</code> pour définir le format du papier par défaut comme étant A4, puis <code>R</code> pour revenir au menu ;</p></li>
<li><p>Sélectionner <code>D</code> puis <code>1</code> pour définir le chemin d'installation, nous considérerons ici :</p>
<p>~/textlive/2020</p></li>
<li><p>Sélectionner <code>I</code> pour installer la distribution, ce qui prendra 7 Go environ.</p></li>
<li><p>Ajouter à la fin du fichier <code>~/.profile</code> la ligne suivante, qui permettra au système de trouver les exécutables de la distribution LaTeX :</p>
<p>PATH=$HOME/texlive/2020/bin/x86_64-linux:$PATH</p></li>
</ol>
<p>L'installation est complète, tous les packages disponibles sont téléchargés.</p>
<h2>Test de la distribution</h2>
<p>Une fois la distribution installée, il s'agit de la tester. Vérifions en premier lieu que la version installée et la bonne :</p>
<pre><code>tex --version
</code></pre>
<p>Cette commande devrait retourner un numéro de version faisant apparaitre la version de TeX Live disponible.</p>
<p>Ensuite, nous pouvons reprendre l'exemple introduit dans un <a href="https://www.dioptre.fr/blog/2020-23-creation-d-un-fichier-tex-minimal.html">précédent article</a>, l'enregistrer avec le nom <code>minimal.tex</code>. Sous GNU/Linux, nous pourrons alors le compiler avec la commande :</p>
<pre><code>pdflatex minimal.tex
</code></pre>
<p>Nous verrons apparaitre un ensemble de fichiers relatifs à la compilation et un fichier pdf (idéalement non vide), qui contient les informations souhaitées. Félicitations, vous avez compilé votre premier fichier TeX. La sortie devrait tenir sur deux pages, comme le montre le montage ci-dessous.</p>
<p><img src="https://www.dioptre.fr/img/12-minimal.png" alt="pdf de minimal.tex" class="img-responsive"></p>
<p>Sous Windows, il vous faudra ouvrir le fichier ainsi créé avec un éditeur LaTeX que vous aurez découvert, et vous devriez obtenir sensiblement le même résultat.</p>
<h2>Mise à jour de TeX Live</h2>
<p>Même si cela n'est pas utile (et parfois même déconseillé), il est possible de la <a href="https://www.tug.org/texlive/pkginstall.html">mettre à jour</a>. Pour cela, on liste dans un premier temps les packages qui doivent être mis à jour, puis si on est satisfait, on peut procéder à la mise à jour :</p>
<pre><code>tlmgr update --list
tlmgr update --self &amp;&amp; tlmgr update --all
</code></pre>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-23-creation-d-un-fichier-tex-minimal.html</guid>
<link>https://www.dioptre.fr/blog/2020-23-creation-d-un-fichier-tex-minimal.html</link>
<pubDate>Fri, 27 Nov 2020 00:00:00 +0000</pubDate>
<title>Création d'un fichier tex minimal</title>
<description><![CDATA[
<h1>Création d'un fichier tex minimal</h1>
<h2>Sans plus attendre, l'exemple</h2>
<p>Voici un exemple de fichier LaTeX relativement minimal :</p>
<pre><code>\documentclass[french,12pt]{article}

\usepackage{lipsum}
\usepackage{babel}
\usepackage[T1]{fontenc}

\title{Tests avec \LaTeX}
\author{Test~\textsc{Auteur}}

\begin{document}

\maketitle

\section{Première partie}

\subsection{Première sous-partie}

\lipsum[1]

\subsection{Deuxième sous-partie}

\lipsum[2]

\section{Deuxième partie}

\subsection{Troisième sous-partie}

\lipsum[3]

\subsection{Quatrième sous-partie}

\lipsum[4]

\end{document}
</code></pre>
<p>Nous lui donnerons le nom <code>minimal.tex</code>, et prendrons soin de vérifier que son codage de caractère est bien <a href="https://fr.wikipedia.org/wiki/UTF-8">UTF-8</a>.</p>
<h2>L'anatomie d'un fichier tex</h2>
<p>Un fichier tex est composé de plusieurs parties. Nous distinguons ce qui se trouve avant et ce qui se trouve après la commande <code>\begin{document}</code>.</p>
<h3>Préambule</h3>
<p>La partie avant la commande <code>\begin{document}</code> constitue le préambule du document, il doit contenir certaines informations, comme en particulier le type de document utilisé ici.</p>
<p>Le type de document est donné par la commande</p>
<pre><code>\documentclass[french,12pt]{article}
</code></pre>
<p>La classe (le type de document) article est un bon choix de départ, simple à utiliser et versatile. Entre les crochets sont donnés deux arguments qui seront appliqués à l'ensemble du document :</p>
<ul>
<li><code>french</code> : cela indique la langue du document et commande à LaTeX la production d'une typographie adaptée ;</li>
<li><code>12pt</code> : on fixe ainsi la taille de la police pour le texte usuel, les tailles des titres et sous-titres seront ajustées automatiquement en fonction de cette valeur.</li>
</ul>
<p>On a ensuite un ensemble de packages, de modules, qui sont chargés avant la compilation à proprement parler du document. Nous chargeons :</p>
<ul>
<li><a href="https://ctan.org/pkg/lipsum">lipsum</a> : un package qui permet de remplir un document avec un texte issu du site <a href="https://lipsum.com/">lipsum.com</a> ;</li>
<li><a href="https://ctan.org/pkg/babel">babel</a> : un module qui assure la bonne mise en forme du document et d'une typographie en accord avec les règles d'usage de la langue indiquée ;</li>
<li><a href="https://ctan.org/pkg/fontenc">fontenc</a> avec l'argument T1 : obligatoire pour des documents en français, ce package autorise LaTeX à choisir le bon type de police en lien avec une langue.</li>
</ul>
<p>Enfin, et même si ce n'est pas obligatoire, on définit le titre du document et l'auteur de celui-ci. De la même manière, il serait possible de définir la date à l'aide de la commande du même nom.</p>
<h3>Document</h3>
<p>Le document se trouve entre les balises <code>\begin{document}</code> et <code>\end{document}</code>. On y voit apparaitre, successivement, les commandes suivantes :</p>
<ul>
<li><code>\maketitle</code> fait apparaitre le titre accompagné du nom de l'auteur et de la date de compilation du document ;</li>
<li><code>\section</code> et <code>\subsection</code> codent les titres des parties et des sous-parties du document ;</li>
<li><code>\lipsum</code> permettent de remplir le document avec du texte.</li>
</ul>
<p>Nous nous servirons de ce document pour tester l'installation de LaTeX que nous ferons dans le <a href="https://www.dioptre.fr/blog/2021-2-installation-d-une-distribution-latex.html">prochain article</a>.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-22-latex-pour-qui-pour-quoi.html</guid>
<link>https://www.dioptre.fr/blog/2020-22-latex-pour-qui-pour-quoi.html</link>
<pubDate>Fri, 20 Nov 2020 00:00:00 +0000</pubDate>
<title>LaTeX, pour qui, pour quoi</title>
<description><![CDATA[
<h1>LaTeX, pour qui, pour quoi</h1>
<p>Cet article est le premier d'une série qui portera sur le langage LaTeX, sur les bénéfices et inconvénients de cette solution d'édition de documents et sur sa mise en œuvre pratique.</p>
<h2>TeX, LaTeX, c'est quoi ?</h2>
<p><a href="https://fr.wikipedia.org/wiki/TeX">TeX</a> est un langage de programmation développé à la fin des années 70 par <a href="https://fr.wikipedia.org/wiki/Donald_Knuth">Donald Knuth</a>, en réaction à la qualité discutable des productions des logiciels d'édition de l'époque. <a href="https://fr.wikipedia.org/wiki/LaTeX">LaTeX</a> est développé par <a href="https://fr.wikipedia.org/wiki/Leslie_Lamport">Leslie Lamport</a> au début des années 80 comme un ensemble de macros pour le langage TeX, permettant une édition plus aisée des documents sous ce langage.</p>
<p>Dans la suite de ces articles, on ne parlera que LaTeX, mais nous pourrons parfois utiliser quelques lignes de TeX si le besoin s'en fait sentir.</p>
<h2>LaTeX, une qualité d'édition indéniable</h2>
<p>Le langage LaTeX permet une séparation assez nette entre les étapes de construction du fond du document et celles de la forme de celui-ci. Cela est visible dès qu'on a vu de quoi était composé un fichier tex. Il contient un préambule et un corps de document. Le préambule contient toutes les informations nécessaires à la bonne mise en page et à la bonne compréhension du document par le logiciel, et le corps de document contiendra un ensemble de données qui seront présentes dans les documents final.</p>
<p>Contrairement à des logiciels <a href="https://fr.wikipedia.org/wiki/What_you_see_is_what_you_get">WYSIWYG</a> où le document est en train d'être créé sous nos yeux, une étape de compilation est nécessaire pour interpréter le fichier tex et le transformer en un document final, distribuable le plus souvent sous la forme d'un fichier pdf. Il faudra donc faire appel à un compilateur de fichier TeX. En 2020, trois compilateurs sont sur le devant de la scène, pdflatex, LuaTeX et XeTeX. Ces trois logiciels, pas totalement compatibles entre-eux, permettent d'obtenir un fichier pdf final à partir d'un fichier tex.</p>
<h2>LaTeX, pour qui ?</h2>
<p>Apprendre le langage LaTeX est un investissement en temps significatif, et demande une pratique régulière. Il est le plus utilisé dans les milieux académiques et d'enseignement, un milieu où la qualité des documents compte, et où, ceux-ci étant complexes, laisser le soin de la mise en forme à un logiciel est un réel avantage.</p>
<p>À mon sens, l'investissement en vaut la peine si on se trouve dans une situation où on doit maintenir sur le long terme un ensemble de documents ayant une charte graphique commune et susceptible d'évoluer, si on doit éditer des documents scientifiques, en particulier dans les domaines des mathématiques ou de la physique, ou si on doit créer un long document, comme une thèse de doctorat ou de master. Il peut y avoir d'autres cas que ceux proposés, mais ceux-ci sont probablement plus anecdotiques.</p>
<p>Connaitre un langage de programmation classique et avoir des notions en base en typographie est assurément un plus dans l'apprentissage de ce langage.</p>
<h2>LaTeX, pour quoi ?</h2>
<p>L'imposante communauté d'utilisateurs du langage LaTeX lui permet d'avoir un grand nombre de modules, appelés packages, qui lui permettent de s'adapter à toutes les situations ou presque. Outre les usuels mémoires ou articles scientifiques, le langage LaTeX permet l'édition de CV, de lettres ou de diaporamas, avec une excellente qualité de mise en page.</p>
<p>LaTeX étant versatile, il peut être utilisé pour éditer tout type de document, mais il n'est pas conseillé de l'utiliser pour un document où le fond est bien moins important que la forme en termes d'efforts investis. En effet, la personnalisation avancée d'une mise en page en LaTeX est assez difficile, celle-ci se faisant en lignes de commande.</p>
<p>Dans un prochain article, nous verrons de quoi doit être constitué un <a href="https://www.dioptre.fr/blog/2020-23-creation-d-un-fichier-tex-minimal.html">document tex minimal</a> puis comment <a href="https://www.dioptre.fr/blog/2020-24-installation-d-une-distribution-latex.html">installer LaTeX sur un ordinateur</a>.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-19-raccourcis-sur-ios.html</guid>
<link>https://www.dioptre.fr/blog/2020-19-raccourcis-sur-ios.html</link>
<pubDate>Fri, 30 Oct 2020 00:00:00 +0000</pubDate>
<title>Raccourcis sur iOS</title>
<description><![CDATA[
<h1>Raccourcis sur iOS</h1>
<p>En guise de suite à notre <a href="https://www.dioptre.fr/blog/2020-18-le-scripting-comme-mode-de-vie.html">précédent article</a>, nous présentons ici l'application <a href="https://apps.apple.com/fr/app/raccourcis/id915249334">Raccourcis</a> disponible sur iOS. Elle permet d'automatiser quelques actions sur un iPhone ou un iPad.</p>
<p><img src="https://www.dioptre.fr/img/7-raccourcis.png" alt="Application Raccourcis sur iOS" class="img-responsive"></p>
<h2>Le scripting sur un smartphone</h2>
<p>Un smartphone est ni plus ni moins qu'un ordinateur que nous avons sur nous en permanence. Il peut être intéressant d'automatiser quelques actions qui dépendent du lieu où nous sommes, d'une certaine heure ou d'un contexte particulier.</p>
<p>L'étendue des actions réalisables est naturellement plus limité que sur un ordinateur, et le choix du langage de programmation est imposé. Dans le cas de l'application Raccourcis, c'est une interface graphique assez bien pensée qui rappelle quelques peu l'interface de <a href="https://scratch.mit.edu/">scratch</a> qui sert de « langage » de programmation.</p>
<p>Nous pouvons présenter deux cas d'usage : la récupération et l'affichage des principaux paramètres météorologiques d'un lieu, et l'automatisation de cette tâche à un moment bien choisi de la journée.</p>
<h2>Récupération et affichage de la météo</h2>
<p>Ce raccourci, librement <a href="https://www.icloud.com/shortcuts/1fce1e10e80b4e7e9d6c6881070bb074">téléchargeable</a>, permet de récupérer les paramètres météorologiques du lieu où se trouve actuellement le téléphone et les prévisions météorologiques du jour, comme le taux de précipitations et les températures maximale et minimale. Il affiche ensuite une notification permettant de fournir à l'utilisateur les informations souhaitées.</p>
<h2>Automatisation de ce raccourci</h2>
<p>Cette tâche peut être effectuée chaque jour, chaque heure ou lors de votre départ d'un lieu prédéfini. Dans ce cas, il suffit d'indiquer dans l'onglet « Automatisation » que vous souhaitez que le raccourci s'exécute dans un contexte particulier. Un contexte intéressant est le matin en semaine lors de l'extinction de votre réveil, ou bien tous les jours à une heure choisie.</p>
<h2>Aller plus loin</h2>
<p>Il est des cas où les options offertes par l'application Raccourcis ne sont pas suffisantes. Il existe fort heureusement un moyen relativement simple pour étendre les fonctionnalités de cette application : exécuter une commande sur un poste distant via ssh, avec en entrée un certain nombre d'arguments tirés du raccourci. Dans ce cas, il faut bien entendu avoir accès à un serveur, mais cela permet d'exécuter n'importe quel programme, celui-ci pouvant être écrit dans n'importe quel langage de programmation, ce qui nous libère du carcan imposé par Apple.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-18-le-scripting-comme-mode-de-vie.html</guid>
<link>https://www.dioptre.fr/blog/2020-18-le-scripting-comme-mode-de-vie.html</link>
<pubDate>Fri, 23 Oct 2020 00:00:00 +0000</pubDate>
<title>Le scripting comme mode de vie</title>
<description><![CDATA[
<h1>Le scripting comme mode de vie</h1>
<p>Le scripting, anglicisme pour le fait de créer ou d'utiliser des scripts, peut être vu comme un mode de vie. C'est en effet une activité assez mal connue par le grand public. Posons-nous la question suivante : quel est le pourcentage des utilisateurs de l'outil informatique qui ont intégré que cet outil, ordinateur ou smartphone, était un formidable outil à exécuter des instructions, de manière itérative ou de manière récursive ? C'est bien entendu une question rhétorique, et à titre personnel, je pense que c'est là une des défaillances dans nos usages modernes de l'informatique.</p>
<h2>Le scripting, pour quoi faire ?</h2>
<p>Le scripting peut avoir différents objectifs :</p>
<ul>
<li>automatiser une tâche rébarbative à répéter un grand nombre de fois ;</li>
<li>automatiser une tâche demandant un temps d'exécution élevé qui ne nécessite pas d'interaction avec un utilisateur humain ;</li>
<li>automatiser une tâche à faire à intervalle régulier, etc.</li>
</ul>
<p>Les situations pour lesquelles il est possible de créer un script sont donc variées, mais il s'agit avant tout de simplifier la vie de l'utilisateur et d'assurer le bon déroulement de tâches routinières. On peut citer, à titre d'exemple :</p>
<ul>
<li>la sauvegarde de documents sur un disque dur externe ou un serveur distant ;</li>
<li>la construction de documents dont la structure dépend d'éléments externes ;</li>
<li>l'automatisation d'un processus qui nécessite un nombre certain d'étapes ne requérant pas une intervention externe.</li>
</ul>
<h2>Quel langage choisir ?</h2>
<p>La question du langage de programmation à utiliser est souvent posée. On a, au choix, deux types de réponses : la réponse dogmatique ou la réponse pragmatique.</p>
<p>La réponse dogmatique dira que tel ou tel langage est meilleur pour telles ou telles raisons, ces raisons dépendant de l'interlocuteur avec qui on échange. Dans la pratique, cette position permet assez souvent de remettre en perspective les choix qui ont été fait, et incitent donc, parfois, à s'intéresser à des alternatives inconnues ou délaissées.</p>
<p>La réponse pragmatique dépend davantage de la situation dans laquelle se trouve l'utilisateur soucieux d'automatiser un ensemble d'actions. Cette réponse est probablement la plus intéressante pour les raisons suivantes :</p>
<ul>
<li>un utilisateur averti sait que tel ou tel langage de programmation est plus efficace pour une situation donnée, mais ce n'est malheureusement pas l'unique facteur à prendre en compte ;</li>
<li>également, la qualité du code fourni ou les capacités du langage choisi ne sont pas les paramètres essentiels du choix ;</li>
<li>le plus souvent, le besoin d'un script se fait sentir lors de l'exécution d'une tâche, et l'idéal est de programmer le script dans l'instant pour en bénéficier le plus vite possible.</li>
</ul>
<p>Ainsi, le script intervient donc pour répondre à un besoin, à un instant donné et dans un certain contexte. Autant tenir compte de ces faits pour les choix futurs.</p>
<h2>Mais dans la pratique, que choisir ?</h2>
<p>La réponse à cette question dépend bien entendu au contexte. Il est un point essentiel : quelles sont les capacités, temporelles, techniques, matérielles dont vous disposez ?</p>
<p>En effet, les ressources à mobiliser pour écrire un programme en C, en bash ou en python ne seront pas les mêmes. Dans la pratique, les questions fondamentales sont les suivantes :</p>
<ul>
<li>quels sont les langages de programmation que vous maitrisez, ou à défaut, dont vous connaissez la syntaxe de base ?</li>
<li>quel est votre objectif ?</li>
</ul>
<p>En étant capable de répondre à ces questions, il est possible de fixer les limites de l'univers dans lequel le script sera développé.</p>
<p>Si nous prenons un exemple et l'univers dans lequel je travaille, j'ai deux réponses en fonction des contraintes liées à mon objectif. J'ai des compétences minimales dans deux langages de programmation, python et le shell POSIX. Dépendamment de mon objectif, je vais être amené à utiliser mon script soit dans un environnement GNU/Linux minimal, soit sur ma machine personnelle, soit sur un ensemble de postes informatiques qui ont des systèmes d'exploitation variés. Dans le premier cas, je choisis le shell POSIX, et dans les deux autres, cela dépend de la complexité du script à écrire : si le script est composé d'une suite de commandes Unix, je vais privilégier le shell, mais s'il y a des opérations logiques complexes ou des calculs à mener, je vais privilégier python. Je ne choisis donc pas le langage de programmation en fonction des performances voulues ou d'un autre critère, ce qui peut sembler contre intuitif.</p>
<h2>Mais quid des performances ?</h2>
<p>Si vous suivez ce blog, vous devez avoir compris que je ne suis pas pour autant en faveur des scripts lents et lourds, et que je recherche un bon niveau de performance. En effet, un script lent aura tendance à laisser penser que l'ordinateur est lent, et rien n'est plus frustrant que d'attendre que son ordinateur finisse une tâche.</p>
<p>Pour autant, l'objectif principal du scripting est de répondre à un besoin initial dans un temps qui est le plus souvent limité. Apprendre un nouveau langage est un investissement important, j'aurai donc toujours tendance à conseiller d'utiliser un langage déjà connu voire maitrisé.</p>
<h2>La méthode quick and dirty</h2>
<p>Ensuite, la méthode <a href="https://fr.wikipedia.org/wiki/Quick-and-dirty">quick and dirty</a> présente des avantages : on obtient un résultat rapide, c'est valorisant et cela permet de rentabiliser immédiatement l'investissement fourni lors de l'écriture du programme. Cela permet également d'étrenner le programme sur une situation réelle de terrain et permet de faire un premier débogage. En revanche, il est indispensable de le reprendre, lorsque le rythme de travail devient plus apaisé, de manière à s'assurer de l'absence de bugs étranges et effectuer un nettoyage du code, pour le rendre plus lisible pour des corrections ou améliorations ultérieures.</p>
<p>Il est, à mon sens, peu pertinent de ne pas prendre le temps d'éclaircir son code, car un script qui ne peut pas être compris et donc impossible à maintenir perd un peu de son intérêt, ce qui serait dommage.</p>
<h2>Approche pragmatique et rapidité d'exécution</h2>
<p>En définitive, seul l'accomplissement de l'objectif compte. Il faut donc bien déterminer son besoin, le plus souvent visible dès qu'un agacement face à un ordinateur se fait sentir, et également réfléchir à son contexte, de manière à y arriver de la manière la plus rapide possible. En revanche, se donner les moyens de reprendre le travail déjà effectué est une excellente chose à faire dès que possible par des revues de code et un suivi des modifications.</p>
<p>Et pour la question des performances, rares sont les applications qui nécessitent véritablement un temps d'exécution aussi faible que possible. Si tel est malgré tout le cas, rien n'empêche de se tourner vers un langage de bas niveau ou des méthodes d'optimisation avancées, mais le temps nécessaire à leur maitrise doit être mis dans la balance coût-bénéfice, afin d'avoir un aperçu objectif de la situation.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-14-cuisine-pour-les-debutants.html</guid>
<link>https://www.dioptre.fr/blog/2020-14-cuisine-pour-les-debutants.html</link>
<pubDate>Fri, 25 Sep 2020 00:00:00 +0000</pubDate>
<title>Cuisine pour les débutants</title>
<description><![CDATA[
<h1>Cuisine pour les débutants</h1>
<p>Cuisiner quand on est débutant est assez difficile, surtout quand personne ne nous a appris les bases de cette discipline pourtant essentielle à notre survie et à notre bien-être. Si on veut changer des pâtes au beurre et leurs déclinaisons, il est important de trouver des ressources permettant de bien manger, tout en assurant l'apprentissage des bons gestes et la montée en compétence du cuisinier débutant.</p>
<h2>Guide de cuisine de l'Étudiant</h2>
<p>Un bon livre pour débuter, Guide de cuisine de l'Étudiant de Véronique Liegeois chez Solar (<a href="https://www.lisez.com/livre-grand-format/guide-de-cuisinede-letudiant/9782263044113">EAN : 9782263044113</a>), permet de se familiariser avec les techniques élémentaires de la cuisine quotidienne. Il regroupe en particulier un ensemble de recettes pour une et deux personnes, faciles et rapides à faire, et pour tout dire, impossibles à rater. Un petit regret qui est également un avantage, le livre n'est pas illustré.</p>
<h2>Petit Larousse cuisine facile</h2>
<p>Le Petit Larousse cuisine facile chez Larousse (<a href="https://cuisine.larousse.fr/livre/petit-larousse-cuisine-facile-collector-9782035906519">EAN : 9782035906519</a>) est un beau livre, bien illustré et très complet, qui permet de monter en compétence et d'acquérir un bon nombre des techniques de bases de la cuisine française. Les recettes ne sont pas difficiles à réaliser, mais les quantités sont assez importantes, c'est un livre à recommander aux foyers composés de deux personnes ou plus. À noter : la blanquette de veau est excellente.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-12-schema-PRG.html</guid>
<link>https://www.dioptre.fr/blog/2020-12-schema-PRG.html</link>
<pubDate>Fri, 11 Sep 2020 00:00:00 +0000</pubDate>
<title>Le schéma PRG</title>
<description><![CDATA[
<h1>Le schéma PRG</h1>
<p>Nous avons vu dans un <a href="https://www.dioptre.fr/blog/2020-10-cgi-et-python.html">article précédent</a> comment apporter un peu de dynamisme à un site web statique, en construisant un programme CGI en python. Il est cependant limité, et nous allons voir ici comment remédier à une des faiblesses de ce dernier.</p>
<h2>Situation actuelle et limites</h2>
<p>Rappelons que le script CGI, cible.py, assure le traitement d'un fichier qui est transmis par l'utilisateur par l'intermédiaire d'un formulaire d'une page statique. Lorsque l'utilisateur clique sur le bouton « Envoyer », il transmet le fichier qu'il a sélectionné, et il voit alors s'afficher le message prévu par le script CGI.</p>
<p>Cependant, s'il essaye pour une raison quelconque d'actualiser la page, il verra apparaitre un message d'avertissement, lui indiquant que les données préalablement transmises vont être renvoyées.</p>
<p><img src="https://www.dioptre.fr/img/4-avertissement-renvoi.png" alt="Avertissement de renvoi de données" class="img-responsive"></p>
<p>Si l'utilisateur clique sur « Annuler », il annule le rafraichissement de la page, et rien ne se passe. En revanche, s'il clique sur « Renvoyer », il va envoyer une nouvelle fois toutes les données au serveur, dont le fichier, et le script CGI cible.py va à nouveau se déclencher et effectuer l'intégralité du traitement prévu. Dans le meilleur des cas, un nouveau fichier est écrit sur le disque du serveur, dans le pire des cas, ce nouveau fichier écrase celui préalablement transmis. C'est le problème des soumissions multiples des formulaires.</p>
<p>C'est une limite de ce script. En effet, la transmission d'un fichier n'est pas nécessairement critique, mais on pourrait imaginer les conséquences du renvoi d'un formulaire portant sur l'achat en ligne d'un objet quelconque.</p>
<h2>Le schéma PRG</h2>
<p>Pour éviter cela, il est possible de mettre en place le <a href="https://fr.wikipedia.org/wiki/Post-redirect-get">schéma de programmation PRG</a>, PRG pour post-redirect-get. L'idée principale est que, si l'utilisateur cherche à réactualiser la page affichée par le script CGI, son navigateur envoie une requête get en comportant uniquement quelques informations bien choisies, et lieu et place de la requête post qui contient toutes les informations importantes, comme le fichier transmis dans notre cas.</p>
<p>Dans la situation précédente, nous avons l'enchainement d'action suivant :</p>
<ol>
<li>l'utilisateur clique sur le bouton « Envoyer » ;</li>
<li>le navigateur envoie une requête post au serveur ;</li>
<li>le serveur accepte les données et déclenche l'exécution du script CGI ;</li>
<li>le serveur renvoie au navigateur un code http 200 et une page contenant éventuellement un message.</li>
</ol>
<p>Si l'utilisateur réactualise la page, l'action est équivalente à rappuyer sur le bouton « Envoyer » et donc à reprendre toutes les étapes de 1 à 4.</p>
<p>Dans le schéma PRG, nous construisons un nouvel enchainement d'action :</p>
<ol>
<li>l'utilisateur clique sur le bouton « Envoyer » ;</li>
<li>le navigateur envoie une requête post au serveur ;</li>
<li>le serveur accepte les données et déclenche l'exécution du script CGI ;</li>
<li>le serveur renvoie au navigateur un code http 303 accompagné d'une nouvelle adresse qui contiendra la page web à afficher ;</li>
<li>le navigateur envoie au serveur une requête get à l'adresse indiquée précédemment ;</li>
<li>le serveur renvoie au navigateur un code http 200 et une page contenant éventuellement un message.</li>
</ol>
<p>Si l'utilisateur réactualise la page, seules les actions 5 et 6 seront reprises, les informations importantes ne sont pas renvoyées au serveur.</p>
<p>Notons que les codes http <a href="https://fr.wikipedia.org/wiki/Liste_des_codes_HTTP#2xx_-_Succ%C3%A8s">200</a> et <a href="https://fr.wikipedia.org/wiki/Liste_des_codes_HTTP#3xx_-_Redirection">303</a> correspondent respectivement au succès de la requête et à la redirection vers une autre url.</p>
<p>On voit que le nom du schéma est ici assez évident : une requête post, une redirection puis une requête get, d'où le schéma post-redirect-get.</p>
<h2>Principe de mise en place dans un programme python</h2>
<h3>Nouvelle structure du programme</h3>
<p>Le choix a été fait de faire supporter au programme CGI cible.py le traitement des données reçues par la requête post, la génération de la redirection 303 et le traitement de la requête get. Ce programme est donc le seul responsable de tout le schéma PRG dans notre cas. Ceci est un peu complexe, mais permet d'avoir un unique script CGI à écrire.</p>
<p>La première chose à faire est de distinguer les requêtes post et get. Il est possible d'avoir accès au type de requête avec :</p>
<pre><code>import os
method = os.environ['REQUEST_METHOD']
</code></pre>
<p>Il reste ensuite à distinguer les deux types de requêtes :</p>
<pre><code>if method == "POST":
    # Traite les données et transmet le code http 303
elif method == "GET":
    # Affiche la réponse du serveur
else:
    # Affiche un message d'erreur
</code></pre>
<p>Il est alors possible de découper le programme en plusieurs parties et avoir des comportements différents en fonction de la requête du navigateur.</p>
<h3>Conception de la réponse 303</h3>
<p>La réponse 303 apportée par le serveur impose au navigateur d'effectuer une nouvelle requête get vers l'url qui lui transmet. Il s'agit donc de construire cette url. Le cas le plus simple est de fournir une url vers une page statique fournissant un message de succès ou d'échec de l'opération.</p>
<p>Cependant, dans l'article <a href="https://www.dioptre.fr/blog/2020-10-cgi-et-python.html">CGI et python</a>, nous avons mis en place une génération dynamique du message. Il est donc intéressant de conserver cette partie du programme précédent, qui permet de fournir à l'utilisateur un message détaillé sur le statut du transfert de son fichier.</p>
<p>Nous allons donc construire une réponse 303 qui contiendra une url contenant un statut et une référence indiquant l'état du transfert :</p>
<pre><code>import urllib.parse
query = urllib.parse.urlencode({'status': status, 'ref': ref})
print("Status: 303 See Other\nLocation: cible.py?{}\n""".format(query))
</code></pre>
<p>On obtient alors un header se terminant par ces deux lignes, soit, par exemple :</p>
<pre><code>Status: 303 See Other
Location: cible.py?status=2&amp;ref=46
</code></pre>
<p>Un header se termine toujours par une ligne vide, il faut donc l'ajouter à la fin de la commande print.</p>
<h3>Interprétation de la commande get</h3>
<p>Lors de la réception du header précédent, le navigateur envoie la requête get permettant d'accéder à la page indiquée. Elle sera donc générée sur la base des variables statut et ref présentes dans l'url de la requête. Ces variables peuvent être récupérées par le script cible.py comme présenté dans le <a href="https://www.dioptre.fr/blog/2020-10-cgi-et-python.html">précédent article</a>, vu qu'il n'y a pas de différence entre le traitement des données fournies par une requête post et une requête get.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-11-pour-une-page-web-qui-dure-10-ans.html</guid>
<link>https://www.dioptre.fr/blog/2020-11-pour-une-page-web-qui-dure-10-ans.html</link>
<pubDate>Fri, 04 Sep 2020 00:00:00 +0000</pubDate>
<title>Pour une page web qui dure 10 ans ?</title>
<description><![CDATA[
<h1>Pour une page web qui dure 10 ans ?</h1>
<h2>Un article de Jeff Huang</h2>
<p>L'article <a href="https://framablog.org/2020/08/24/pour-une-page-web-qui-dure-10-ans/">« Pour une page web qui dure 10 ans ? »</a> a été publié le 24 août 2020, c'est une traduction d'un <a href="https://jeffhuang.com/designed_to_last/">article</a> publié sur le site personnel de son auteur initial, Jeff Huang. Il y présente un certain nombre d'idées, pour un web au contenu plus durable, avec un ensemble de propositions pour que ce contenu puisse survivre 10 ans au minimum.</p>
<p>Cet article est plus une base de discussion devant mener à une réflexion, qu'une liste de recommandations à suivre à la lettre. Je vais donc ici exposer mes réflexions en lien avec cet article.</p>
<h2>1. Revenez à du html/css « Vanilla »</h2>
<p>Composer un site web en 2020 sans javascript, c'est possible. Attention, ici, je parle bien d'un site web et pas d'une application web qui devra par définition avoir davantage de capacités qu'un simple site informationnel.</p>
<p>Mais est-ce que cela veut dire qu'il faut directement rédiger le site en langage html ? À titre individuel, je pense que le langage html possède une syntaxe complexe. Le <a href="https://www.dioptre.fr/blog/2020-8-langage-markdown.html">langage markdown</a> simplifie grandement l'étape de création du contenu, même si celle-ci doit contenir une étape de conversion en page html. Cette étape n'est pas limitante en termes de maintenance du code, car le résultat est une page html qu'il est possible de modifier si besoin. C'est donc une alternative tout à fait intéressante pour simplifier l'écriture des pages web.</p>
<h2>2. Ne réduisez pas ce html.</h2>
<p>Ne pas réduire le code html présente deux grands avantages :</p>
<ul>
<li>simplifier le processus de mise en place du site web ;</li>
<li>simplifier la lecture du code par être humain.</li>
</ul>
<p>La simplification du code est en effet une étape qui est le plus souvent superflue vu le gain effectif de concernant la taille des fichiers, dès lors que ceux-ci ne contiennent pas des quantités de commentaires. En revanche, l'argument de la lecture facilité du code est trop léger. En effet, tous les navigateurs ont aujourd'hui un inspecteur qui permet de visualiser le code html, indenté automatiquement. Ainsi un code html simplifié reste donc préférable.</p>
<h2>3. Préférez maintenir une page plutôt que plusieurs.</h2>
<p>Une unique page sera toujours plus simple à maintenir qu'une multitude de pages. C'est un principe appliqué sur ce site, en deux endroits :</p>
<ul>
<li>il existe une unique page de blog, récapitulant tous les articles, sans classement autre que l'ordre chronologique ;</li>
<li>le fil rss est un unique fichier xml, qui reprend tous les articles et leurs contenus.</li>
</ul>
<p>Il est cependant des cas où une multitude de pages est préférable, comme pour un blog avec différents articles, figés dans un certain état, donc sans maintenance à prévoir.</p>
<h2>4. Mettez fin à toutes les formes de liaison automatique (hotlinking).</h2>
<p>Utiliser sur son site des ressources présentes sur d'autres sites n'est généralement pas une bonne idée. En effet, si un site tombe ou s'il ferme dans préavis, la ressource que vous utilisiez devient inaccessible. C'est un risque, et une fois la ressource perdue, elle peut être difficile à récupérer.</p>
<p>Il faut ajouter que si vos internautes récupèrent des ressources extérieures à votre site, ils vont laisser des traces sur d'autres serveurs que le vôtre, et donc accroître les traces qu'ils laissent lors de leur navigation.</p>
<p>Aussi, des traqueurs comme Google Analytics sont effectivement inutiles, il n'est pas souhaitable de fournir à Google ou à une autre société l'historique des visites que vous recevez.</p>
<h2>5. N'utilisez que les 13 polices de caractères adaptées au Web.</h2>
<p>Si l'idée du site web que vous avez est bien d'informer un public, il faut rendre le site le moins distrayant et le plus lisible possible. L'idéal est donc d'utiliser des polices bien connues, idéalement déjà présentes sur l'ordinateur de l'internaute. À ce titre, ce site web applique à la lettre ce point.</p>
<h2>6. Compressez vos images de manière obsessionnelle.</h2>
<p>Si vous avez un site web statique et que vous observez la distribution de la taille des fichiers par type d'extension, vous vous apercevrez que les images pèsent très lourd par rapport au texte. Les compresser permet d'économiser de la bande passante, et d'accélérer l'affichage des pages sur le navigateur de l'internaute.</p>
<p>Les formats recommandés sont jpg pour les vraies photographies, svg pour les dessins qui vectoriels et png pour les images ayant de grands aplats de couleur uniformes. Il n'empêche que faire quelques tests permet d'ajuster sa politique de compression des images.</p>
<p>Jeff Huang soulève malgré tout un point intéressant : si en Europe nous sommes habitués à avoir des forfaits illimités en termes de données mobiles ou fixes, il est des parties du monde, comme les États-Unis, où chaque mégaoctet coûte à l'utilisateur final. C'est donc un point très important à prendre en compte.</p>
<h2>7. Éliminez le risque de rupture d'URL.</h2>
<p>Si on souhaite garder un site web en vie pendant une longue période, il est en effet prudent de mettre en place un système permettant de contrôler l'accessibilité du site régulièrement. On peut alors utiliser un service externe, un serveur ou un petit script qui s'exécute régulièrement sur la machine du mainteneur du site.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-10-cgi-et-python.html</guid>
<link>https://www.dioptre.fr/blog/2020-10-cgi-et-python.html</link>
<pubDate>Fri, 28 Aug 2020 00:00:00 +0000</pubDate>
<title>CGI et python</title>
<description><![CDATA[
<h1>CGI et python</h1>
<h2>Site statique et site dynamique</h2>
<p>Comme discuté dans les <a href="https://www.dioptre.fr/blog/2020-2-ssg5-generateur-de-site-statique.html">articles précédents</a>, les sites statiques présentent bien des avantages par rapport aux sites dynamiques. Mais il est des situations où il faut avoir un minimum d'interactivité ou une action du côté serveur est requise. Plusieurs approches peuvent être considérées, mais il s'agit toujours d'écrire un programme qui sera capable d'avoir un comportement donné en fonction des données transmises par l'utilisateur.</p>
<p>Le besoin conduisant à cet article est le suivant : déposer des fichiers sur un serveur par l'intermédiaire d'un formulaire contenu dans une page html. Pour des raisons de sécurité, il y a un ensemble de données à vérifier, comme la taille du fichier reçu, la validité du nom du fichier, et il est également intéressant de contrôler dans quel répertoire le fichier sera écrit.</p>
<p>Un site statique composé exclusivement de pages html ne pouvant fournir un tel comportement, il faut alors inclure une page dynamique et un programme qui pourra s'adapter aux données fournies par l'utilisateur.</p>
<h2>Formulaire dans une page html</h2>
<p>Pour transmettre des informations, le plus simple est d'utiliser un formulaire dans lequel l'utilisateur pourra entrer des informations à destination du serveur. Un cours complet sur la syntaxe d'un fichier html n'entrant pas dans l'objet de cet article, le lecteur débutant pourra se reporter au <a href="https://fr.wikibooks.org/wiki/Le_langage_HTML">wikibook</a> portant sur ce sujet.</p>
<p>Vu que les données reçues par le serveur vont contenir un fichier, il faut indiquer dans le formulaire que les données reçues peuvent être quelconques avec <code>enctype="multipart/form-data"</code>. Le fichier ayant de bonnes chances d'être volumineux, il faut privilégier la méthode de transfert de données post plutôt que get. Il s'agit ensuite de placer un champ input de type file donnant un bouton qui permet de sélectionner un fichier, puis un second champ input de type submit pour envoyer le formulaire au serveur. Si on regroupe toutes ces informations, on aboutit à l'exemple minimal suivant :</p>
<pre><code>&lt;form action="cible.py" method="post" enctype="multipart/form-data"&gt;
&lt;p&gt;Votre fichier :
&lt;input type="file" name="myfile" /&gt;&lt;br /&gt;
&lt;input type="submit" value="Envoyer" /&gt;&lt;/p&gt;
&lt;/form&gt;
</code></pre>
<h2>Common Gateway Interface (CGI)</h2>
<p>La <a href="https://fr.wikipedia.org/wiki/Common_Gateway_Interface">Common Gateway Interface</a> est une interface permettant au serveur web de transmettre des données à un programme, ici appelé cible.py, puis de récupérer les données fournies par celui-ci. C'est un standard indépendant du langage de programmation du programme cible.</p>
<p>On comprend alors que ce mode de fonctionnement permet d'obtenir l'interactivité manquant aux sites purement statiques.</p>
<h2>Python et programmation web</h2>
<p>Le programme cible.py sera un programme python. Dans l'absolu, celui-ci pourrait être écrit en php, en C, en bash ou n'importe quel autre langage, mais il est généralement conseillé de choisir un langage de programmation avec lequel on est à l'aise.</p>
<p>Python n'est pas le langage de choix pour faire une application web, mais ce langage présente l'avantage d'être simple et puissant, et il inclut une <a href="https://docs.python.org/3.8/library/cgi.html">bibliothèque cgi</a> permettant de prendre en charge la réception des données par l'interface CGI.</p>
<h2>Premières considérations pour utiliser python avec CGI</h2>
<p>Comme tout programme python, il commencera par les deux lignes suivantes, pour indiquer le chemin vers le binaire et l'encodage du fichier.</p>
<pre><code>#!/usr/bin/python3
# -*- coding: utf-8 -*-
</code></pre>
<p>Pour récupérer les données du formulaire, on utilise la bibliothèque cgi :</p>
<pre><code>import cgi
form = cgi.FieldStorage()
</code></pre>
<p>La variable form contiendra alors toutes les données fournies par le serveur web.</p>
<p>Ayant à gérer les lettres accentuées, il faut s'assurer que toutes les données seront encodées avec utf-8 :</p>
<pre><code>import codecs
import sys
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
</code></pre>
<p>Une différence majeure avec l'écriture d'une simple page html est la construction du header de la requête. En effet, avec un site dynamique, il est possible de contrôler le contenu de ce dernier, et il faut en particulier préciser quel sera le contenu fourni par le programme. Ici, ce sera une page html :</p>
<pre><code>print("Content-type: text/html\n")
</code></pre>
<p>La ligne vide ajoutée ici est celle qui sépare le header du code html à proprement parler.</p>
<p>Pour faciliter le débogage du programme, il peut être utile d'afficher les traces des exceptions dans la page html. Ces lignes devront être commentées lors de la mise en production du site, car elles peuvent fournir des informations sur le code exécuté sur le serveur.</p>
<pre><code>import cgitb
cgitb.enable()
</code></pre>
<p>Il est à noter qu'il faut d'abord terminer le header puis exécuter la commande permettant d'afficher les traces, sans quoi rien ne s'affichera sur l'écran.</p>
<p>Une fois ces considérations prises en compte, il ne reste plus qu'à construire un programme mettant en œuvre les vérifications d'usage et s'assurer du bon comportement du programme dans toutes les situations.</p>
<h2>Quelques commandes intéressantes pour construire le programme</h2>
<p>Pour récupérer une variable qui serait transmise par l'utilisateur, il est possible d'employer la commande ci-dessous. Il faudrait alors ajouter un champ dans lequel l'utilisateur peut entrer une donnée.</p>
<pre><code>variable = form.getvalue("variable")
</code></pre>
<p>Les données liées au fichier fourni peuvent être stockées dans une variable fileitem :</p>
<pre><code>fileitem = form["myfile"]
</code></pre>
<p>Ensuite, ce fichier peut être écrit sur le disque à l'emplacement <code>path/filename</code> à l'aide de l'unique ligne :</p>
<pre><code>open("{}/{}".format(path, filename), 'wb').write(fileitem.file.read())
</code></pre>
<p>Il faudra à la fin de l'exécution du script afficher un retour à l'utilisateur. Une méthode pour faire cela est d'afficher sur son écran une page html, dont le message dépendra de la réussite ou de l'échec du transfert de données par exemple :</p>
<pre><code>print("""&lt;!DOCTYPE html&gt;
&lt;html lang="fr"&gt;
&lt;head&gt;
&lt;meta charset="utf-8" /&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1" /&gt;
&lt;title&gt;Titre de la page&lt;/title&gt;
&lt;link rel="stylesheet" type="text/css" href="https://www.dioptre.fr/style.css" /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;{}&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.dioptre.fr/"&gt;Retour&lt;/a&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;""".format(message))
</code></pre>
<p>Il faut noter que si cette page affiche des données fournies par l'utilisateur, il est indispensable de se protéger contre la faille XSS. Cela est possible en transformant tous les symboles &lt; > &amp; " qui pourraient être interprétés comme du code html par le navigateur. La bibliothèque html fournit une commande permettant de faire cela simplement :</p>
<pre><code>import html
html.escape("chaine de caractère fournie par l'utilisateur")
</code></pre>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-8-langage-markdown.html</guid>
<link>https://www.dioptre.fr/blog/2020-8-langage-markdown.html</link>
<pubDate>Fri, 14 Aug 2020 00:00:00 +0000</pubDate>
<title>Langage markdown</title>
<description><![CDATA[
<h1>Langage markdown</h1>
<h2>Premières considérations</h2>
<p>Le langage markdown a été créé en 2004 par John Gruber. Il a pour but premier de rendre l'édition des pages web plus simple, en remplaçant la très lourde syntaxe html par celle plus légère de markdown.</p>
<p>C'est un langage de balisage léger, qui n'a pas connu d'évolution depuis sa création, et qui n'a jamais été standardisé. Aujourd'hui, un grand nombre de syntaxes coexistent et la génération d'une page web à l'aide d'un compilateur markdown peut donner un résultat surprenant s'il n'a pas été prévu pour la syntaxe employée lors de la rédaction du fichier markdown. C'est aujourd'hui un véritable problème, sans qu'une syntaxe particulière prenne le pas sur les autres à l'heure actuelle. Signalons tout de même l'initiative <a href="https://commonmark.org/">CommonMark</a> qui vise à proposer une syntaxe standardisée, qui est assez largement adoptée aujourd'hui.</p>
<p>Cet article s'appuie sur la version vanilla de markdown, telle que décrite par Gruber sur son <a href="https://daringfireball.net/projects/markdown/">site</a>, mais tout ce qui est décrit ici s'applique également à la syntaxe CommonMark.</p>
<h2>Code de la cheatsheet markdown</h2>
<p>On dresse alors une cheatsheet minimale, qui sera compilée ci-après.</p>
<pre><code># Premier titre

## Deuxième niveau de titre

Un paragraphe est précédé d'une ligne vide.
Il est possible d'écrire en _italique_, en **gras** et avec une police `monospace` et d'ajouter des [liens](https://www.dioptre.fr/).

    Bloc de code
    print("Hello world!")

Une liste est faite avec la syntaxe :

- premier objet ;
- deuxième objet,

et une liste ordonnée se construit ainsi :

1. premier objet ;
1. deuxième objet.

Une image peut être insérée dans la page par une ligne de code html:

&lt;img src="https://www.dioptre.fr/img/2-markdown-mark.svg" alt="Texte alternatif" title="Logo Markdown" class="img-responsive" /&gt;

[commentaire]: &lt;&gt; (Ce texte ne sera pas affiché !)
</code></pre>
<h2>Rendu de la cheatsheet markdown</h2>
<p>On a alors le résultat :</p>
<h1>Premier titre</h1>
<h2>Deuxième niveau de titre</h2>
<p>Un paragraphe est précédé d'une ligne vide.
Il est possible d'écrire en <em>italique</em>, en <strong>gras</strong> et avec une police <code>monospace</code> et d'ajouter des <a href="https://www.dioptre.fr/">liens</a>.</p>
<pre><code>Bloc de code
print("Hello world!")
</code></pre>
<p>Une liste est faite avec la syntaxe :</p>
<ul>
<li>premier objet ;</li>
<li>deuxième objet,</li>
</ul>
<p>et une liste ordonnée se construit ainsi :</p>
<ol>
<li>premier objet ;</li>
<li>deuxième objet.</li>
</ol>
<p>Une image peut être insérée dans la page par une ligne de code html:</p>
<p><img src="https://www.dioptre.fr/img/2-markdown-mark.svg" alt="Texte alternatif" title="Logo Markdown" class="img-responsive" /></p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-6-generation-d-un-site-statique-avec-gitlab-ci-cd.html</guid>
<link>https://www.dioptre.fr/blog/2020-6-generation-d-un-site-statique-avec-gitlab-ci-cd.html</link>
<pubDate>Fri, 31 Jul 2020 00:00:00 +0000</pubDate>
<title>Génération d'un site statique avec Gitlab CI-CD</title>
<description><![CDATA[
<h1>Génération d'un site statique avec Gitlab CI-CD</h1>
<h2>Étapes de la génération d'un site statique</h2>
<p>Les sites statiques sont générés par des programmes, assez simples, comme Hugo, Pelican ou, dans le cas qui nous concerne, ssg5. Tout l'intérêt est de dissocier l'étape de génération des pages de leur mise à disposition par un serveur web.</p>
<p>Pour effectuer cette étape, il est nécessaire de disposer d'un ordinateur possédant l'environnement adéquat, dépendant du générateur choisi. Il faut ensuite rendre le résultat disponible aux internautes. Le choix fait ici est d'utiliser un hébergement mutualisé d'un grand nom européen, mais d'autres options peuvent être retenues.</p>
<p>Il est possible d'utiliser l'ordinateur du blogueur pour faire ces deux opérations, mais cela n'est pas le choix qui a été fait ici. En effet, si plusieurs contributeurs veulent rédiger des articles, ou si un rédacteur unique utilise plusieurs ordinateurs, comment s'assurer que toutes les personnes et toutes les machines ont la dernière version du code ?</p>
<h2>Suivi de version par git et Gitlab</h2>
<p>Dans une optique de suivi des modifications apportées au présent site web et d'uniformisation des versions du site existantes, un gestionnaire de suivi de version est utilisé, c'est git. Un article futur traitera de ce logiciel très utile aux personnes manipulant du code, mais nous ne saurions que recommander la <a href="https://www.youtube.com/watch?v=rP3T0Ee6pLU&amp;list=PLjwdMgw5TTLXuY5i7RW0QqGdW0NZntqiP">série de vidéos</a> de Grafikart sur le sujet.</p>
<p>Pour rendre le code disponible au plus grand nombre, le choix a été fait de déposer le dépôt git sur une plateforme publique : <a href="https://framagit.org/">framagit</a>. C'est une instance Gitlab hébergée par <a href="https://framasoft.org/">Framasoft</a> dans le cadre de la campagne Dégooglisons Internet. Il est en revanche difficile de conseiller d'héberger son code sur cette plateforme, vu qu'elle sera probablement prochainement abandonnée par l'association.</p>
<p>Les trois grands avantages de ce choix sont les suivants :</p>
<ul>
<li>une ouverture du code du site web si le dépôt est public ;</li>
<li>la possibilité de générer le site statique directement sur un serveur, appelé runner ;</li>
<li>la possibilité d'héberger le site ainsi généré via un système appelé Gitlab Pages, dont le fonctionnement ne sera pas développé ici.</li>
</ul>
<h2>Compilation et déploiement d'un site web statique par un runner</h2>
<h3>Fichier <code>gitlab-ci.yml</code></h3>
<p>Un runner est un serveur qui est capable d'exécuter une succession de travaux dans un environnement préalablement choisi. La configuration des opérations, appelées jobs, prend place dans un fichier <code>.gitlab-ci.yml</code> placé à la racine du dépôt. Celui du présent site peut être trouvé sur <a href="https://framagit.org/hummingbird/dioptre/-/blob/master/.gitlab-ci.yml">framagit</a>. La version sur laquelle s'appuie cet article correspond au <a href="https://framagit.org/hummingbird/dioptre/-/blob/378b2bd04189a3e78756897c6c5654551eec5c7a/.gitlab-ci.yml">commit 378b2bd0</a>.</p>
<p>L'environnement retenu ici est celui de la dernière version de la distribution Alpine Linux, qui présente un immense avantage sur les autres environnements : sa petite taille. En effet, à chaque fois que le runner se lance, il récupère l'image Docker choisie, et plus celle-ci est petite, mieux c'est. Celle choisie ici a une taille de l'ordre de 5 Mo, bien plus faible que celle des grandes distributions GNU/Linux comme Arch, Ubuntu ou Debian. À ce titre, on pourra se référer à la <a href="https://enix.io/fr/blog/cherie-j-ai-retreci-docker-part1/">série d'articles</a> d'Enix sur le sujet. Ainsi, on indique au début du fichier :</p>
<pre><code>image: alpine:latest
</code></pre>
<p>Il est ensuite possible de définir des jobs, qui se construisent comme un script shell. Ici, il y a deux jobs, en lien avec deux étapes du processus, dites stages. Ces deux étapes sont build et deploy qui correspondent aux étapes de génération et de déploiement du site sur son hébergement. On a alors les deux étapes :</p>
<pre><code>stages:
  - build
  - deploy
</code></pre>
<h3>Job de génération du site statique</h3>
<p>Le premier job reprend les étapes de construction du site, avec les appels aux programmes brg, ssg5 et smc. Quelques lignes du fichier <code>.gitlab-ci.yml</code> sont néanmoins remarquables. Les premières concernent l'internationalisation d'Alpine Linux. En effet, par défaut, cette distribution n'embarque pas les différentes locales dont peut avoir besoin un utilisateur non anglophone. Ici, nous avons besoin de la locale <code>fr_FR.UTF-8</code>. Pour cela, on installe le package <code>musl-locales</code> et on exporte les variables permettant de définir cette nouvelle locale comme celle à utiliser :</p>
<pre><code>apk add --no-cache musl-locales
export MUSL_LOCPATH=/usr/share/i18n/locales/musl
export LANG=fr_FR.UTF-8
</code></pre>
<p>Ensuite, le site est généré à l'aide des scripts détaillés dans les articles précédents.</p>
<pre><code>mkdir -p dst fin
./bin/brg src/blog 'https://www.dioptre.fr' 'https://www.dioptre.fr/blog'
./bin/ssg5 src dst "www.dioptre.fr" "https://www.dioptre.fr"
./bin/smc dst fin
</code></pre>
<p>Aussi, ce job crée un artifact. Un artifact est une archive contenant un certain nombre de répertoires ou fichiers dont l'utilisateur pense avoir besoin pour la suite de l'exécution du processus. Ici, les deux répertoires conservés à la fin de l'exécution du job sont <code>dst</code> et <code>fin</code>, correspondant respectivement aux répertoires de création du site et celui qui sera finalement téléversé sur l'hébergement mutualisé. On lui attribue une durée de vie ; il est inutile de le garder trop longtemps :</p>
<pre><code>artifacts:
  paths:
  - dst
  - fin
  expire_in: 1 day
</code></pre>
<h3>Déploiement du site sur un hébergement mutualisé</h3>
<p>Cet artifact est ensuite utilisé dans le job suivant, le contenu du répertoire <code>fin</code> étant prêt à être téléversé sur l'hébergement du site. Il faut alors indiquer que ce job dépend du présent et de son artifact :</p>
<pre><code>dependencies:
  - build_site
</code></pre>
<p>Il est également précisé que cette étape de déploiement ne doit être effectuée que si la branche est master. Cela est utile dans le cas où une autre branche serait créée, comme une branche de développement. En effet, il n'est pas conseillé de placer en production un site qui peut ne pas être stable. Ainsi, le développement particulier se fera sur une branche spécifique, qui ne sera jamais visible par l'internaute.</p>
<pre><code>only:
  - master
</code></pre>
<p>Le déploiement du site se fait via rsync avec une connexion ssh à l'aide d'une clé RSA. Il est nécessaire de l'ajouter aux fichiers de configuration du runner pour qu'il puisse se connecter au serveur distant. Or, cette clé est un fichier sensible qu'il faut protéger. Il est possible de l'ajouter aux variables du processus dans l'interface en ligne de Gitlab, pour que son contenu soit inaccessible aux personnes extérieures. On ajoute également les informations qui permettent d'identifier le serveur distant à <code>~/.ssh/known_hosts</code>. Les différents fichiers étant sensibles, on ajuste leurs permissions.</p>
<pre><code>apk add --no-cache openssh-client
eval $(ssh-agent -s)
echo "$SFTPKEY" | tr -d '\r' | ssh-add -
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "$SSHKNOWNHOSTS" &gt;&gt; ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
</code></pre>
<p>Enfin, le runner assure la synchronisation du répertoire <code>fin</code> avec celui du répertoire distant à l'aide de l'utilitaire rsync. Le fichier <code>.files</code>, créé par ssg5 n'est pas nécessaire au bon fonctionnement du site, il est donc ignoré.</p>
<pre><code>rsync -aczv --no-t --rsh='ssh' --delete-excluded --exclude='.files' fin/ "$DEPLOYDST"
</code></pre>
<p>Notons que le premier job peut être redémarré une fois en cas d'erreur, le second deux fois. Cela est particulièrement pertinent dans le cas du second job, pour lequel la connexion ssh peut échouer sans raison apparente. Pour que la nouvelle version du site soit effectivement déployée, il est utile que ce job puisse être relancé un peu plus tard.</p>
<h3>Dépendances des programmes et performances</h3>
<p>Avoir un temps d’exécution court était un des prérequis lors de la construction de ce processus de génération et de déploiement. En effet, cela permet de s’assurer rapidement qu’il n’y a pas eu d’erreur lors de l’exécution et que le site est bien déployé.</p>
<p>Cela justifie en particulier le choix de s’appuyer uniquement sur des scripts compatibles POSIX. Le shell embarqué par défaut dans Alpine Linux est ash. C’est un shell très rapide et minimaliste, compatible POSIX. Si un autre shell est requis pour l’exécution du processus, il faudra le télécharger et l’installer, ce qui prendra du temps. Aussi, le fait de s’appuyer sur un ensemble de script permet de limiter de nombre de dépendances et donc le nombre de logiciels à installer.</p>
<p>Dans l'état actuel des choses, l'exécution du processus ainsi exposé prend moins de 30 secondes. Cela est jugé satisfaisant.</p>
<p>Pour accélérer le processus, il serait possible :</p>
<ul>
<li>d'écrire directement les articles en html, de manière à enlever la dépendance liée au langage markdown ;</li>
<li>de déployer le site sur Gitlab Pages pour éliminer le déploiement sur un stockage distant avec ssh et rsync.</li>
</ul>
<h3>Documentation du fichier <code>.gitlab-ci.yml</code></h3>
<p>On pourra se reporter à la <a href="https://docs.gitlab.com/ee/ci/yaml/">très bonne documentation</a> (en anglais) fournie par Gitlab au sujet de la construction du fichier <code>.gitlab-ci.yml</code> pour plus d'informations. Il est également intéressant de lire la page dédiée au <a href="https://docs.gitlab.com/ee/ci/">processus d'intégration continue</a> et aux <a href="https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html">artifacts</a>.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-5-compression-et-minification-d-un-site-statique-avec-smc.html</guid>
<link>https://www.dioptre.fr/blog/2020-5-compression-et-minification-d-un-site-statique-avec-smc.html</link>
<pubDate>Fri, 24 Jul 2020 00:00:00 +0000</pubDate>
<title>Compression et minification d'un site statique avec smc</title>
<description><![CDATA[
<h1>Compression et minification d'un site statique avec smc</h1>
<h2>Étude d'un site créé par ssg5</h2>
<p>ssg5 crée un site web composé de pages au format html, accompagnées au besoin d'une ou plusieurs feuilles de style css. Ces fichiers sont généralement assez petits, mais nombreux. ssg5 crée également une carte du site au format xml, et rssg ou brg génèrent un fil RSS également au format xml. Ces deux fichiers deviennent vite volumineux avec l'augmentation du nombre de page du site.</p>
<p>Ces fichiers ont tous un point commun : ils contiennent des informations qui se répètent, leur compression apportera un gain important en termes de taille. Aussi, ils peuvent contenir des caractères non indispensables à leur interprétation par un navigateur, comme des tabulations d'indentation ou des commentaires, il peut donc être utile de les supprimer avant de les téléverser sur le serveur assurant leur mise à disposition sur le web.</p>
<p>Au bilan, on retiendra que les fichiers créés par ssg5 contiennent des informations non indispensables et qu'ils peuvent être facilement compressés.</p>
<h2>Une minification a minima</h2>
<p>La <a href="https://fr.wikipedia.org/wiki/Minification">minification</a> d'un fichier est l'opération visant à éliminer de celui-ci tous les caractères non indispensables. Comme indiqué précédemment, les commentaires et les caractères blancs (espaces, tabulations, sauts de ligne) peuvent être supprimés d'un fichier html, css ou xml sans nuire à l'interprétation de celui-ci par un navigateur web.</p>
<p>Pour effectuer cette opération, deux options s'offrent à nous : utiliser un logiciel dédié à cette tâche ou créer un script basé sur des commandes de base d'un système de type Unix. Dans un objectif de garder les étapes de déploiement les plus simples et les plus rapides possibles, c'est la deuxième option qui est retenue.</p>
<p>Pour minifier un fichier html, on enlèvera les lignes vides, les espaces et tabulations de début et de fin de ligne et les commentaires présents dans le code. Pour cela, on pourra utiliser la commande suivante :</p>
<pre><code>sed -i 's/&lt;\!\-\-.*\-\-&gt;//g;s/^\s*//g;s/\s*$//g;/^$/d' file
</code></pre>
<p>Le même traitement sera appliqué aux fichiers xml, ceux-ci étant basés sur un système de balise proche de celui des fichiers html.</p>
<p>Pour minifier un fichier css, on enlèvera les commentaires et tous les caractères blancs, à l'exception de ceux qui influencent la mise en page du document. On pourra également utiliser une commande sed :</p>
<pre><code>sed -i 's|\/\*.*\*\/||g;:a;N;$!ba;s/\n/ /g;s/\([^a-z0-9]\)\s*/\1/g;s/\s*\([^a-z0-9]\)/\1/g' file
</code></pre>
<p>Les lecteurs attentifs auront vu que les commentaires supprimés ici correspondent uniquement aux commentaires tenant sur une ligne. Les commentaires multilignes seront conservés, mais nous partons du principe que les personnes utilisant ssg5 comme générateur de site statique ne créerons pas de tels commentaires.</p>
<p>Seuls les fichiers d'extension html, xml ou css seront minifiés. Les autres extensions étant moins courantes pour des sites web statiques, elles seront ignorées.</p>
<h2>Pourquoi compresser les pages d'un site statique ?</h2>
<p>Pour servir les pages web le plus rapidement possible, les serveurs web compressent à la volée les pages en fonction des données fournies par le navigateur. C'est une opération qui accroit significativement la charge du serveur web, et qui, pour être efficace, doit trouver le compromis optimal entre vitesse de compression et vitesse de distribution du fichier. En effet, compresser des données demande un temps de calcul non négligeable. Celui-ci augmente si on demande à avoir un meilleur ratio de compression, pour un gain qui sera réduit par rapport à celui déjà obtenu. La vitesse de distribution des données dépend de la vitesse de la connexion internet de l'internaute, et plus le débit est faible, plus la distribution d'une page web sera lente, surtout si celle-ci n'est pas ou peu compressée.</p>
<p>Pour diminuer la charge des serveurs web et pour accélérer les transferts, il est possible de compresser les pages web lors de la création du site statique. Cela présente plusieurs avantages :</p>
<ul>
<li>une diminution de la charge du serveur web qui n'a plus à compresser les données à la volée, il se contente de distribuer les fichiers qu'on lui a fournis ;</li>
<li>une diminution du temps d'attente de la page pour l'internaute, le serveur ayant déjà le contenu demandé compressé ;</li>
<li>une diminution de la taille des pages web compressées, la vitesse de compression n'étant plus un facteur limitant, le temps alloué à la compression des pages peut être allongé ;</li>
<li>une diminution du temps de transfert de l'information, la page web étant plus petite que celle qui aurait été fournie par le serveur sans cette étape.</li>
</ul>
<p>Le site étant statique, le contenu des pages n'est modifié que lors de la génération du site. Cela permet de les compresser qu'une seule fois, lors de la génération du site, et non pas à chaque requête issue du navigateur.</p>
<h2>Compression des données</h2>
<p>Un navigateur web moderne accepte les formats de page compressée gzip et brotli ; une telle page peut être obtenue à l'aide des formats gzip, zopfli et brotli. Le format gzip peut être obtenu avec les commandes <code>gzip</code> et <code>pigz</code>, zopfli avec <code>pigz</code> et brotli avec <code>brotli</code>.</p>
<p>Le format gzip est le plus rapide à produire, c'est également celui qui possède la compatibilité la plus large. Le format zopfli conserve la même compatibilité que celle du format gzip, mais est beaucoup plus lent à produire pour un gain assez limité dans l'essentiel des cas. Le format brotli n'est accepté que par les navigateurs les plus récents depuis 2017 environ. Il est en revanche assez lent à produire pour un <a href="https://damien.pobel.fr/post/precompress-brotli-gzip-static-site/">gain assez faible</a>, et n'est pas compatible avec le format gzip.</p>
<p>Dans un souci de simplicité et de rapidité de génération du site statique, une seule compression sera effectuée. Celle retenue sera donc celle ayant la meilleure compatibilité. Le gain en taille apporté par zopfli par rapport à gzip ne justifie pas le temps de calcul significativement supérieur nécessaire à la compression. La solution retenue sera donc gzip, avec la meilleure compression possible, uniquement pour les fichiers de plus de 300 octets :</p>
<pre><code>test "$(stat -c %s file)" -ge 300 &amp;&amp; gzip -9 &lt; file &gt; file.gz
</code></pre>
<p>Cette valeur a été choisie arbitrairement, en pensant au fait que la compression d'un fichier extrêmement petit, de l'ordre de quelques dizaines d'octets, augmente sa taille au lieu de la réduire.</p>
<h2>smc, un utilitaire de minification et de compression pour les sites statiques</h2>
<p>smc (static minification and compression) est l'utilitaire créé pour automatiser les étapes de minification et de compression discutées précédemment. C'est un court script compatible POSIX, traitant les fichiers html, xml, css, js et svg. Il n'a pas de dépendance particulière, si ce n'est les utilitaires de base comme sed, find et gzip. Il peut donc être exécuté sur toute machine de type Unix.</p>
<p>Ce script attend deux arguments :</p>
<ul>
<li>un répertoire source, noté <code>src</code> contenant les pages html générées par ssg5 par exemple ;</li>
<li>un répertoire de destination, noté <code>dst</code>.</li>
</ul>
<p>Le script est librement téléchargeable :</p>
<pre><code>wget https://www.dioptre.fr/bin/smc
</code></pre>
<p>On le rend alors exécutable :</p>
<pre><code>chmod +x smc
</code></pre>
<p>On exécute alors le script sur le site :</p>
<pre><code>smc src dst
</code></pre>
<p>Le répertoire de destination peut alors être téléversé sur le serveur web fournissant le site en question.</p>
<h2>Annexe : Configuration du serveur web</h2>
<p>Pour indiquer à un serveur web qu'il doit fournir un contenu préalablement compressé et pas compresser les pages à la volée, il faut modifier sa configuration courante. Ce site étant hébergé sur un serveur apache mutualisé, le fichier à modifier sera le fichier <code>.htaccess</code> présent à la racine du site web.</p>
<p>Dans ce fichier, il faudra alors détecter si le navigateur demandant la page accepte la compression gzip, et si oui, il faut lui donner la page précédemment compressée si elle existe :</p>
<pre><code>RewriteCond "%{HTTP:Accept-encoding}" "gzip"
RewriteCond "%{REQUEST_FILENAME}\.gz" -s
RewriteRule "^(.*)\.(html|css|js|svg|xml)" "$1\.$2\.gz" [QSA]
</code></pre>
<p>Ensuite, il faut s'assurer que le serveur ne va pas compresser le contenu déjà compressé. On définit pour cela de nouveaux types de fichier, en lien avec les extensions traitées par smc :</p>
<pre><code>RewriteRule "\.html\.gz$" "-" [T=text/html,E=no-gzip:1]
RewriteRule "\.css\.gz$" "-" [T=text/css,E=no-gzip:1]
RewriteRule "\.js\.gz$"  "-" [T=text/javascript,E=no-gzip:1]
RewriteRule "\.svg\.gz$"  "-" [T=image/svg+xml,E=no-gzip:1]
RewriteRule "\.xml\.gz$"  "-" [T=application/xml,E=no-gzip:1]
</code></pre>
<p>Enfin, il faut indiquer au navigateur que le fichier est compressé et forcer les mandataires à mettre en cache les fichiers compressés ou non à part :</p>
<pre><code>&lt;FilesMatch "(\.html\.gz|\.css\.gz|\.js\.gz|\.svg\.gz|\.xml\.gz)$"&gt;
    Header append Content-Encoding gzip
    Header append Vary Accept-Encoding
&lt;/FilesMatch&gt;
</code></pre>
<p>Pour plus de détails, on pourra se reporter à la <a href="https://httpd.apache.org/docs/2.4/mod/mod_deflate.html#precompressed">documentation</a> d'apache.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-4-generer-un-index-de-blog-et-un-fil-rss-avec-brg.html</guid>
<link>https://www.dioptre.fr/blog/2020-4-generer-un-index-de-blog-et-un-fil-rss-avec-brg.html</link>
<pubDate>Fri, 17 Jul 2020 00:00:00 +0000</pubDate>
<title>Générer un index de blog et un fil RSS avec brg</title>
<description><![CDATA[
<h1>Générer un index de blog et un fil RSS avec brg</h1>
<h2>Une limite de ssg5</h2>
<p>Une des limites de ssg5 est l'absence totale d'outil pour construire automatiquement un blog. Construire l'index des articles publiés est une action qui est pourtant absolument nécessaire et qui peut être rébarbative si le contenu du blog s'étoffe rapidement.</p>
<p>brg (blog and RSS generator) est un logiciel permettant de générer cet index, en regroupant la totalité des articles publiés, et de produire un fil RSS auquel les lecteurs peuvent s'abonner. La combinaison des deux logiciels, ssg5 et brg, donne alors un système autonome, capable de construire un site web statique contenant un blog.</p>
<h2>Philosophie de brg</h2>
<p>brg est un script shell, compatible POSIX, qui tient en moins de 220 lignes de code. Il est adapté à mon usage, à savoir la compilation de ce site avec une machine ayant Alpine Linux comme système d'exploitation. Il pourrait fonctionner avec BSD moyennant une modification mineure concernant la syntaxe de la commande <code>date</code>.</p>
<p>Il s'inspire de <a href="https://www.romanzolotarev.com/rssg.html">rssg</a> pour la génération du fil RSS, un utilitaire développé par Roman Zolotarev, l'auteur de ssg5.</p>
<p>brg est donc un logiciel simple, supposément rapide, ayant les mêmes dépendances que ssg5, à savoir Markdown.pl si les articles du blog sont écrits en markdown.</p>
<h2>Prérequis à l'utilisation de brg</h2>
<p>brg s'attend à trouver dans un répertoire :</p>
<ul>
<li>des articles de blog au format markdown ou html dont le nom est composé de l'année de rédaction et du numéro de l'article dans cette année ;</li>
<li>ces articles doivent contenir deux métadonnées : le titre de l'article et sa date de publication ;</li>
<li>un fichier <code>_brg.md</code> contenant un titre qui deviendra le titre de la page d'index du blog et le titre du fil RSS ;</li>
<li>ce fichier <code>_brg.md</code> doit également contenir au moins un paragraphe, ce premier paragraphe devenant la description du fil RSS.</li>
</ul>
<p>Cet article aura alors le nom de fichier et les deux métadonnées suivantes :</p>
<pre><code>head -2 2020-4-generer-un-index-de-blog-et-un-fil-rss-avec-brg.md
[title]: &lt;&gt; (Générer un index de blog et un fil RSS avec brg)
[date]: &lt;&gt; (2020-07-17)
</code></pre>
<p>C'est le quatrième article de l'année 2020, intitulé « Générer un index de blog et un fil RSS avec brg », publié le 17 juillet 2020. Il est à noter que les deux dernières lignes sont des commentaires markdown, ils ne seront donc pas compilés lors de la création des fichiers html par ssg5. Notons également que le compilateur choisi dans le cas présent est Markdown.pl. Si le choix du compilateur change, il sera alors utile de se <a href="https://stackoverflow.com/questions/4823468/comments-in-markdown">renseigner</a> sur la meilleure manière de créer un commentaire dans un fichier markdown.</p>
<p>Le fichier <code>_brg.md</code> contiendra, dans le cas présent, les lignes suivantes :</p>
<pre><code># Les dernières nouvelles sur dioptre.fr

Ici sont regroupés les derniers articles publiés sur dioptre.fr.

Vous pouvez vous abonner au fil [RSS](http://www.dioptre.fr/blog/rss.xml).
</code></pre>
<p>La première ligne contient le titre qui deviendra le titre de la page d'index et le titre du fil RSS, la seconde deviendra la description du fil RSS et la troisième apparaitra uniquement dans la page d'index, comme le montrent l'<a href="https://www.dioptre.fr/blog">index</a> et le <a href="https://www.dioptre.fr/blog/rss.xml">fil RSS</a> de ce site.</p>
<p>Les sources de ce site et en particulier du blog sont <a href="https://framagit.org/hummingbird/dioptre/">disponibles</a>, à titre d'exemple.</p>
<h2>Utilisation de brg</h2>
<p>Le script est librement téléchargeable :</p>
<pre><code>wget https://www.dioptre.fr/bin/brg
</code></pre>
<p>On le rend alors exécutable :</p>
<pre><code>chmod +x brg
</code></pre>
<p>Lors de l'exécution, la commande attend deux ou trois arguments :</p>
<ul>
<li>le répertoire qui contient les articles de blog et le fichier <code>_brg.md</code> ;</li>
<li>l'url complète du site ;</li>
<li>l'url complète du blog, où se trouvera son index.</li>
</ul>
<p>Si l'url du site est identique à celle du blog, le troisième argument est superflu.</p>
<p>Pour ce site, la commande requiert les trois arguments, le site complet se trouvant dans le répertoire <code>src</code> et le blog dans le répertoire <code>src/blog</code> :</p>
<pre><code>brg src/blog 'https://www.dioptre.fr' 'https://www.dioptre.fr/blog'
</code></pre>
<p>Le script produira alors deux fichiers dans <code>src/blog</code>, un index <code>index.md</code> et un fichier contenant le fil RSS <code>rss.xml</code>.</p>
<p>Pour générer le site, on peut ensuite faire appel à ssg5, il compilera les pages statiques du site, les articles de blog et l'index de ce dernier, tout en ignorant le fichier <code>_brg.md</code>.</p>
<p>Pour faciliter la détection du fil RSS par les navigateurs, il est utile d'ajouter son lien au fichier <code>_header.html</code> utilisé par ssg5 pour la compilation des pages du site :</p>
<pre><code>&lt;link rel="alternate" type="application/atom+xml" href="https://www.dioptre.fr/blog/rss.xml"&gt;
</code></pre>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-3-les-scripts-et-la-norme-posix.html</guid>
<link>https://www.dioptre.fr/blog/2020-3-les-scripts-et-la-norme-posix.html</link>
<pubDate>Fri, 10 Jul 2020 00:00:00 +0000</pubDate>
<title>Les scripts et la norme POSIX</title>
<description><![CDATA[
<h1>Les scripts et la norme POSIX</h1>
<h2>Un petit point historique</h2>
<p>La famille des systèmes Unix est grande, mais ce n'est rien comparé à sa taille dans les années 80. À cette époque, de grandes sociétés se font face et proposent chacune une version d'Unix, avec leurs spécificités. Cela a entrainé une perte de la portabilité des applications d'une plateforme à une autre.</p>
<p>Une norme fut alors proposée par l'IEEE en 1988, la norme POSIX pour Portable Operating System Interface. Elle avait donc pour objectif de normaliser les comportements des briques essentielles de chaque système comme le shell, permettant ainsi de retrouver une forme de portabilité des applications. Les différents systèmes pouvaient et peuvent toujours être certifiés compatibles POSIX.</p>
<p>Cependant, cette certification coutant cher et la documentation liée à ce standard n'étant pas publique, une autre norme a émergé, la norme SUS Single Unix Specification. Aujourd'hui, c'est la version 3 de cette norme qui est en vigueur, et elle présente les grands avantages d'avoir intégré le contenu de la norme POSIX et d'être disponible librement.</p>
<p>Il est donc intéressant, aussi souvent que possible, d'écrire des scripts shells compatibles avec la norme POSIX, de manière à pouvoir les partager largement.</p>
<h2>Shells et systèmes d'exploitation</h2>
<p>Aujourd'hui, les shells les plus courants sont bash, zsh, fish, ksh, etc. Ils sont nombreux, et une grande partie d'entre eux sont dits compatibles POSIX. Tous ont leurs spécificités, ils pourront alors exécuter des applications qui respectent ce standard. Fish est le seul shell de cette liste qui n'est pas compatible POSIX.</p>
<p>Ces shells sont disponibles sur de nombreux systèmes d'exploitation, comme GNU/Linux, FreeBSD, OpenBSD, macOS et dans une certaine mesure Windows avec WSL. Comprenons ainsi qu'une telle application compatible pourra être exécutée sur toutes les plateformes, sans adaptation ou presque.</p>
<p>Il faut maintenant parler des performances de ces différents shells. Bien entendu, ayant à faire à un langage interprété, les performances ne seront pas au niveau d'un langage compilé. En revanche, tous les shells n'offrent pas la même réactivité. Sur les systèmes basés sur Debian, deux shells sont installés par défaut : bash pour la partie interactive dans un terminal, dash pour l'exécution des scripts. Dash, Debian Almquist Shell, est un shell qui n'intègre que les fonctionnalités liées à la norme POSIX et permet donc d'avoir de meilleures performances qu'avec bash. Ce gain en performance se paye par une souplesse moindre, c'est donc pour cela que le choix de conserver bash comme shell interactif a été fait.</p>
<h2>Scripts et norme POSIX</h2>
<p>Nous avons donc deux bonnes raisons de privilégier les scripts POSIX :</p>
<ul>
<li>avec un système GNU/Linux de type Debian, la performance sera meilleure qu'avec un script bash, non compatible POSIX ;</li>
<li>il sera distribuable et exécutable sur toute machine possédant un shell compatible.</li>
</ul>
<p>Un script POSIX commence par la ligne suivante :</p>
<pre><code>#!/bin/sh
</code></pre>
<p>Cette ligne indique au système d'exploitation le logiciel avec lequel le script doit être exécuté. Ici, le logiciel sera donc <code>/bin/sh</code> qui est généralement un simple lien vers un autre shell, dash sur un système Debian, bash sur un système Arch Linux. À cette commande sont parfois ajoutés quelques arguments qui permettent en particulier de contrôler le comportement du script en cas d'erreur.</p>
<p>Lors de la rédaction d'un script compatible POSIX, il faudra dont prendre soin de n'utiliser que des écritures compatibles. Cela peut être vérifié avec le programme <code>shellcheck</code> qui parcourt l'ensemble du script à la recherche de syntaxes non optimales ou non compatibles POSIX dès lors que la ligne indiquée ci-dessus apparait sur la première ligne de code du script. On pourra se référer à la page <a href="https://github.com/koalaman/shellcheck">GitHub</a> du projet pour plus d'informations.</p>
<h2>La recherche de performance dans les scripts</h2>
<p>Rechercher la meilleure performance possible dans un script shell peut paraitre vain. Pour d'autres, ce point aura une grande importance. Cela dépend de l'utilisation qui sera faite du script. Si ce script est utilisé une fois par jour sur demande de l'utilisateur, cette quête de la performance maximale n'en vaut pas la peine. En revanche, si c'est un script lié à une surveillance d'un système informatique qui est exécuté automatiquement par le système plusieurs fois par seconde, cette recherche de performance est importante.</p>
<p>Pour atteindre cet objectif, il est possible d'appliquer les quelques règles suivantes :</p>
<ul>
<li>utiliser dash comme shell exécutant les scripts compatibles POSIX ;</li>
<li>limiter les appels à des programmes non nécessaires ;</li>
<li>limiter les dépendances des scripts ;</li>
<li>utiliser au maximum les tuyaux (pipes en anglais) pour faire passer des informations d'un programme à un autre.</li>
</ul>
<p>Toutefois, la compréhension des actions d'un programme lors de la lecture de son code pouvant être difficile même pour un utilisateur expérimenté, il faudra toujours privilégier une bonne lisibilité du code à une amélioration des performances du programme.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-2-ssg5-generateur-de-site-statique.html</guid>
<link>https://www.dioptre.fr/blog/2020-2-ssg5-generateur-de-site-statique.html</link>
<pubDate>Fri, 03 Jul 2020 00:00:00 +0000</pubDate>
<title>ssg5, un générateur de site statique</title>
<description><![CDATA[
<h1>ssg5, un générateur de site statique</h1>
<p>Les générateurs de site statique deviennent de plus en plus populaires auprès des blogueurs en quête d’un site web stable et robuste. Les plus connus sont sans nul doute Jekyll et Hugo, et dans une moindre mesure Pelican. Celui que je vais présenter aujourd’hui est <a href="https://www.romanzolotarev.com/ssg.html">ssg5</a>.</p>
<h2>ssg5 en quelques lignes</h2>
<p>ssg5 est un générateur de site statique minimaliste créé et maintenu par Roman Zolotarev, composé d'une bonne centaine de lignes de code shell, compatible POSIX, initialement écrit pour OpenBSD. C'est un outil simple, pour ne pas dire simpliste, qui a pour unique fonction de générer le code html d'une page à partir d'un fichier html ou d'un fichier markdown le cas échéant. Il n'est pas en mesure de générer un fil RSS, de générer une table des matières de billets de blog ou de gérer des thèmes. Cela doit être fait à la main ou par un autre programme utilisé en amont ou en aval de la génération du site.</p>
<p>Une question survient alors : pourquoi privilégier un tel programme, minimaliste en termes de fonctionnalités à des alternatives bien documentées et stables ? Pour ma part, les avantages sont les suivants : grande rapidité d'exécution, création d'un processus de déploiement continu simplifié par le très faible nombre de dépendances, possibilité de comprendre le code en quelques heures, etc. Il faut également noter qu'un tel générateur laisse une latitude appréciable pour générer un site exactement conforme aux souhaits de l'utilisateur, et c'est bien là l'essentiel. Par ailleurs, l'absence de fichier de configuration élimine une étape qui peut être douloureuse dans bien des cas.</p>
<h2>Contenu du répertoire source</h2>
<p>Le répertoire source du site est habituellement appelé src. Il doit contenir deux fichiers, <code>_header.html</code> et <code>_footer.html</code>. Ces deux fichiers écrits en html formeront les parties hautes et basses du code html de chaque page. Le but est ici de créer un entête, un pied de page, de faire les appels aux différents scripts et feuilles de style nécessaires au bon affichage de la page. Un fichier <code>.ssgignore</code> peut être également ajouté pour définir un ensemble de fichiers qui seront ignorés par le programme.</p>
<p>Une fois cela fait, il ne reste plus qu'à créer du contenu. Il est possible de créer un fichier <code>index.md</code> qui sera la page d'accueil de notre site, et toutes les autres pages qui viendront l'enrichir.</p>
<h2>Génération du site, la théorie</h2>
<p>Il est possible de se procurer le binaire sur le <a href="https://www.romanzolotarev.com/bin/ssg5">site</a> de son créateur, puis une simple commande permet de générer le site :</p>
<pre><code>ssg5 src dst "Nom du site" "https://www.exemple.fr"
</code></pre>
<p>Le site web est ainsi généré dans le répertoire <code>dst</code>. Pour chaque fichier markdown ou html, une page web est créée. L'arborescence du répertoire <code>dst</code> est identique à celle du répertoire <code>src</code>, et que tous les autres fichiers sont directement copiés sans modification. La carte du site <code>sitemap.xml</code> est générée automatiquement. Il est donc utile de créer un fichier <code>robots.txt</code> précisant l'URL complète du site :</p>
<pre><code>user-agent: *
sitemap: https://www.exemple.fr/sitemap.xml
</code></pre>
<p>On pourra se reporter à la page <a href="http://robots-txt.com/">robots-txt.com</a> pour plus de précisions sur la construction de ce fichier.</p>
<h2>Génération du site, un exemple minimal</h2>
<p>Essayons de produire un site minimal avec ssg5. On télécharge le programme qu'on rend exécutable.</p>
<pre><code>wget https://www.romanzolotarev.com/bin/ssg5
chmod +x ssg5
</code></pre>
<p>On commence par créer le répertoire source, on crée le fichier <code>index.md</code> avec un contenu minimal, puis on génère le site.</p>
<pre><code>mkdir src
echo '# Hello world!' &gt; src/index.md
./ssg5 src dst "Nom du site" "https://www.exemple.fr"
</code></pre>
<p>Il ne reste plus qu'à se rendre dans le répertoire <code>dst</code> pour visualiser les fichiers ainsi créés. Pour rendre ces fichiers disponibles pour les internautes, il faudrait les téléverser sur le FTP d'un hébergeur. Un exemple détaillé des contenus des fichiers <code>_header.html</code> et <code>_footer.html</code> pourra être trouvé dans le dépôt <a href="https://framagit.org/hummingbird/dioptre/">git</a> de ce site web.</p>
]]></description>
</item>
<item>
<guid>https://www.dioptre.fr/blog/2020-1-blog-article-0.html</guid>
<link>https://www.dioptre.fr/blog/2020-1-blog-article-0.html</link>
<pubDate>Fri, 26 Jun 2020 00:00:00 +0000</pubDate>
<title>Blog, article 0</title>
<description><![CDATA[
<h1>Blog, article 0</h1>
<p>Bienvenue sur mon blog personnel. Qui dit blog personnel dit que les sujets abordés ici seront ceux qui me tiennent à cœur, ils sont multiples et seront choisis au moment de l’écriture de chaque billet de blog. Il y a de fortes de chances que vous y trouviez des articles sur les logiciels que j'utilise, la pratique du vélo en ville et éventuellement sur ma pratique de la cuisine. Sans constituer une liste exhaustive, celle-ci permet au moins de donner une première idée des sujets qui y seront abordés. Un ensemble de sujets ne sera a priori pas abordé ici, ceux en lien avec mon activité professionnelle, aussi passionnante soit-elle.</p>
<p>Ce blog aura aussi, du moins à terme, une partie rédigée en anglais, de manière à renforcer le côté international de celui-ci. Le plus gros frein à ce projet est aujourd’hui d’ordre technique.</p>
<p>Chaque article de blog sera rédigé avec <a href="https://www.vim.org/">vim</a>, et le code html est généré par <a href="https://www.romanzolotarev.com/ssg.html">ssg5</a> et un processus d’intégration continue et de déploiement continu. Cela fera l’objet d’un article détaillé. En revanche, vous n'y trouverez pas de section commentaire. Ce n'est pas par volonté de museler l'auditoire, mais plutôt de garder ce site le plus simple possible à maintenir. En revanche, il sera toujours possible de me contacter par voie électronique, par mail, et je pourrais éventuellement faire un article réponse ou revenir sur un point particulier qui aura été abordé dans un tel courriel.</p>
<p>Il ne me reste plus qu’à vous souhaiter une bonne lecture !</p>
]]></description>
</item>
</channel>
</rss>
