Dans cette partie, nous allons faire plus ample connaissance avec les concepts de layouts et de partials qui vont nous éviter de nous répéter et donc nous permettre d'écrire moins de code. On pourra ainsi rédiger nos pages très rapidement. Ce sera aussi l'occasion de découvrir Slim qui lui allègera notre code.

Les langages de templating

Avant d'expliquer le fonctionnement des layouts et partials, faisons une courte pause et attardons nous quelques instants sur Slim.

Jusqu'à présent, nous n'avons pour ainsi dire rien codé du tout, aucune de nos pages n'est existante. Par défaut les pages sont codées en HTML que vous connaissez évidement. Le HTML seul ne nous servirait pas à grand chose. Comment récupérer les données que l'on a mises dans nos fichiers YAML avec uniquement du markup ?

C'est là qu'intervient ERB (Embedded Ruby) qui nous permet d'introduire directement du Ruby dans nos pages en le plaçant dans une paire de délimiteurs <% %>, un peu comme on pourrait le faire en PHP avec <?php ?>.

Le tout fonctionne parfaitement sans rien ajouter d'autre dans Middleman. Alors dans ce cas pourquoi changer ?

Slim, exterminateur de chevrons

Je ne sais pas pour vous mais ce que j'aime le moins dans le HTML c'est les chevrons! Pour chaque balise il y a 4 chevrons à taper. L'emplacement de cette touche sur le clavier et le fait d'aller la saisir avec le petit doigt tend à m'irriter en fin de semaine. Pour couronner le tout, on vient de voir que le Ruby de nos pages doit être délimité par des chevrons et le signe pourcentage..

Le simple fait de ne pas aimer les chevrons devrait vous faire adorer Slim. C'est très simple avec Slim, il n'y a plus du tout de chevrons, et en plus on ne ferme pas ses balises HTML. Pour ces deux seules fonctionnalités, on vient de réduire une bonne partie de code à taper ! Et c'est sans compter sur autres possibilités qui vont encore réduire cette quantité. Pour l'exemple:

<!-- En html et erb -->

<h1><%= current_page.data.title %></h1>
<div class="content">
  <p class="author-box">
    Publié par : 
    <span><%= current_page.data.author %></span>
  </p>
  <ul>
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
  </ul>
</div>
/ En Slim

h1 = current_page.data.title
.content
  p.author-box 
    ' Publié par :
    span = current_page.data.author
  ul
   li item 1
   li item 2
   li item 3

Je vous invite à parcourir l'introduction à Slim sur le dépôt Github, la prise en main est rapide.

En gros, on enlève tous les chevrons et on ne ferme pas les balises. Pour que cela fonctionne il faut respecter l'indentation. Slim est strict là dessus et ne manquera pas de vous rappeler à l'ordre si votre indentation est mauvaise.

La balise div qu'on utilise très souvent se voit remplacée par un unique point '.' même si div fonctionne toujours. Lorsqu'on veut ajouter une classe CSS pas besoin de la déclarer avec class="maclasse", on la colle directement à la balise. On peut même chainer plusieurs classes : p.author-box.sidebar-item

Pour inclure du Ruby on sert de deux signes, le signe - et le signe = ce dernier affichant dans la page l'expression évaluée.

Au final, utiliser Slim permet d'avoir des pages beaucoup plus lisibles et d'être plus rapide. Depuis que j'ai adopté Slim, j'ai vraiment du mal à revenir au HTML classique.

Installer Slim

Slim se présente sous forme de gem, on peut donc l'ajouter à notre Gemfile :

gem 'slim',    '~> 3.0.2'

On sauvegarde le fichier puis en ligne de commande :

$ bundle install

Slim est installé, il ne reste qu'une petite chose à faire pour pouvoir l'utiliser, ajouter un require dans le fichier config.rb, juste au dessus du bloc qu'on avait ajouté pour le déploiement :

require 'slim'

Si le serveur Middleman était lancé, il faut le stopper et le relancer : Ctrl + C pour le stopper et middleman server pour le relancer. On va pouvoir commencer à coder notre site !

Les layouts et partials

Une nouvelle fois, il va être question de ne pas se répéter et d'écrire le moins de code possible. Les layouts et partials vont grandement nous aider en nous laissant réutiliser du code dans nos pages.

Pour ceux qui ont fait un peu de WordPress, le layout est en quelque sorte le fichier index.php avec get_header() et get_footer() tandis que les partials serait les morceaux de codes qu'on inclut avec get_template_part().

Les layouts

Basiquement, on pourrait dire que le layout est une sorte de modèle qui va contenir tout le code de la page à l'exception du contenu. Le contenu sera appelé à l'intérieur du layout avec la fonction yield qu'on verra plus tard.

On peut donc placer dans le layout les éléments qui sont répétés sur toutes les pages comme le contenu de la balise head, la barre de navigation ou encore le footer.

Tout ce code ne se retrouve donc qu'à un seul endroit ce qui facilite la maintenabilité. (Si vous aviez encore des doutes sur la façon de concevoir un site statique, ils devraient se dissiper)

Dans le cas du tutoriel, nous n'avons besoin que d'un seul layout puisque le modèle est le même pour toutes les pages. Middleman permet tout de même de créer plusieurs layouts et de spécifier ensuite lequel utiliser et dans quel cas, ce qui ouvre beaucoup de possibilités pour des sites de plus grosse envergure.

Les partials

Les partials sont des fragments de code qu'on peut appeler où on veut dans nos pages ou dans un layout. Ils permettent eux aussi d'éviter la répétition. Si on remarque qu'un élément doit être répété sur plusieurs pages, c'est un parfait candidat pour être placé dans un partial.

Si on reprend les vues du projet, on remarque qu'en bas de page il y a le bloc "Rejoignez-nous cet été" qui revient sur toutes les pages sauf pour la page réservation. Sa place est donc dans un partial. On code une fois le bloc et on l'appelle depuis nos pages quand on en a besoin.

Si on regarde bien, on peut aussi remarquer que deux pages possèdent une galerie de photos, même si celles-ci sont différentes. Là encore on peut utiliser un partial.

L'usage de partials ne s'arrêtent pas là, on peut également les utiliser pour isoler du code ou découper de gros fichiers en plus petits fichiers sur lesquels il sera plus simple d'intervenir. Cela permet aussi de tester facilement des alternatives.

Pour le projet on isolera ainsi la barre de navigation, l'image en header et le footer.

Créer le layout principal

Notre layout se trouve dans le dossier source/layouts/ et comme on utilise Slim, la première chose à faire c'est de le renommer en layout.slim et d'en supprimer le contenu.

Comme le menu et le footer seront en partials, le layout est très léger, on l'enrichira par la suite d'autres fonctionnalités :

/ layout.slim
doctype html
  html lang="fr"
    head
      meta charset="utf-8"
      meta name="viewport" content="width=device-width,initial-scale=1"

      title = current_page.data.title ? current_page.data.title : data.settings.site.title
      meta name="description" content="#{current_page.data.description}"
      meta name="robots" content="index,follow"

      = stylesheet_link_tag 'application'

    body class="#{page_classes}"

      = partial "partials/navbar"

      == yield

      = partial "partials/footer" 

Si on observe le code, on remarque quelques nouveautés. La balise title est remplie avec une condition ternaire : Si dans les datas de la page courante il y a un titre on l'utilise sinon on utilise le titre déclaré dans le fichier settings.yml.

Pour la meta description, on cherche dans les datas de la page si la description a été renseignée. On inclura cette donnée avec Frontmatter.

= stylesheet_link_tag 'application' est un helper permettant d'afficher le lien vers la feuille de style, ici application.css. Cela évite de taper la version complète : <link href="application.css" rel="stylesheet" type="text/css"> On utilisera par la suite d'autres helpers très pratiques pour les liens ou les images, vous pouvez en avoir un aperçu dans la documentation de Middleman.

Pour la balise body on voit page_classes qui est également un helper. Il va utiliser des information de l'url pour nommer les classes CSS pour body.

Dans notre body, on appelle nos partials navbar et footer et entre les deux, on vient placer le yield qui lui appellera le contenu de notre page.

Créer les partials

On ne va s'occuper ici que du menu, du footer, du bloc "Rejoignez-nous" et de la galerie en ne balisant que le HTML, les classes CSS seront ajoutées une fois tout le contenu intégré. Créer un nouveau dossier partials/ dans source, au même niveau que layout/ puis créer les fichiers :

# dans le dossier source
$ mkdir partials
$ cd partials
$ touch _navbar.html.slim footer.html_slim _call-to-action.html.slim _gallerie.html.slim

Pour être identifié comme partial, les noms de fichiers doivent commencer par un underscore. Notez que dans layout.slim, on utilise le nom du partial sans underscore et sans extension.

La barre de navigation

/ _navbar.html.slim
div role="banner"
  div
    = image_tag "/images/logo.png" alt="No Wifi Summercamp"
   nav role="navigation"
     ul
       li = link_to "Accueil", "/"
       li = link_to "Camp", "/camp.html"
       li = link_to "Equipe", "/equipe.html"
       li = link_to "Activités", "/activites.html"
       li = link_to "Blog", "/blog.html"
       li = link_to "Réservation", "/reservation.html"

On voit ici l'usage des helpers image_tag et link_to. Les dimensions de l'image ne sont pas spécifiées et c'est voulu, Middleman dispose d'une fonction permettant d'ajouter automatiquement les dimensions lors du build.

/ _footer.html.slim    
footer
  div
    = image_tag "/images/logo.png", alt:"No Wifi Summercamp"
  div role="content-info"
    p  #{data.settings.author.address}
    p Tel : #{data.settings.author.phone}
    p Mail : #{data.settings.author.email}
    p 
      ' Suivez nous sur 
      = link_to "Facebook", data.settings.social.facebook
    p 
      ' et sur
      = link_to "Twitter", data.settings.social.twitter

  nav role="navigation"
    ul
      li = link_to "Accueil", "/"
      li = link_to "Camp", "/camp.html"
      li = link_to "Equipe", "/equipe.html"
      li = link_to "Activités", "/activites.html"
      li = link_to "Blog", "/blog.html"
      li = link_to "Réservation", "/reservation.html"
      li = link_to "Mentions légales", "/mentions-legales.html"
      li = link_to "Conditions générales de vente", "/cgv.html"

  p 
    '  &copy;
    = Time.now.year
    '
    = link_to data.settings.author.name, "/"
    '  - Design et développement :
    = link_to data.settings.copyright.developer.name, data.settings.copyright.developer.url

Le footer reprend le logo et le menu de la navbar avec quelques liens en plus. Les autres informations comme l'adresse, le numéro de téléphone, l'email, les liens vers les réseaux sociaux sont récupérés depuis le fichier settings.yml.

Idem pour la dernière ligne avec le copyright. Cela peut sembler un peu overkill puisqu'il aurait été bien plus rapide de taper directement les valeurs puisqu'elles ne sont que dans le seul fichier _footer.html.slim.

C'est tout à fait vrai, mais l'idée ici est de pouvoir, une fois le site terminé, n'intervenir que sur les fichiers datas. En outre cela permet une réutilisation plus aisée pour d'autres projets.

Les dernières lignes peuvent sembler étranges, il s'agit de quelques règles d'indentation pour gérer l'écriture multilignes et les espaces. C'est expliqué dans la documentation. Le Time.now.year permet simplement de récupérer l'année en cours.

Le bloc "Rejoignez-nous"

/ _call-to-action.html.slim
h2 Rejoignez-nous
p Seul, en famille ou entre amis, nous vous attendons
= link_to "Reserver mon séjour", "/reservation.html" 

Rien de compliqué pour ce bloc…

La galerie

Le partial galerie est intéressant car il nécessite d'ajouter un peu de logique. En effet il doit être utilisable sur deux pages avec des galeries différentes. Le système de partial étant intelligent on verra qu'il est possible de passer des variables dans = partial "partials/gallery"

/ _gallery.html.slim 
div
  ul
    - gallery.each do |picture|
      li
        = link_to "/images/galleries/#{picture}" do
          = image_tag "/images/galleries/thumbs/#{picture}"

Notre galerie est une liste d'images qu'on a défini dans galleries.yml et comme on a deux galeries, il y a deux listes nommés homepage et camp.

Lorsque nous allons appeler ce partial dans notre page, on va lui préciser la liste qu'on souhaite utiliser en la passant dans la variable gallery.

Donc dans notre partial, la variable gallery contient un tableau dans lequel se trouve nos images. On peut ensuite faire une boucle avec .each pour afficher nos images en miniature et les liens correspondants.

Testons notre layout et nos partials

Afin de tester tous nos partials, il faut modifier le layout pour lui faire afficher une galerie et le call to action. Ajoutez ces deux lignes au dessus de = partial "partials/footer" et dessous de yield:

/ layout.slim
= partial "partials/gallery", :locals => { gallery: data.galleries.homepage}
= partial "partials/call-to-action"

Démarrez le serveur si il n'était pas actif (middleman server) et vous devriez avoir cet affichage.

Vous remarquerez comment la liste d'images est passée en variable. Pour vérifier le bon fonctionnement, changez cette partie par data.galleries.camp la galerie spécifique à la page camp s'affichera.

Une fois les vérifications faites, supprimez les dernières lignes ajoutées, commitez, et passons à la partie suivante, la création des pages.

Article précédent : Tutoriel Middleman, organiser ses données sans base de données
Article suivant : Tutoriel Middleman, création des pages

Je suis disponible pour des missions longues / CDD / CDI Cliquez pour en savoir plus