Aller au contenu

#Filtres

Un filtre transforme une valeur avant de l’écrire : {{ x | filtre: argument }}. Webcosa en ajoute sept aux filtres standard de Liquid, et ces sept-là sont ceux qu’un thème de site vitrine utilise vraiment. Cette page donne, pour chacun, sa signature, ce qu’il fait, une entrée et la sortie exacte.

Les sorties ci-dessous ont été obtenues en exécutant le moteur, pas en le lisant. La source est la fonction ajouterFiltres() de src/lib/liquid/moteur.ts : si un filtre y est ajouté ou retiré, c’est elle qui fait foi, pas cette page.

#Les filtres maison

FiltreEntrée → sortie
asset_url'theme.css'/theme-assets/8f2c…/theme.css
stylesheet_tagune adresse → une balise link complète
teinte: n'#3366cc' | teinte: 40#85a3e0
lignesun texte multiligne → le même, avec des br
date_fr'2026-03-08T10:00:00Z'8 mars 2026
handle'Prêt-à-Porter n°3'pret-a-porter-n-3
escapea<b&ca&lt;b&amp;c

#asset_url

Fabrique l’adresse servie d’un fichier d’assets/. Il prend le nom seul du fichier — jamais son chemin.

entréechaînerequis

Le nom du fichier tel qu’il apparaît dans assets/, extension comprise, sans le dossier.

Entrée et sortieliquid
{{ 'theme.css' | asset_url }}
→ /theme-assets/8f2c1b40-…/theme.css
Danger

Le segment assets/ n’apparaît PAS dans l’adresse produite. La route est /theme-assets/<id>/<fichier> — un seul segment de nom — et c’est elle qui remet le préfixe assets/ pour interroger la base.

Écrire {{ 'assets/theme.css' | asset_url }} fabrique une adresse à deux segments qui ne correspond à aucune route. La feuille de style répond 404, et la page rend quand même : du HTML nu, sans style. C’est exactement le bug qui a tenu, sur tous les sites à thème Liquid à la fois, sans jamais lever d’erreur. Un thème sans CSS ressemble à un thème mal écrit, pas à une adresse fausse — voilà pourquoi personne ne l’a vu.

La forme correcte, et la seule : le nom du fichier, rien d’autre.

Le filtre lit theme_base dans le contexte. Hors du rendu d’un site — dans un essai isolé, par exemple — theme_base est absent et la sortie tombe à /theme.css. Ce n’est pas une erreur du filtre, c’est un contexte incomplet.

#stylesheet_tag

Enveloppe une adresse dans une balise link. Il s’enchaîne avec asset_url, et c’est ainsi que les quatre thèmes livrés chargent leur feuille de style.

layout/theme.liquidliquid
{{ 'theme.css' | asset_url | stylesheet_tag }}
Sortiehtml
<link rel="stylesheet" href="/theme-assets/8f2c1b40-…/theme.css">

L’adresse est échappée au passage. Le filtre ne prend aucun argument : ni media, ni preload. Si tu as besoin d’autre chose, écris la balise à la main autour de asset_url.

#teinte

Éclaircit ou assombrit une couleur hexadécimale.

entréecouleur hexadécimale à six chiffresrequis

#3366cc ou 3366cc. Les formes courtes (#36c), les noms de couleur et les notations rgb() ou oklch() ne sont pas reconnues : la valeur est alors rendue inchangée.

deltanombre entre -100 et 100défaut : 0

Positif, la couleur est éclaircie — elle se rapproche du blanc. Négatif, elle est assombrie — elle se rapproche du noir. La valeur est un pourcentage du chemin restant : teinte: 100 rend du blanc pur, teinte: -100 du noir pur.

Entrée et sortieliquid
{{ '#3366cc' | teinte: 40 }}    → #85a3e0
{{ '#3366cc' | teinte: -40 }}   → #1f3d7a
{{ '#3366cc' | teinte: 0 }}     → #3366cc
{{ 'bleu'    | teinte: 40 }}    → bleu

Ce filtre est la raison pour laquelle un panneau de réglages Webcosa tient en cinq couleurs au lieu de vingt. Sans lui, chaque nuance d’une couleur réglable — le survol d’un bouton, le fond d’une carte, la bordure d’un champ — devrait être un réglage de plus. Vingt sélecteurs de couleur dans un panneau, personne ne les remplit : le client en règle trois, laisse les autres à leur défaut, et obtient un site incohérent qu’il croit mal conçu.

layout/theme.liquid — Origoliquid
:root {
  --accent: {{ settings.accent }};
  --accent-sombre: {{ settings.accent | teinte: -18 }};
  --accent-clair: {{ settings.accent | teinte: 88 }};
}

Un seul réglage de couleur, trois variables CSS, et toute la palette d’accent du site suit quand le client change d’avis.

#lignes

Transforme les sauts de ligne en balises br, après avoir échappé le HTML. C’est le filtre à appliquer à tout texte multiligne saisi par le client : une adresse postale, des horaires.

Entrée et sortie
entrée   12 rue des Lilas ⏎ 75011 Paris
sortie   12 rue des Lilas<br>75011 Paris

entrée   a<b ⏎ c
sortie   a&lt;b<br>c
sections/contact.liquid — Origoliquid
{%- if section.settings.adresse != blank -%}
  <div><dt>Adresse</dt><dd>{{ section.settings.adresse | lignes }}</dd></div>
{%- endif -%}

L’ordre compte : l’échappement a lieu avant l’insertion des br, donc les balises produites survivent et le contenu saisi ne peut pas en fabriquer. Un client qui tape <b>gras</b> dans le champ Adresse verra les chevrons, pas du gras — c’est le comportement voulu pour un champ textarea. Pour du texte formaté, c’est un réglage richtext qu’il faut déclarer.

#date_fr

Formate une date en français, sans dépendance.

Entrée et sortieliquid
{{ '2026-03-08T10:00:00Z' | date_fr }}   → 8 mars 2026
{{ '' | date_fr }}                       → (rien)
{{ 'pas une date' | date_fr }}           → (rien)

Le style est long (8 mars 2026), le fuseau est Europe/Paris, la langue est fr-FR — les trois sont fixes et ne se règlent pas. Une entrée illisible rend une chaîne vide plutôt qu’Invalid Date : mieux vaut une ligne manquante qu’un message d’erreur en anglais dans le pied d’une carte d’article.

Attention

En pratique, {{ article.date | date_fr }} rend aujourd’hui du vide sur tous les sites, parce que articles[].date n’est pas encore rempli par le rendu public. Le filtre est correct ; c’est sa matière qui manque. Voir la description du champ.

#handle

Réduit un texte à un identifiant utilisable en ancre ou en classe CSS : minuscules, accents retirés, tout le reste remplacé par des tirets, tirets de bord supprimés.

Entrée et sortieliquid
{{ 'Prêt-à-Porter n°3'        | handle }}  → pret-a-porter-n-3
{{ 'Élagage & Taille — 100 %' | handle }}  → elagage-taille-100
Un titre de section devient son ancreliquid
<h2 id="{{ section.settings.titre | handle }}">{{ section.settings.titre }}</h2>

Aucun des quatre thèmes livrés ne s’en sert : ils écrivent leurs ancres en dur (id="contact", id="journal"), ce qui est plus sûr quand l’ancre doit rester stable même si le client change le titre. handle sert quand l’identifiant doit suivre un contenu variable — les blocs d’une FAQ, par exemple.

#escape

Échappe le HTML. Explicite, comme chez Shopify : Liquid n’échappe rien par défaut.

Entrée et sortieliquid
{{ '<b>x</b>' | escape }}   → &lt;b&gt;x&lt;/b&gt;

Il échappe cinq caractères : &, <, >, " et ' — cette dernière en &#39;, comme le fait LiquidJS. Un attribut délimité par des apostrophes est donc protégé au même titre qu’un attribut à guillemets doubles.

Astuce

Prends quand même l’habitude des guillemets doubles pour tous tes attributs : c’est la convention des quatre thèmes livrés, et un attribut à guillemets doubles reste lisible quand le contenu porte une apostrophe française.

Où l’appliquer, concrètement : sur tout contenu saisi par le client qui atterrit dans un attribut — un alt, un title, un value. Dans le corps du document, un thème qui vient de nous ou du propriétaire du site peut se passer d’échapper ; c’est une décision à revoir le jour où des thèmes de tiers circuleront. Voir le bac à sable.

snippets/image.liquid — Origoliquid
<img
  src="{{ src }}"
  alt="{{ alt | default: '' | escape }}"
  loading="{{ loading | default: 'lazy' }}"
  decoding="async">

#Les filtres de Liquid

Tous les filtres standard de LiquidJS sont disponibles. Voici ceux que les thèmes livrés utilisent réellement — c’est un bon indicateur de ce dont un thème de site vitrine a besoin.

FiltreCe qu’il faitVu dans
default: vremplace une valeur vide, nulle ou faussepartout, 52 fois
replace: a, bremplace toutes les occurrencestel: sans espaces
split: sdécoupe une chaîne en tableaulistes saisies en une ligne
slice: i, nextrait une portioninitiales d’un nom
prepend: scolle devantpréfixes d’adresse
plus: nadditionnenumérotation
sections/entete.liquid — Origoliquid
<a class="entete-tel" href="tel:{{ section.settings.telephone | replace: ' ', '' }}">
  {{ section.settings.telephone }}
</a>

Le numéro est affiché tel qu’il a été saisi, espaces compris, et le lien tel: en est débarrassé. Deux usages de la même valeur, une seule saisie.

Le reste du catalogue standard répond aussi : upcase, downcase, capitalize, strip, truncate, truncatewords, size, first, last, join, sort, uniq, map, where, reverse, date, round, ceil, floor, minus, times, divided_by, modulo, newline_to_br, strip_html, json, slugify… La liste complète est chez LiquidJS, et elle fait autorité pour tout ce que cette page ne redit pas.

Note

escape est le seul filtre standard que Webcosa remplace. Tous les autres se comportent comme LiquidJS les décrit.

#Un filtre inconnu ne lève pas d’erreur

Le moteur tourne avec strictFilters désactivé. Un filtre qui n’existe pas rend la valeur inchangée, sans un mot.

Trois filtres Shopify qui n’existent pas iciliquid
{{ 'accueil'  | t }}                    → accueil
{{ image      | img_url: '400x' }}      → (la valeur d'origine)
{{ 1000       | money }}                → 1000

C’est le bon comportement en production — une faute de frappe ne doit pas éteindre une page — et c’est le piège classique quand on transpose un thème Shopify : le code paraît fonctionner, la page rend, et les valeurs traversent les filtres sans être transformées. Si un montant s’affiche 1000 au lieu de 10,00 €, ce n’est pas que le filtre a échoué, c’est qu’il n’existe pas. La liste de ce qui manque et pourquoi est sur la page des absents.