Jekyll: une hiérarchie de dossiers

mercredi 1 juillet 2015 • GF

Le moteur de sites statiques Jekyll génère les URL en fonction du nom des fichiers. Ainsi, le fichier 2015-07-01-jekyll-hierarchie-de-dossiers.markdown sera visible à l’adresse /2015/07/01/jekyll-hierarchie-de-dossiers/. C’est très pratique, jusqu’à ce que le dossier posts contenant les fichiers source soit plein à craquer. C’est alors que l’on songe à classer les fichiers en sous-dossiers, par exemple par année. Et c’est là que les problèmes commencent…

Le moteur de sites statiques Jekyll génère les URL en fonction du nom des fichiers. Ainsi, le fichier 2015-07-01-jekyll-hierarchie-de-dossiers.markdown sera visible à l’adresse /2015/07/01/jekyll-hierarchie-de-dossiers/. C’est très pratique, jusqu’à ce que le dossier posts contenant les fichiers source soit plein à craquer. C’est alors que l’on songe à classer les fichiers en sous-dossiers, par exemple par année. Et c’est là que les problèmes commencent…

Cette structure par défaut devient vite difficile à gérer :

_posts/
      |- 2015-07-01-jekyll-hierarchie-de-dossiers.markdown

Ainsi, la structure suivante est préférable :

_posts/
      |- 2015/
             |- 2015-07-01-jekyll-hierarchie-de-dossiers.markdown

Jekyll associe le nom du fichier à son URL, mais le fichier doit être placé dans le dossier racine posts. S’il se trouve dans un sous-dossier, le nom de ce sous-dossier est intégré dans l’URL.

Un exemple permet de comprendre le problème :

Fichier : /posts/2015-07-01-jekyll-hierarchie-de-dossiers.markdown
URL : /2015/07/01/jekyll-hierarchie-de-dossiers/

Fichier : /posts/2015/2015-07-01-jekyll-hierarchie-de-dossiers.markdown
URL : /2015/2015/07/01/jekyll-hierarchie-de-dossiers/

Si l’on tente de compiler le site en ayant déplacé les fichiers dans des sous-dossiers correspondant à l’année de rédaction, l’on se heurte à un problème de compilation dès lors que le tag post_url est utilisé.

Liquid Exception: Could not find post "2010-06-08-les-choix-par-defaut" in tag 'post_url'. Make sure the post exists and the name is correct. in pages/index.md
jekyll 2.5.3 | Error:  Could not find post "2010-06-08-les-choix-par-defaut" in tag 'post_url'.

Il faut donc commencer par modifier le contenu de ces tags, dans le corps des fichiers, en préfixant l’URL indiquée du nouveau sous-dossier.

Cependant, il reste le problème de l’URL du fichier, qui fait apparaître l’année en double. Pour le résoudre, j’ai choisi d’utiliser le mot-clé permalink dans le front-matter de chaque fichier Markdown. Ainsi, dans le fichier correspondant au présent article, l’on peut lire :

permalink:  /2015/07/01/jekyll-hierarchie-de-dossiers/

Cela fonctionne parfaitement, mais il faut éditer chaque fichier pour définir un permalink personnalisé, ce qui est extrêmement long et fastidieux lorsqu’on a plusieurs centaines de fichiers…

J’ai donc réalisé le petit script suivant en Ruby pour automatiser le processus.

############# CLASS DEFINITION #############

class Analyzer
  attr_accessor :ext, :src
  
  def initialize(ext, src)
    @ext = ext
    @src = src + "*" + ext
        
    Dir[@src].each do |filesrc|
      readfile filesrc
    end
  end
  
  def readfile(filesrc)
    # Read file
    begin
        # Open the file and read the lines
        file = File.new(filesrc, "r+")
        lines = IO.readlines(file)
        lines.map.each_with_index do |line,index|
            # Before the last line, add the permalink
            if "#{lines[index+1]}".include? "---"
              lines[index] += "permalink:  #{self.make_permalink(file)}/"
            end
        end
        # Write the line to the file
        lines.each do |line|
          file.puts(line)
        end
        file.close
    rescue => err
        puts "Exception: #{err}"
        err
    end
  end
  
  # Build the permalink :
  # 2015-07-01-foo => /2015/07/01/foo
  def make_permalink(file)
    f = File.basename(file, @ext)
    '/' + f.slice!(0..11).gsub!('-','/') + f
  end
  
end

############# MAIN #############
# Edit here
# First parameter: the file extension, .markdown, .md, .txt...
# Second parameter: the root dir
a = Analyzer.new(".markdown", "_posts/")

En spécifiant, à la dernière ligne, l’extension des fichiers et le dossier racine, le script modifie chacun des fichiers en ajoutant le permalink correspondant au nom du fichier. L’analyse menée par le script n’est pas récursive, si bien qu’elle doit être lancée avant de déplacer les fichiers dans des sous-dossiers.