La gestion des permalinks sous Octopress ne permet, par défaut, pas beaucoup de fantaisie. Elle sera généralement structurée d’une des manières suivantes :

  • /:categories/:title
  • /:year/:month/:day/:title/
  • /:title

Certains cas de figures ne sont pas gérés par défaut. Par exemple, je me suis retrouvé confronté à la situation suivante :

Pour un blog donné, nous avons trois “types” de posts : des articles concernant l’entreprise, des articles concernant le produits, et des vidéos. Chaque article, peu importe son type, peut appartenir à une ou plusieurs catégories.

Pour ce cas précis, je voulais un shéma d’URL reprenant le type d’article, suivit du titre de l’article. Le type d’un article étant défini par son layout, on pourrait penser à une structure de permalink du type :layout/:title. Malheureusement, cette solution ne fonctionne pas par défaut sous Octopress.

On pourrait également proposer comme solution de préciser, dans les entêtes de chaque article, la valeur permalink propre à chaque article :

---
layout: videos
title: "Ma vidéo"
date: 2015-10-07 09:20:08 +0200
share: true
published: true
permalink: videos/ma-video
---

Cette solution n’est pas efficace pour deux raisons :

  • Nous avons déjà plusieurs dizaines d’articles existants,
  • C’est une étape supplémentaire à chaque création d’article pour la personne en charge du blog

La solution : utiliser les hooks

Heureusement, nous avons une solution disponible out of the box : la libraire Octopress::Hook

Les Hooks permettent d’intéragir avec un Post au moment du rake generate. Ils permettent également d’intéragir avec d’autres types d’objets :

  • Site : permet d’intéragir avec l’instance Site
  • Page : permet d’intéragir avec une Page
  • Document : permet d’intéragir avec une collection de Documents

Les Hooks proposent plusieurs méthodes pour intéragir avec une instance donnée :

  • reset : permet de réinitialiser les variable avant chaque build
  • post_init : permet d’intéragir avec les objets après qu’ils n’aient été initialisés
  • pre_read : permet d’intéragir avec les objets avant que les fichiers statiques, les posts et les pages ne soient lus
  • post_read : permet d’intéragir après que les fichiers ne soit lu mais avant que le générateur ne soit enclanché
  • pre_render : permet d’intéragir avant que les posts et pages ne soient rendu (rendered)
  • post_write : permet d’intéragir après que tous les documents aient été écrits sur le disque

Exemple d’utilisation

Dans notre cas précis, nous voulons intéragir avec les objets de type Posts après qu’ils n’aient été initialisés

Pour ce faire, nous allons créer une class qui héritera de Octopress::Hooks::Post et qui surchargera la méthode post_init.

Créons un fichier plugins/hooks.rb :


require 'octopress-hooks'
module Jekyll
  class MyPageHook < Octopress::Hooks::Post

    def post_init(post)

    end

  end
end

La variable post reçue par notre méthode post_init correspond à un article donné. La méthode data appliquée à l’objet renvoie un Hash reprenant tous les headers du fichier ainsi que son contenu. Nous allons donc y retrouver les valeurs de :title, :categories, etc.

{
  "layout"=>"post",
  "title"=>"Octopress : surcharger les permalinks",
  "date"=>2015-10-0709: 20: 08+0200,
  "share"=>true,
  "published"=>true,
  "categories"=>[
    "Jekyll",
    "Octopress"
  ],
  "description"=>"TODO",
  "image"=>{
    "thumb"=>"TODO"
  },
  "date_xml"=>"2015-10-07T09:20:08+02:00",
  "date_text"=>"Oct 7th, 2015",
  "time_text"=>"9:20 am",
  "date_html"=>"",
  "date_time_html"=>""
}

Dans notre cas, nous souhaitons définir une valeur pour ce qui aurait pu être la valeur :permalink dans les headers du fichier.

Nous allons donc :

  • Vérifier la présence de permalink
    • Si elle n’existe pas, la définir
    • Sinon, ne rien faire

De cette manière, si nous décidons de définir un permalink particulier pour un article, celui-ci ne sera pas écrasé par le Hook au moment de gérerer le code HTML du site.

  def post_init(post)
    unless post.data.key?('permalink')
      post.data['permalink'] = "#{post.data['layout']}/:title"
    end
  end

Le code complet


require 'octopress-hooks'
module Jekyll
  class MyPageHook < Octopress::Hooks::Post

    def post_init(post)
      unless post.data.key?('permalink')
        post.data['permalink'] = "#{post.data['layout']}/:title"
      end
    end

  end
end

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

This site uses Akismet to reduce spam. Learn how your comment data is processed.