Manuel · 6

Templates – les bases

Le HTML des pages, le Head, le titre SEO, la description et les Snippets sont des templates. La syntaxe correspond largement à Twig ou Django (pongo2).

Sortie

{{ page.title }}
{{ post.titel|upper }}
{{ preis|floatformat:2 }} €
{{ beschreibung|default:"Keine Beschreibung" }}

Les sorties sont automatiquement échappées en HTML – < devient &lt;. Cela protège contre un balisage cassé et l’injection de code. Pour du HTML qui doit vraiment apparaître comme HTML :

  • Champs HTML : {{ post.inhalt|safe }}
  • Champs Markdown : {{ post.text|markdown }}

Conditions et boucles

{% if page.slug == "kontakt" %}
  …
{% elif route.query.seite %}
  …
{% else %}
  …
{% endif %}

{% for p in data("team") %}
  <li class="{% if forloop.First %}erste{% endif %}">{{ forloop.Counter }}. {{ p.name }}</li>
{% empty %}
  <li>Noch niemand da.</li>
{% endfor %}

Dans les boucles, forloop.Counter (à partir de 1), forloop.Counter0 (à partir de 0), forloop.First, forloop.Last et forloop.Revcounter sont disponibles.

Définir des variables

{% with post=item("blog", "slug", route.slug) %}
  <h1>{{ post.titel }}</h1>
{% endwith %}

Commentaires

{# N’est pas affiché #}

Espaces

Les balises de template ne modifient ni les espaces ni les sauts de ligne – le texte est émis exactement tel qu’il est écrit (comme avec Twig). Hallo {% if name %}{{ name }}{% endif %}! conserve l’espace après « Hallo ».

Afficher la syntaxe de template : verbatim

Si vous avez besoin de {{ … }} littéralement – par exemple pour Vue, Alpine ou Handlebars –, entourez la zone :

{% verbatim %}<div id="app">{{ nachricht }}</div>{% endverbatim %}

L’outil d’import ajoute verbatim automatiquement si l’original contient de telles séquences de caractères.

Variables disponibles

Variable Contenu
page.title, page.meta_title, page.slug, page.path, page.description, page.id, page.parent_id Page actuelle (meta_title et description sont déjà évalués)
page.noindex, page.nofollow Paramètres robots de la page (true/false)
page.lang Langue effective de la page – propre ou héritée, sinon de (voir Sites multilingues)
route.path Chemin demandé
route.slug Sous-chemin des pages Catch-All, p. ex. "mein-artikel" ou "2025/rueckblick"
route.rest Sous-chemin sous forme de liste : route.rest.0, route.rest.1 …
route.query.x Paramètre de requête ?x=…
today Date du jour au format AAAA-MM-JJ – adaptée aux champs de date, p. ex. data("events", "datum__gte", today) pour les événements à venir
now Instant actuel pour le filtre date : {{ now|date:"2006" }} (année du copyright)
site.title, site.id, site.domain, site.domains, site.favicon Le site actuel (sa page d’accueil) – site.domain est le premier domaine saisi, site.favicon l’URL de l’icône du site
preview true dans l’aperçu de l’admin

Fonctions

Fonction Résultat
nav() Sous-pages publiées de la page d’accueil du site actuel (menu principal) – sans les pages avec Masquer dans les menus ; nav(true) avec elles
children() / children(12) Sous-pages publiées de la page actuelle ou de la page 12 – sans les pages masquées ; children(true) / children(12, true) avec elles
lang_root() / lang_root(12) Page d’accueil de l’arborescence linguistique de la page actuelle ou de la page 12 : la page elle-même ou la plus proche au-dessus avec sa propre langue, sinon la page d’accueil du site – pour les menus par langue : children(lang_root().id)
data("slug", …) Entrées d’une Collection ou résultat d’une source REST (voir Données)
item("slug", "feld", wert) Première entrée avec feld == wert – ou rien
workflow("pfad", …) Résultat d’un Workflow avec une entrée HTTP sous ce chemin
image(id, sizes, klasse) <img> responsive avec srcset, dimensions et texte alternatif – pour JPEG/PNG dans un <picture> avec WebP
file(id) Infos sur le fichier : .url, .name, .alt, .width, .height, .srcset, .webp_srcset, .mime, .size
asset_url(id) URL versionnée d’un fichier CSS/JS
translations() / translations(entrée) Versions linguistiques publiées de la page ou d’une entrée, triées par code de langue : chacune avec lang, title, url, current – pour les sélecteurs de langue
language_name("fr") Nom d’une langue dans cette langue (« Français », « Deutsch » …) ; les codes inconnus restent tels quels
not_found() Termine le rendu avec la page 404 (statut 404)

Chaque page issue de nav()/children() (et lang_root()) possède title, path, slug, id, description et lang, ainsi que hidden (Masquer dans les menus). Exemple de pied de page avec mentions légales et politique de confidentialité, absentes du menu principal :

<footer>{% for p in nav(true) %}{% if p.hidden %}<a href="{{ p.path }}">{{ p.title }}</a> {% endif %}{% endfor %}</footer>

Filtres utiles

Filtre Exemple
default {{ x|default:"–" }}
upper, lower, title, capfirst {{ name|upper }}
truncatechars, truncatewords {{ text|truncatechars:120 }}
floatformat {{ preis|floatformat:2 }}
length {{ liste|length }}
join {{ tags|join:", " }}
safe Afficher du HTML sans filtrage
markdown Markdown vers HTML (markdown:"html" laisse passer le HTML intégré – voir ci-dessous)
json Valeur en JSON, p. ex. pour JavaScript : <script>const cfg = {{ cfg|json }};</script>
urlencode <a href="/suche?q={{ q|urlencode }}">

Markdown directement dans le HTML

Les textes longs s’écrivent plus confortablement en Markdown – même au beau milieu du HTML d’une page ou d’un Snippet. Entourez la zone de {% filter markdown %} :

<main class="container">
{% filter markdown %}
# Über uns

Wir gestalten und entwickeln **Websites mit Haltung** – von der Idee bis zum Betrieb.
Mehr dazu unter [Leistungen](/leistungen) – das Team von {{ site.title }} freut sich auf dich.

- Beratung
- Umsetzung
{% endfilter %}
</main>
  • Les variables et balises de template fonctionnent à l’intérieur du bloc.
  • Les titres reçoivent des ancres pour les liens de saut ; les trémas sont transcrits : « Über uns » → #ueber-uns, « Größe » → #groesse.
  • HTML dans le Markdown : le filtre normal rejette le HTML intégré (<div …>), car il traite aussi des contenus de Collections et de sources REST qui peuvent venir de l’extérieur. Pour les textes que vous écrivez vous-même dans l’éditeur, {% filter markdown:"html" %} laisse passer le HTML – par exemple pour une <div class="hinweis"> entre deux paragraphes. Pour les données venant de l’extérieur, |markdown reste le choix sûr.

Pens – bacs à sable

Sous Pens, vous créez de petits bacs à sable – comme sur CodePen : HTML (avec toutes les possibilités des templates : data(), item(), workflow(), filtres …), CSS et JS côte à côte, avec le résultat en dessous, en direct pendant la saisie. Idéal pour essayer des templates avec de vraies données, pour des prototypes ou de petits microsites.

  • Chaque Pen a sa propre adresse, impossible à deviner : /cms-admin/pen/<uuid>. Une fois connecté, elle ouvre l’éditeur (plein écran), Ctrl+S enregistre. En haut, vous changez la disposition – Code en haut (côte à côte) ou Code à côté (empilé à gauche, résultat à droite) –, Plein écran n’affiche que le résultat sur tout l’écran (Esc pour quitter).
  • Public (interrupteur en haut) : sans connexion, la même adresse affiche le résultat et, à côté, le code – en lecture seule, dans des onglets HTML/CSS/JS. Avec Afficher le code désactivé, l’adresse devient une page autonome : uniquement le résultat, avec le titre du Pen – pratique pour des pages uniques rapides. Les Pens non publics n’existent pas pour les visiteurs (404). En tant qu’administrateur, vous voyez la vue des visiteurs via Vue visiteur (nouvel onglet, ?view=1).
  • Les Pens sont toujours noindex, nofollow (balise meta et en-tête X-Robots-Tag) et n’apparaissent dans aucun sitemap.
  • Le résultat s’exécute dans un bac à sable avec sa propre origine – les scripts du Pen n’ont pas accès à votre session d’admin.
  • Pour les visiteurs, seules les entrées de Collection publiées sont utilisées ; dans l’éditeur, comme dans l’aperçu, vous voyez aussi les brouillons. site et nav() se rapportent au site du domaine appelé.
  • Les Pens font partie des Bundles ; ils n’ont pas d’historique des versions.