Logo de Cecil Cecil
Sur cette page

Contenu dynamique

Par défaut, le corps d’une page est statique : la syntaxe Twig écrite dans un fichier Markdown est affichée telle quelle.

Vous pouvez créer du contenu dynamique dans une page en utilisant la fonction Twig template_from_string, qui interprète le contenu de la page comme un template Twig.

{{ include(template_from_string(page.content, "contenu dynamique pour la page " ~ page.id)) }}

Avec cette approche, vous pouvez utiliser n’importe quelle variable de page dans le body de la page.

---
var: 'value'
---
La valeur de `var` est {{ page.var }}.

Activer le contenu dynamique

La méthode recommandée consiste à créer un layout dédié qui surcharge le bloc content, et à ne l’utiliser que pour les pages qui en ont besoin.

{# layouts/dynamic.html.twig #}
{% extends '_default/page.html.twig' %}

{% block content %}
{{ include(template_from_string(page.content, "contenu dynamique pour la page " ~ page.id)) }}
{% endblock content %}

Puis définissez la variable layout dans le front matter de la page :

---
title: "Ma page dynamique"
layout: dynamic
---

Variables disponibles

Le contenu de la page est rendu avec le même contexte que le layout, vous pouvez donc utiliser :

  • les variables de page : page.title, page.date, page.<variable personnalisée>, etc.
  • les variables du site : site.title, site.pages, site.data, etc.
  • toutes les fonctions, filtres et tris disponibles dans les templates ;
  • les tags Twig : {% set %}, {% if %}, {% for %}, {% include %}, etc.

Fonctionnement

Le corps Markdown est d’abord converti en HTML, puis le résultat (page.content) est rendu par Twig. Cet ordre a quelques conséquences :

  • Markdown échappe les caractères < et >, les opérateurs de comparaison (>, <=) et les fonctions fléchées (=>) ne peuvent donc pas être utilisés dans le corps : le build échoue avec une erreur Unexpected character "&".
  • Une expression Twig utilisée dans un attribut HTML (ex. : href="{{ url(post) }}") est encodée (URL) par le convertisseur Markdown et ne sera pas évaluée.
  • Une expression Twig seule sur sa ligne est encapsulée dans un élément <p>.
  • La syntaxe Twig écrite dans un bloc ou une portion de code est également évaluée.

Pour afficher la syntaxe Twig telle quelle, encadrez-la avec le tag verbatim :

{% verbatim %}`{{ page.title }}`{% endverbatim %}

Pour éviter un élément <p> superflu autour d’un bloc HTML, encadrez l’expression dans un élément HTML, séparé par des retours à la ligne :

<div>
{{ include('partials/latest-posts.html.twig') }}
</div>

Exemple : variables, données et template partiel

Cet exemple montre une page affichant des variables du site et de la page, des données issues d’un fichier de données, ainsi que les derniers articles du blog via un template partiel réutilisable.

Fichier de données :

# data/team.yml
- name: Alice
  role: Développeuse
- name: Bob
  role: Designer

Template partiel, qui reçoit section et limit en paramètres :

{# layouts/partials/latest-posts.html.twig #}
{% set posts = site.pages.showable|filter_by('section', section|default('blog'))|sort_by_date|slice(0, limit|default(5)) %}
{% if posts|length > 0 %}
<ul class="latest-posts">
  {% for post in posts %}
  <li><a href="{{ url(post) }}">{{ post.title }}</a> <time datetime="{{ post.date|date('Y-m-d') }}">{{ post.date|format_date('long') }}</time></li>
  {% endfor %}
</ul>
{% else %}
<p>Aucun article pour le moment.</p>
{% endif %}

Page :

---
title: À propos
layout: dynamic
---
Bienvenue sur **{{ site.title }}** ! Cette page a été publiée le {{ page.date|format_date('long') }}.

Notre équipe compte {{ site.data.team|length }} membres : {{ site.data.team|column('name')|join(', ') }}.

## Derniers articles

<div>
{{ include('partials/latest-posts.html.twig', {section: 'blog', limit: 3}) }}
</div>

Résultat :

<p>Bienvenue sur <strong>Mon site</strong> ! Cette page a été publiée le 9 octobre 2026.</p>
<p>Notre équipe compte 2 membres : Alice, Bob.</p>
<h2 id="derniers-articles">Derniers articles</h2>
<div>
<ul class="latest-posts">
  <li><a href="/blog/post-3/">Post 3</a> <time datetime="2026-03-01">1 mars 2026</time></li>
  <li><a href="/blog/post-2/">Post 2</a> <time datetime="2026-02-01">1 février 2026</time></li>
  <li><a href="/blog/post-1/">Post 1</a> <time datetime="2026-01-01">1 janvier 2026</time></li>
</ul>
</div>

Exemple : shortcodes avec des macros

Les macros Twig peuvent être utilisées comme shortcodes pour insérer des fragments HTML riches dans le corps d’une page.

Créez les macros :

{# layouts/macros/shortcodes.html.twig #}
{% macro youtube(id, title = 'Vidéo YouTube') %}
<iframe src="https://www.youtube-nocookie.com/embed/{{ id }}" title="{{ title }}" width="560" height="315" loading="lazy" allowfullscreen></iframe>
{% endmacro %}

{% macro alert(message, type = 'info') %}
<div class="alert alert-{{ type }}" role="alert">{{ message }}</div>
{% endmacro %}

Créez un layout qui importe les macros avant de rendre le contenu :

{# layouts/shortcodes.html.twig #}
{% extends '_default/page.html.twig' %}

{% block content %}
{% set imports = "{% import 'macros/shortcodes.html.twig' as sc %}" %}
{{ include(template_from_string(imports ~ page.content, "contenu dynamique pour la page " ~ page.id)) }}
{% endblock content %}

Utilisez les shortcodes dans une page :

---
title: "Vidéo de démo"
layout: shortcodes
---
<div>
  {{ sc.alert('Cette vidéo est en anglais.', 'warning') }}
</div>

## Démo

<div>
  {{ sc.youtube('NaB8JBfE7DY', 'Démo de Cecil') }}
</div>

Résultat :

<div>
  <div class="alert alert-warning" role="alert">Cette vidéo est en anglais.</div>
</div>
<h2 id="demo">Démo</h2>
<div>
  <iframe src="https://www.youtube-nocookie.com/embed/NaB8JBfE7DY" title="Démo de Cecil" width="560" height="315" loading="lazy" allowfullscreen></iframe>
</div>