#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
| Filtre | Entrée → sortie |
|---|---|
asset_url | 'theme.css' → /theme-assets/8f2c…/theme.css |
stylesheet_tag | une adresse → une balise link complète |
teinte: n | '#3366cc' | teinte: 40 → #85a3e0 |
lignes | un 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 |
escape | a<b&c → a<b&c |
#asset_url
Fabrique l’adresse servie d’un fichier d’assets/. Il prend le nom seul du
fichier — jamais son chemin.
entréechaînerequisLe nom du fichier tel qu’il apparaît dans assets/, extension comprise, sans le
dossier.
{{ 'theme.css' | asset_url }}
→ /theme-assets/8f2c1b40-…/theme.cssLe 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.
{{ 'theme.css' | asset_url | stylesheet_tag }}<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 : 0Positif, 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.
{{ '#3366cc' | teinte: 40 }} → #85a3e0
{{ '#3366cc' | teinte: -40 }} → #1f3d7a
{{ '#3366cc' | teinte: 0 }} → #3366cc
{{ 'bleu' | teinte: 40 }} → bleuCe 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.
: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 12 rue des Lilas ⏎ 75011 Paris
sortie 12 rue des Lilas<br>75011 Paris
entrée a<b ⏎ c
sortie a<b<br>c{%- 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.
{{ '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.
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.
{{ 'Prêt-à-Porter n°3' | handle }} → pret-a-porter-n-3
{{ 'Élagage & Taille — 100 %' | handle }} → elagage-taille-100<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.
{{ '<b>x</b>' | escape }} → <b>x</b>Il échappe cinq caractères : &, <, >, " et ' — cette dernière en
', comme le fait LiquidJS. Un attribut délimité par des apostrophes est
donc protégé au même titre qu’un attribut à guillemets doubles.
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.
<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.
| Filtre | Ce qu’il fait | Vu dans |
|---|---|---|
default: v | remplace une valeur vide, nulle ou fausse | partout, 52 fois |
replace: a, b | remplace toutes les occurrences | tel: sans espaces |
split: s | découpe une chaîne en tableau | listes saisies en une ligne |
slice: i, n | extrait une portion | initiales d’un nom |
prepend: s | colle devant | préfixes d’adresse |
plus: n | additionne | numérotation |
<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.
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.
{{ 'accueil' | t }} → accueil
{{ image | img_url: '400x' }} → (la valeur d'origine)
{{ 1000 | money }} → 1000C’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.

