Archives par année dans Jekyll

Je continue dans mon exploration du monde merveilleux de Jekyll (le générateur de site statique qui fait maintenant tourner ce blog), avec une autre fonctionnalité de WordPress que je voulais reproduire : les archives par année avec menu dans la sidebar.

Ça semble trivial comme, mais non. Avec Jekyll RIEN (ou presque) n’est trivial. Je suis assez vite tombé sur le plugin jekyll-archives qui permet de générer les pages d’archive (non-paginées, mais tant pis). Je suis assez vite arrivé à un truc qui marche de ce côté-là, pas de problème majeur.

Par contre, c’était un peu plus compliqué pour générer le menu.

En cherchant un peu, j’ai fini par tomber sur cet article qui décrit comment générer une sorte de plan du site par date, basé sur une itération sur l’ensemble des articles. J’ai pu en tirer (en simplifiant) ce qu’il me fallait pour mon menu, à une exception près : le décompte des articles (forcément il n’en avait pas besoin dans son cas).

Et là, je me suis heurté à un truc : comment incrémenter une variable dans Liquid (le moteur de templates de Jekyll) ? Naïvement, j’ai tenté un simple {% assign postCount = postCount + 1 %} mais ce fut un échec cuisant. Je n’ai pas trouvé ce que fait un “+” dans ce cas, mais clairement pas une addition (ma variable valait toujours 0 et en inversant les arguments j’avais toujours 1). J’ai donc :

  1. cherché comment incrémenter une variable : rien trouvé dans la doc, forcément, on n’a que des exemples d’assignations avec une variable en dur
  2. cherché sur le net : je suis tombé sur cette doc qui parle d’un tag increment gérant des variables incrémentales indépendantes des autres variables (pourquoi indépendantes ? qu’est-ce que ça apporte ? mystère…) et semble-t-il non-réinitialisable, donc ça ne répond pas à ma question
  3. puis j’ai fini par tomber là-dessus et là, j’ai enfin trouvé : pour faire une addition, il faut passer par le filtre plus

Donc voilà, j’ai ma solution pour générer mon menu :

<h2>Archives</h2>
<ul>
  {% assign postCount = 0 %}
  {% for post in site.posts %}
    {% assign year = post.date | date: '%Y' %}
    {% if post.previous %}{% assign nextYear = post.previous.date | date: '%Y' %}{% else %}{% assign nextYear = 0 %}{% endif %}
    {% assign postCount = postCount | plus: 1 %}
    {% if year != nextYear %}
      <li><a href="/archives/{{ year }}/">{{ year }}</a> ({{ postCount }})</li>
      {% assign postCount = 0 %}
    {% endif %}
  {% endfor %}
</ul>

C’est laborieux, mais ça marche.

Reste juste un défaut : rien qu’avec ça je suis passé de 20 à 30 secondes pour régénérer mon site. C’est un peu chiant quand on veut contrôler que ce qu’on vient de faire marche (mais ça n’a aucun impact pour le visiteur puisque lui n’accède qu’à des pages statiques).

J’ai donc cherché comment on pouvait faire un peu de caching dans Jekyll. Forcément, j’ai rien trouvé de natif, mais je suis tombé rapidement sur le plugin jekyll-include-cache. Il ajoute une nouvelle instruction alternative à include et qui s’utilise exactement pareil mais n’effectue l’évaluation du contenu qu’une fois : include_cached. Du coup en utilisant ça pour mes header, footer et sidebar, j’ai pu redescendre à environ 17 seconde de temps de génération. Ça reste beaucoup, mais c’est quand même moitié moins.

Par contre, le cache en question n’est pas régénéré à chaque changement (y compris changement du template inclus) mais seulement à chaque fois que le serveur est relancé, ce qui veut dire relancer systématiquement le serveur avant de publier pour prendre en compte les mises à jour (dans mon cas nouvel article ou changement de catégorie). Du coup ça reste largement bancal comme solution, pas sûr que je garde ça sur le long terme.


Plugin de tri des catégories pour Jekyll

Comme je le disais la semaine dernière, il restait des ajustements à faire sur le blog. L’un d’entre eux était d’afficher un menu présentant notamment les catégories (et aussi les archives par années, mais ça viendra plus tard).

J’ai pas mal galéré pour trouver comment faire (ça me semble être un truc assez basique, mais ce n’est pas trop mis en évidence dans la doc). J’ai assez rapidement fini par trouver dans quelle variable chercher les catégories (il s’agit de site.categories) qui se trouvent sous la forme d’un tableau associatif où la clé est le nom de la catégorie et la valeur un tableau des articles.

Ce qui m’a pris beaucoup plus de temps, c’est trouver comment récupérer la clé lors de l’itération. J’ai fini par trouver dans la doc de Liquid (le moteur de templates de Jekyll) : lorsqu’on itère sur un tel tableau chaque item qu’on reçoit contient un tableau à deux entrées : la clé en 0 et la valeur en 1 (pour le coup, je préfère les syntaxes de Twig ou AngularJS qui sont plus claires). Pour afficher les catégories, j’en étais donc arrivé à :

<ul>
  {% for category in site.categories %}
    <li><a href="/categories/{{ category[0]|slugify:'latin' }}/">{{ category[0] }}</a> ({{ category[1].size }})</li>
  {% endfor %}
</ul>

Restait à les trier parce que j’en ai quand même beaucoup… Et là pour le coup je n’ai rien trouvé de natif. Je suis tombé sur plusieurs plugins. D’abord un premier qui avait l’air riche, mais que je n’ai pas réussi à faire fonctionner… Puis un deuxième beaucoup plus simple, mais pas complètement satisfaisant (notamment le tri ne mettait à la fin ma catégorie “À propos du blog” à cause de l’accent). Ne connaissant rien à Ruby, j’ai un peu tâtonné pour épurer le truc et corriger ce qui me gênait.

Le résultat est accessible ici : jekyll-hash-table-sort-filters

L’exemple de code précédent, après installation du plugin, devient le suivant :

<ul>
  {% assign categories = site.categories | sort_by_keys %}
  {% for category in categories %}
    <li><a href="/categories/{{ category[0]|slugify:'latin' }}/">{{ category[0] }}</a> ({{ category[1].size }})</li>
  {% endfor %}
</ul>

EDIT du 10/06/2018 à 11h10 : forcément, y avait une erreur dans la version du plugin que j’ai publiée… et qui faisait tout planter. C’est corrigé : jekyll-hash-table-sort-filters.

Et comme tout est généré une fois pour toutes, je n’ai vu le problème qu’à la génération suivante, donc aujourd’hui.


Retour du blog

Ça faisait déjà près d’un an et demi que ce blog était mort suite à un crash serveur. Je ne pouvais pas le remettre en fonction directement parce qu’il utilisait une vieille version de WordPress qui n’était pas compatible avec PHP7 et je n’avais pas envie de pourrir mon nouveau serveur avec un vieux PHP. Quant à la mise à jour de WordPress était dissuasive parce que j’avais de nombreuses versions de retard et que ça se serait forcément fait dans la douleur.

En parallèle, j’avais vu passer plusieurs articles parlant de remplacer WordPress et autres moteurs dynamiques par un générateur de site statique. Cet aspect me tentait bien, mais pas pour les raisons avancées habituellement, en particulier la principale : les perfs, je m’en fiche un peu (mon serveur se tourne les pouces la plupart du temps et j’ai une audience limitée).

Non, ce qui m’intéressait, c’était plutôt de supprimer la maintenance et les besoins de mise à jour, soit précisément ce qui m’a fait repousser la remise en ligne du blog (et ce qui me causait sans doute de grosses failles de sécurité sur le précédent serveur). En effet, dans ce cas le générateur n’est pas en ligne, je peux le garder tranquillement en local sur mon ordi perso.

Par contre, ça a plusieurs gros inconvénients qui m’ont retenu de sauter le pas plus tôt, en particulier deux :

  • Pas de système de commentaires. C’est embêtant parce qu’il est exclus que je délègue ça à un silo genre Discuss. Et si c’est pour remettre du JS et un système de web services, ben on reperd direct l’intérêt principal de s’éviter la maintenance… Je n’ai pas de solution correcte pour l’instant donc il faudra s’en passer (genre en passant par Mastodon ou à défaut Twitter), jusqu’à ce que je trouve quelque chose de viable.
  • Pas de moteur de recherche. Moins gênant, mais quand même déléguer à Google et autres la recherche interne du site ça me déplaît pas mal. Là non plus, je n’ai pas de solution pour l’instant (j’ai trouvé un plugin qui permettrait de le faire, mais en passant par une API tierce, donc bon, on n’y gagne pas grand-chose au final).

J’ai finalement décidé de sauter le pas parce que ça m’est arrivé quand même assez souvent de me dire que j’aurais bien fait un article sur un sujet, mais qu’en l’absence de blog, j’ai soit rien fait, soit résumé en quelques pouets et/ou tweets.

J’ai donc cherché un peu dans les outils existants. Forcément, y en a des dizaines… Du coup, faut choisir. Après avoir écarté tout ce qui est NodeJS et rien trouvé en PHP, je me suis rabattu sur Jekyll (en Ruby) qui a le mérite d’avoir un peu d’ancienneté et donc pas mal de plugins dispo et probablement une durée de vie pas trop basse.

Après avoir rencontré pas mal de problèmes tels que :

  • besoin de choisir un thème
  • besoin d’installer des plugins et configurer plein de choses (Jekyll de base est assez vide)… pour la liste des plugins, cf. la page à propos
  • du temps perdu à comprendre que si ma pagination était morte d’un coup, c’était parce que j’avais reformaté le fichier (oui les pages contiennent des en-têtes en YAML qui a l’idée VRAIMENT débile de se baser sur l’indentation, donc un formatage et boum ça marche plus… et vas-y pour comprendre que ça vient de là !)
  • repasser sur tous les articles pour faire en sorte que ça se rende bien (un convertisseur depuis une base WordPress est dispo mais il ne convertit pas les balises spécifiques… et j’en avais pas mal pour du code ou de la mise en forme autour des images)

J’ai enfin quelque chose de fonctionnel \o/

J’en profite également pour basculer sur un autre domaine (en .net plutôt que .com).

Il reste à mettre en place les redirections pour ressusciter les anciennes URL des articles, mais ça peut attendre, après un an et demi, on est plus à quelque semaines près… Et il risque d’y avoir encore quelques ajustements, mais ça a déjà le mérite d’être fonctionnel ^^


AMT : archiver ses tweets

Ça faisait longtemps que je voulais sortir mes tweets et favoris de Twitter et ce pour plusieurs raisons :

  • éviter de perdre ce qui est supprimé (y compris les images)
  • faire des recherches efficaces (Twitter est lamentable de ce côté-là)
  • garder tout ça chez moi sous mon contrôle

En début d'année, je me suis finalement décidé à prendre le temps de regarder ce qui existait. J'ai fini par tomber sur Archive My Tweets qui semblait faire ce que je voulais. Et que j'ai donc installé : bingo, mes tweets sont exportés \o/

Du coup, forcément, j'ai commencé à modifier un peu le thème et traduire l'interface en français... et là c'est le drame. Comme souvent quand on creuse un peu ben, c'est bugué et très limité :

  • les retweets sont tronqués
  • le thème n'est pas remplaçable sans écraser les fichiers
  • pas de système de traduction de l'interface et, pire, la moitié des textes sont directement dans le code et pas dans les templates
  • ...

Au premier bug, je me dis que je vais le corriger puis proposer les corrections à l'auteur. Au troisième gros changement, je laisse tomber l'idée et je pars sur un fork.

Du coup de fil en aiguille, j'ai dû réécrire plus de la moitié du code pour aboutir à une application qui :

  • archive mes tweets, retweets et favoris
  • archive les images et avatars qu'ils contiennent (c'était nécessaire pour pouvoir les afficher et de toute façon, c'est pas plus mal, comme ça ils sont archivés aussi)
  • permet de rechercher dans l'ensemble des tweets et de filtrer entre tweets, retweets, favoris et réponses
  • gère des traductions de l'interface (français et anglais même si je ne garantis rien sur la qualité de la seconde)
  • permet d'ajouter d'autres thèmes graphiques

J'envisage d'autres améliorations encore, mais c'est déjà pas mal :)

Le code est évidemment libre (hébergé sur la forge de Framasoft) et j'ai même pris le temps de le documenter ! Quand à mon instance à moi, elle est consultable ici : tweets.darathor.net.

L'application n'est pas encore totalement stable, mais n'hésitez pas à la tester. Par contre, si vous l'utilisez effectivement, n'hésitez pas à m'en avertir parce que tant que personne d'autre que moi ne s'en sert, je ne perdrai pas de temps à publier des procédures de migration lors des mises à jour...

Voilà voilà... Ça faisait longtemps que j'avais plus fait un article pour autre chose qu'ironiser sur la dérive sécuritaire ^^

PS : Bon par contre, j'ai eu la mauvaise surprise de constater qu'en termes de favoris, on ne peut récupérer que les 3200 derniers (et contrairement aux tweets et retweets ils ne sont pas dans l'archive qu'on peut exporter depuis son compte). Et j'ai bien l'impression qu'ils sont vraiment perdus parce que j'ai pris le temps de supprimer tous ceux que j'avais exportés mais je suis juste arrivé à une liste vide, aucune trace des plus anciens... Ou comment perdre 10000 tweets que j'avais mis en favoris justement pour en garder une trace :blase: Ça m'apprendra à faire confiance à un silo.


« Tant que c'est à l'étranger, ça compte pas. »

« Tant que c'est à l'étranger, ça compte pas. » C'est le seul et unique article du nouveau projet de loi anti-terroriste présentée par Bernard Caseneuve mercredi prochain devant le Sénat dans le cadre d'une procédure accélérée.

Ce nouveau projet de loi devrait permettre à nos équipes de récolter des renseignements plus facilement sur le terrain et, le cas échéant, de contrecarrer des attentats en neutralisant efficacement leurs auteurs potentiels. « Cela se pratique déjà dans les faits, mais comme ce n'est pas explicitement précisé dans la loi, les agents vivent dans une insécurité juridique qui nuit à leur efficacité », a assuré le ministre de l'Intérieur devant l'Assemblée Nationale lors des débats en début de semaine dernière. « Le cadre juridique encadrant leurs actions doit être le plus clair possible et il me semble que notre projet de loi répond parfaitement à ce besoin tout en instaurant les garde-fous nécessaires », a-t-il précisé. Devant les critiques que lui ont opposés quelques rares députés lors de la première lecture à l'Assemblée la semaine passée, il a répondu que « c'est d'ailleurs déjà ce que pratiquent nos alliés américains à Guantanamo et récemment nos alliés anglais via des interventions ciblées à l'aide drones ».

Cependant, le projet de loi n'est pas passée sans heurts jusqu'à présent puisque des débats animés ont opposé à l'assemblée le ministre et le rapporteur Jean-Jacques Urvoas au groupe Les Républicains qui critiquaient la complexité de la loi et l'absence de contrôle. Mais un compromis a été trouvé vers une heure du matin après une interruption de séance de trente minutes grâce à deux amendements décisifs. Le premier rajoutait la précision « Tant que c'est à l'étranger » en début d'article, instaurant une certaine limitation dans la portée de la loi, approuvée des deux côtés de l’hémicycle. Le second retirant un « n' » jugé inutilement complexe. « Je ne peux qu'approuver cette loi qui va dans le bon sens », a déclaré Éric Ciotti, député des Alpes-Maritimes « mais je regrette toutefois qu'elle n'aille pas plus loin. Notamment en ce qui concerne les étrangers présents sur le territoire français. »

La simplicité de cette loi ne semble cependant pas faire l'unanimité. « Je ne comprenais rien à l'essentiel de la loi et des amendements, j'ai donc suivi l'avis du ministre », a déclaré une députée de la majorité. Malgré tout, le ministre se veut rassurant : « cela reste évidemment une problématique éminemment technique, mais nous nous sommes attachés à l'aborder de la manière la plus simple possible. »

Plusieurs organisations qui se sont fermement opposées, sans succès jusqu'à présent, à ce projet de loi qu'elles jugent « inacceptable, dangereux et irrespectueux des Droits de l'Homme » ont annoncé leur intention de durcir leur action à l'occasion du passage devant le Sénat. « Jusqu'à présent, nous avons privilégié les voies légales [plusieurs recours devant le Conseil Constitutionnel et le Conseil d'État ces derniers mois, NDLR] contre les lois précédentes et avons tenté d'expliquer en quoi elles étaient dangereuses, mais force est de constater que ça ne fonctionne pas », a déclaré tristement Adrienne Charmet-Alix, porte-parole de la Quadrature du net. « Nous allons donc nous inspirer des actions qui ont obtenu gain de cause auprès du gouvernement ces dernières années en bloquant des routes, en tabassant des fonctionnaires du renseignement et en brûlant des boites noires. Puisque faire appel à l'intelligence ne nous vaut que du mépris, voire des insultes, nous allons tenter la connerie et la violence, sait-on jamais », a-t-elle conclu sur un haussement d'épaules désespéré.

Voilà voilà, c'est mon troisième article débile de suite sur le sujet, mais en parler sérieusement serait trop déprimant... Cela dit, ça devient difficile de grossir le trait quand il est déjà si épais...

Cet article est bien entendu publié sous licence :

License : Complete Bullshit