Liquid: основы
Шаблон блока — это Liquid. Вы пишете разметку, а вместо конкретных заголовков, ссылок и картинок подставляете переменные: значения приходят из полей блока, заполненных на странице.
<section class="hero"> <h1>{{ props.title }}</h1> {% if props.subtitle != '' %}<p>{{ props.subtitle }}</p>{% endif %}</section>Один шаблон — сколько угодно наборов значений: тот же блок на десяти страницах выглядит по-разному, а разметка правится в одном месте.
Где Liquid работает, а где нет
Заголовок раздела «Где Liquid работает, а где нет»| Часть блока | Liquid |
|---|---|
Шаблон (template) |
да |
| CSS блока | нет — отдаётся как есть |
| JS блока | нет — отдаётся как есть |
| Шаблон макета | да, но контекст другой — см. Что доступно в контексте |
Переменную в CSS не подставить. Нужен параметр из поля — выводите его инлайн-стилем в шаблоне или классом-модификатором:
<div class="hero hero--{{ props.theme | default: 'light' }}" style="max-width: {{ props.max_width | default: '800px' }}">Три конструкции
Заголовок раздела «Три конструкции»Вывод — двойные фигурные скобки. Результат подставляется в HTML как есть, автоматического экранирования нет:
{{ props.title }}{{ props.title | escape }} {# если в поле может оказаться разметка #}Теги — управляющие конструкции в {% %}:
{% if props.show_button %} <a href="{{ props.url }}">{{ props.text }}</a>{% endif %}Фильтры — преобразование значения после |, их можно выстраивать цепочкой:
{{ props.title | strip | truncate: 60 | upcase }}Условия
Заголовок раздела «Условия»{% if props.title != '' %}…{% elsif props.subtitle != '' %}…{% else %}…{% endif %}{% unless props.hide_header %}…{% endunless %}
{% case props.size %} {% when 'sm' %}<div class="card card--sm"> {% when 'lg' %}<div class="card card--lg"> {% else %}<div class="card">{% endcase %}Операторы: ==, !=, >, <, >=, <=, and, or, contains.
{% for slide in props.slides %} <div class="slide slide--{{ forloop.index }}"> <h3>{{ slide.title }}</h3> {% if forloop.first %}<span class="badge">Новинка</span>{% endif %} </div>{% else %} <p>Слайды не добавлены</p>{% endfor %}Внутри цикла элемент адресуется без префикса props — переменной цикла
(slide.title). Доступны forloop.index, forloop.index0, forloop.first,
forloop.last, forloop.length; работают {% break %} и {% continue %}.
Индекс и диапазон тоже поддерживаются: {{ props.slides[0].title }},
{% for i in (1..3) %}.
Переменные внутри шаблона
Заголовок раздела «Переменные внутри шаблона»{% assign css_class = 'hero hero--' | append: props.theme %}{% capture button_label %}{{ props.text }} →{% endcapture %}
<div class="{{ css_class }}"><a>{{ button_label }}</a></div>Фильтры, доступные везде
Заголовок раздела «Фильтры, доступные везде»Эти 55 фильтров работают одинаково и в предпросмотре, и при публикации.
| Группа | Фильтры |
|---|---|
| Строки | append prepend capitalize upcase downcase strip lstrip rstrip strip_html strip_newlines newline_to_br replace replace_first replace_last remove remove_first remove_last slice split truncate truncatewords escape escape_once url_encode url_decode |
| Числа | plus minus times divided_by modulo abs ceil floor round at_least at_most |
| Массивы | size first last join sort sort_natural reverse uniq compact concat map sum where reject find find_index has |
| Прочее | default date |
Пример работы date с полем типа date:
{{ props.published_at | date: '%d.%m.%Y' }}{{ 'now' | date: '%Y' }}Управление пробелами
Заголовок раздела «Управление пробелами»Дефис внутри скобок съедает пробелы и переносы с этой стороны — разметка остаётся читаемой, а вывод чистым:
{%- for tag in props.tags -%} <span>{{- tag.name -}}</span>{%- endfor -%}Комментарии и «сырой» вывод
Заголовок раздела «Комментарии и «сырой» вывод»{% comment %} Пояснение, в HTML не попадёт {% endcomment %}{% raw %}{{ этот_текст_не_рендерится }}{% endraw %}Чего в шаблоне нет
Заголовок раздела «Чего в шаблоне нет»{% include %}, {% render %}, {% layout %} и любые другие подключения файлов
не работают: шаблон блока самодостаточен, файловой системы шаблонов у движка нет.
Общий кусок разметки не выносится в партиал — он либо копируется, либо становится
отдельным блоком.
Что происходит при ошибке в шаблоне
Заголовок раздела «Что происходит при ошибке в шаблоне»Ошибку синтаксиса или рендеринга блок не роняет наружу: вместо разметки блока на страницу попадает HTML-комментарий, а публикация продолжается.
<!-- Liquid render error: Expected Identifier, got | -->У макета поведение обратное: ошибка в шаблоне макета останавливает публикацию с сообщением, потому что страница без макета бессмысленна.
- Что доступно в контексте — полный перечень переменных.
- Различия сервера и браузера — где предпросмотр врёт.
- Схема полей — какие поля вообще бывают и что попадает
в
props.
Источники: backend/src/Publishing/BlockRenderer.php,
backend/src/Publishing/LayoutRenderer.php, front/src/lib/liquid.ts,
keepsuit/liquid (src/Filters/StandardFilters.php, src/Extensions/StandardExtension.php),
liquidjs@10.