Dans les précédentes parties, nous avons vu comment créer nos pages à l'aide de layout et partials, puis avons ajouter un peu de ruby pour automatiser la création de celles-ci. Nous allons maintenant ajouter une fonction blog, grâce à l'extension blog de Middleman.
Installation et configuration du blog
L'extension blog est une gem, donc comme pour les précédentes, on va ajouter la gem dans le Gemfile
:
# Gemfile
gem "middleman-blog", "~> 3.6.0.beta.2"
On installe la gem avec bundle install
puis on va initialiser le blog à la main dans config.rb
. Il existe une commande pour le faire automatiquement mais qui est surtout utile en début de projet.
# depuis la racine du projet
$ bundle install
# config.rb
###
# Blog settings
###
Time.zone = "Paris"
I18n.config.enforce_available_locales = false
activate :blog do |blog|
# This will add a prefix to all links, template references and source paths
# blog.prefix = "blog"
blog.name = "blog"
blog.permalink = "/{title}.html"
# Matcher for blog source files
blog.sources = "{year}-{month}-{day}-{title}.html"
# blog.taglink = "tags/{tag}.html"
blog.layout = "layouts/blog"
# blog.summary_separator = /()/
# blog.summary_length = 250
# blog.year_link = "{year}.html"
# blog.month_link = "{year}/{month}.html"
# blog.day_link = "{year}/{month}/{day}.html"
blog.default_extension = ".markdown"
blog.new_article_template = "source/new-article.markdown"
# blog.tag_template = "tag.html"
# blog.calendar_template = "calendar.html"
# Enable pagination
blog.paginate = true
blog.per_page = 10
blog.page_link = "page/{num}"
# Custom categories
blog.custom_collections = {
category: {
link: '/categories/{category}.html',
template: '/category.html'
}
}
end
page "/feed.xml", layout: false
J'ai volontairement laissé le bloc avec toutes les options activables à titre informatif. Lorsqu'on va créer un nouvel article, son url sera de type année-mois-jour-titre. C'est ce qu'on voit pour blog.sources
, mais ce n'est pas pour autant qu'on souhaite utiliser le même nom pour notre permalien. On définit donc la structure qu'on veut dans blog.permalink
, ici j'ai choisi de ne garder que le titre.
blog.layout
permet de préciser quel layout on utilise pour le blog, on va donc créer un nouveau layout pour le blog dans le quel on affichera l'article mais également les informations sur l'auteur et la date de publication ainsi que les commentaires.
blog.default_extension
permet d'indiquer le type de fichier qu'on va utiliser, ici ce sera du Markdown.
blog.new_article_template
définit l'emplacement d'un modèle d'article qui servira comme base à chaque création d'article. On s'en servira pour avoir le bloc Frontmatter déjà prêt à la création.
Le bloc pagination va nous permettre d'activer la pagination, ici on affichera 10 articles par page.
Parmi les éléments commentés, on voit les year_link
, month_link
et day_link
que l'on n'utilisera pas ici, de même que les tags et le calendrier. blog.summary
permet de créer automatiquement des résumés en utilisant les premiers mots de l'article. On ne l'utilisera pas non plus au profit d'un extrait qui sera géré avec Frontmatter.
Le bloc custom collections
va nous permettre de créer des collections d'articles en fonction de la catégorie indiquée dans l'en-tête. Middleman se charge automatiquement de créer les pages listant les articles par catégories.
Puisqu'on n'utilise pas les tags, on aurait très bien pu se servir des tags en guise catégories, l'usage est le même. L'intérêt ici c'est de montrer comment créer des collections. Par contre il y a une limitation, un article ne peut appartenir qu'à une seule catégorie, ce qui est le cas ici.
Inception de layouts
Le layout pour le blog est ni plus ni moins qu'une copie du layout de base auquel on va venir ajouter les éléments spécifiques au blog. On pourrait donc tout à fait copier le fichier layout.slim
et le modifier. Mais ça ne serait pas très DRY tout ça. Heureusement Middleman a une fonction pour nous aider : wrap_layout
qui va nous permettre d'imbriquer le layout blog dans le layout principal.
Dans ce nouveau layout on va inclure les informations sur l'auteur. Le nom de l'auteur sera stocké dans les données de l'article, mais il faut pouvoir retrouver sa photo et cette information se trouve dans le fichier data/members.yml
. On va donc créer un helper pour effectuer cette tâche.
Ouvrez le fichier config.rb
, cherchez le bloc commenté helper et ajoutez ce qui suit :
# config.rb
# Methods defined in the helpers block are available in templates
helpers do
def find_author(author_slug)
author_slug = author_slug.downcase
result = data.members.select {|member| member.keys.first == author_slug }
raise ArgumentError unless result.any?
result.first
end
end
Dans le fichier members.yml
, chaque membre est identifié par son nom en minuscule. ( comparez les fichiers members.yml
et activities.yml
pour voir la différence).
On passe au helper le nom de l'auteur (current_article.data.author
) et on fait un select dans le fichier data/members.yml
pour retrouver notre auteur.
Pour plus d'informations sur la gestion des auteurs dans Middleman, référez-vous à ce billet sur Pixelcabin
Dans le layout de blog on utilisera donc ce helper pour créer une variable author
:
- author = find_author(current_article.data.author)
Création du layout blog
On crée un nouveau fichier blog.slim
dans le dossier layouts/
/ layouts/blog.slim
= wrap_layout :layout do
div role="main"
= partial "partials/header"
aside
- author = find_author(current_article.data.author)
= image_tag "/images/equipe/#{author.picture}"
h3 = author.name
p
' Publié le :
= I18n.l current_page.date, format: '%e %b %Y'
p
' Dans :
= current_article.data.category
article
= current_article.data.excerpt
== yield
Comment fonctionne ce layout imbriqué ? Quand Middleman va tomber sur un article de blog, il va savoir automatiquement qu'il faut utiliser le layout blog. A la première ligne wrap_layout
lui indique d'aller chercher le layout principal et d'inclure le code qui suit dans le = yield
.
Puis le yield
du layout blog va lui inclure le code contenu dans l'article.
Création des pages
On continue donc avec la création du modèle d'article que l'on va créer dans le dossier source
. Le fichier est au format .erb ce qui va nous permettre de récupérer les variables @title
et @date
automatiquement.
Modèle pour le blog
# new-article.erb
---
title: <%= @title %>
title_seo: ""
description: ""
date: <%= @date %>
hero_image:
thumbnail:
category:
excerpt:
author:
---
Pas grand chose à dire sur ce ficher, on y met simplement notre code FrontMatter auquel on a ajouté thumbnail, category, excerpt et author. Le thumbnail sera utilisé dans les listes d'articles, l'excerpt sera utilisé en en-tête d'article et dans les listes.
Lister les articles
On va avoir besoin de listes d'articles pour plusieurs pages. La première c'est la page blog qui liste l'ensemble des articles. Puis les pages catégories pour filtrer les articles en fonction des catégories.
Les catégories sont gérées par des custom collections. Middleman se charge de créer les listes pour les catégories qu'ils trouvent dans les articles. Si vous décidez de renter "chaton" pour la clé category:
, une page categories/chaton.html
sera créée, listant tous les articles "chaton".
Pour le site du projet, les catégories sont décidées en amont, il y en a 6 : La vie au camp, Activités, Reportage photo, Portrait de résident, Conseils et Lifehack.
La liste des catégories est affichée sur la page blog et dans toutes les pages de catégories. Je pense que vous avez deviné, on va créer un nouveau partial !
La boucle pour afficher les articles est également commune aux deux types de pages, on peut donc tout mettre dans le partial articles_list.html.slim
/ _articles_list.htlm.slim
p Catégories :
ul
li = link_to "La vie au camp", category_path("la-vie-au-camp")
li = link_to "Activités", category_path("activites")
li = link_to "Reportage photos", category_path("reportage-photos")
li = link_to "Portrait de résident", category_path("portrait-de-resident")
li = link_to "Conseils", category_path("conseils")
li = link_to "Lifehack", category_path("lifehack")
ul
- page_articles.each_with_index do |article, i|
li
h2 = link_to article.title, article
p
' Publié le
= I18n.l article.date, format: '%e %b %Y'
' par
= article.data.author
p = article.data.excerpt
= image_tag article.data.thumbnail
On peut ensuite créer les pages blog.html.slim
et category.html.slim
dans le dossier source/
. Les deux pages sont assez similaires, on pourrait d'ailleurs n'en créer qu'une et ajouter quelques conditions. L'avantage d'avoir deux pages distinctes c'est de pouvoir mieux les personnalisées par la suite.
Les pages catégories étant créées à la volée, on ne peut pas personnaliser facilement le bloc Frontmatter et donc le titre à afficher dans le header ce qui va nécessiter une petite astuce.
# blog.html.slim
---
title: "L'actualité du camp pour rester informé"
title_seo: "Blog du camp de vacances No Wifi Summercamp"
description: "Retrouvez l'actualité du camp, avec des reportages sur la vie au camp, sur les diverses activités de plein air, découvrez nos résidents, profitez de conseils..."
hero_image: blog.jpg
---
div role="main"
= partial "partials/header"
= partial "partials/articles-list"
= partial "partials/call-to-action"
La page blog contient donc uniquement le bloc Frontmatter. Pour la page category, l'astuce va consister à passer le nom de la catégorie au _partial _header.html.slim
qu'il faudra donc aller modifier.
# category.html.slim
---
hero_image: blog.jpg
---
div role="main"
= partial "partials/header", locals: {title: category}
= partial "partials/articles-list"
= partial "partials/call-to-action"
En passant la variable title
à _header
, on crée une variable locale qu'on va pouvoir tester. Dans le cas d'une catégorie, la variable title
est égale au nom de la catégorie et donc elle n'est pas nulle. Dans les autres cas, la variable est nulle et on peut donc lui assigner current_page.data.title
. Soit le fichier suivant :
/ partials/_header.html.slim
header
/ Set the title
- title = current_page.data.title if title.blank?
/ Check if it's the homepage
- if current_page.url == '/'
= image_tag "/images/logo-home.png", alt: "No Wifi Summercamp, camp de vacances en plein air"
p = current_page.data.slogan_sup
p = current_page.data.slogan
h1 = title
- else
h1 = title
Créer des articles
Nos pages sont prêtes, on va pouvoir maintenant créer des articles pour en vérifier le bon fonctionnement. On a configuré le blog de manière à ce que les articles se situent dans un dossier blog et soient dans un format année-mois-jour-titre. On pourrait aller les créer manuellement mais il y a bien sur une commande pour ça :
# depuis la racine du projet
$ middleman article "Titre de mon article"
Un nouveau fichier sera automatiquement créé dans le dossier blog à la date du jour et grâce au modèle de blog crée plus tôt le bloc Frontmatter est déjà en place avec le titre et la date.
Ecrire en markdown
On peut choisir le format dans lequel rédiger nos articles, on pourrait tout à fait les rédiger en HTML pur. Si vous connaissez ou utilisez déjà le Markdown, inutile de prêcher des convaincus, si non vous avez tout à gagner à rédiger les articles dans ce format.
C'est très simple à écrire, permet de se concentrer sur le contenu plutôt que la forme, et n'importe qui peut l'apprendre rapidement. Si vous ne connaissez la syntaxe cette cheatsheet est faite pour vous.
Pour les articles du projet, vous pouvez vous servir dans ce gist ou sur le dépot github du projet.
Ajouter une pagination
On a maintenant une liste d'articles qui s'affiche sur la page blog et pour chacune des catégories. Par contre il n'y a pas de pagination. Si on avait 200 articles, ils s'afficheraient tous sur la même page. De même il nous manque des liens en bas de pages pour naviguer plus facilement entre les articles.
Pour la pagination, il suffit simplement d'ajouter deux variables dans le Frontmatter des pages que l'on souhaite paginer. Rouvrez donc les fichiers blog.html.slim
et category.html.slim
et ajouter ce qui suit dans l'en-tête :
pageable : true
per_page: 20
Middleman va se charger de créer une nouvelle page tous les 20 articles. Maintenant il nous faut des liens pour naviguer vers les 20 articles suivants ou précédents.
per_page
permet d'écraser la valeur définie dans config.rb
( mise ici pour l'exemple), on pourrait ainsi avoir, pour la liste principale 20 articles et pour les catégories 30 articles.
On va ensuite ajouter ces liens dans le partial _articles-list.html.slim
, soit le fichier complet :
/_articles-list.html.slim
/ Variables for pagination
- locals = current_resource.metadata[:locals]
- prev_page = locals['prev_page']
- page_number = locals['page_number']
- num_pages = locals['num_pages']
- next_page = locals['next_page']
p Catégories :
ul
li = link_to "La vie au camp", category_path("la-vie-au-camp")
li = link_to "Activités", category_path("activites")
li = link_to "Reportage photo", category_path("reportage-photo")
li = link_to "Portrait de résident", category_path("portrait-de-resident")
li = link_to "Conseils", category_path("conseils")
li = link_to "Lifehack", category_path("lifehack")
ul
- page_articles.each_with_index do |article, i|
li
h2 = link_to article.title, article
p
' Publié le
= I18n.l article.date, format: '%e %b %Y'
' par
= article.data.author
p = article.data.excerpt
= image_tag article.data.thumbnail
- if num_pages > 1
nav role= "navigation"
- if prev_page
= link_to '< Billets récents', prev_page
span
' Page #{page_number}
' sur #{num_pages}
- if next_page
= link_to 'Billets anciens >', next_page
Reste à ajouter les liens de navigation inter-articles, cette fois dans le layout blog.slim
à la suite de = yield
:
/ blog.slim
nav role= "navigation"
ul
li
- prev_article = current_article.previous_article
- if prev_article
= link_to prev_article.title, prev_article.url,
rel: 'prev', title: "Article précédent: #{prev_article.title}"
li
- next_article = current_article.next_article
- if next_article
= link_to next_article.title, next_article.url,
rel: 'next', title: "Article suivant: #{next_article.title}"
Ajouter des commentaires avec Disqus
Le blog est prêt ! On peut créer facilement de nouveaux billets, les lister et les catégoriser, mais il nous manque encore les commentaires.
Puisqu'on est sur un système statique, l'ajout de commentaires ne peut passer que par un système tiers. Il en existe plusieurs, chacun a ses avantages et inconvénients et répond ou non aux attentes. Le plus simple à mettre en œuvre pour Middleman c'est Disqus puisqu'une gem est là pour faire le travail pour nous.
Si vous n'avez pas de compte Disqus, il est nécessaire d'en créer un et de déclarer le site (dans l'onglet moderation). Ajouter ensuite la gem dans le Gemfile
:
# Gemfile
gem "middleman-disqus"
Puis en ligne de commande :
$ bundle install
La configuration de Disqus se fait dans le fichier config.rb
où on va ajouter ce qui suit :
# config.rb
activate :disqus do |d|
d.shortname = 'nowifisummercamp' # Remplacer par votre nom Disqus
end
Disqus est activé, il ne reste plus qu'à ajouter les commentaires au blog en ajoutant ce qui suit dans le layout blog.slim
après les liens de navigations :
/layouts/blog.slim
= disqus
On arrive à la fin de la partie "contenu et fonctionnalités". Les pages du sites sont rédigées, on a un blog avec des commentaires, il nous manque un peu d'habillage CSS et on pourra mettre le tout en ligne.
Retrouvrez tous les fichiers dans ce gist (sauf les billets de blog, voir plus haut)
Je suis disponible pour des missions longues / CDD / CDI Cliquez pour en savoir plus