Что доступно в контексте
Контекст шаблона в PageCraft маленький и закрытый: в нём ровно то, что перечислено на этой странице. Обращение к чему-то ещё не вызывает ошибки — оно просто выводит пустую строку, поэтому опечатка выглядит как «блок отрендерился, но текста нет».
Шаблон блока
Заголовок раздела «Шаблон блока»| Переменная | Когда есть | Что внутри |
|---|---|---|
props.* |
всегда | значения полей схемы блока |
content |
только у markdown-блоков | HTML, полученный из markdown-редактора |
data.* |
только у блоков со слотами данных | живые данные витрины |
Больше в контексте блока нет ничего. Ни названия страницы, ни адреса сайта, ни переменных сайта — это не «пока не сделано», а сознательная граница: блок переносим между страницами и сайтами, поэтому он не знает, куда его поставили.
props.* — поля схемы
Заголовок раздела «props.* — поля схемы»Каждое поле схемы блока становится ключом внутри props, вложенность повторяет
схему:
{{ props.title }} {# поле text #}{{ props.button.label }} {# поле object #}{% for item in props.items %} {# поле array #} {{ item.title }} — {{ item.url }} {# внутри цикла — без props #}{% endfor %}{% if props.is_wide %}wide{% endif %} {# поле switch: true/false #}Что попадает в значения — зависит от типа поля: switch даёт true/false,
select и radio — строку value варианта, image — URL файла, остальные типы —
строку. Полный разбор типов — Схема полей.
content — markdown-блок
Заголовок раздела «content — markdown-блок»У блока с типом «markdown» текст из WYSIWYG-редактора конвертируется в HTML
и кладётся в корневую переменную content — без префикса props:
<article class="post" style="max-width: {{ props.max_width | default: '800px' }}"> {{ content }}</article>Вставлять как есть: там уже готовый HTML, экранировать его не нужно. Остальные поля
схемы у такого блока живут в props обычным образом. Подробности —
Markdown в блоках.
data.* — живые данные витрины
Заголовок раздела «data.* — живые данные витрины»Если блок объявил в схеме bindingSlots, каждый слот доступен в шаблоне по своему
имени внутри data:
{% for product in data.products.items %} <a class="card" href="{{ product.url }}"> <img src="{{ product.image }}" alt="{{ product.name }}" loading="lazy"> <span>{{ product.name }}</span> <b>{{ product.price }}</b> </a>{% endfor %}<p>Всего: {{ data.products.total }}</p>Форма данных описана типом результата слота, а не вами: product_list всегда
устроен одинаково, откуда бы товары ни пришли.
Шаблон макета
Заголовок раздела «Шаблон макета»У макета контекст другой — он знает о странице и сайте:
| Переменная | Что внутри |
|---|---|
content |
HTML всех блоков страницы по порядку |
blocks_css |
CSS всех блоков страницы, склеенный |
blocks_js |
JS всех блоков страницы, склеенный |
page.id |
числовой идентификатор страницы |
page.slug |
адрес страницы |
page.title |
название страницы |
page.meta_title |
SEO-заголовок |
page.meta_description |
SEO-описание |
settings.* |
значения настроек макета для этого сайта |
site.name |
название сайта |
site.variables.* |
переменные сайта |
<!doctype html><html lang="ru"> <head> <title>{{ page.meta_title | default: page.title }}</title> <meta name="description" content="{{ page.meta_description }}"> <style>{{ blocks_css }}</style> </head> <body> <header>{{ settings.header_title | default: site.name }}</header> {{ content }} <script>{{ blocks_js }}</script> </body></html>props в макете нет — это переменная блока. И наоборот: page, settings
и site недоступны в шаблоне блока.
Переменные сайта: @имя
Заголовок раздела «Переменные сайта: @имя»Переменные сайта — отдельный механизм, к Liquid отношения не имеющий. Пишете
@имя где угодно в шаблоне, а подстановка выполняется после рендеринга, простой
заменой по тексту:
<a href="mailto:@support_email">Написать нам</a><p>© @brand_name</p>Работает и в блоке, и в макете, но не заменяет props: переменная сайта одна
на весь сайт, а поле блока задаётся на каждой странице.
Быстрая проверка себя
Заголовок раздела «Быстрая проверка себя»| Хочу вывести | Пишу |
|---|---|
| Значение поля блока | {{ props.field }} |
| Поле внутри повторяющейся группы | {% for i in props.items %}{{ i.field }}{% endfor %} |
| Текст markdown-блока | {{ content }} |
| Данные из слота | {{ data.slot_name… }} |
| Заголовок страницы (в макете) | {{ page.title }} |
| Общий телефон компании | @phone — переменная сайта |
Источники: backend/src/Publishing/BlockRenderer.php (buildContext,
buildDefaultData, applyVariables), backend/src/Publishing/LayoutRenderer.php
(render), backend/src/Publishing/BlockAssembler.php,
backend/src/Publishing/Provider/FourCmsProvider.php (buildSsrContext),
front/src/lib/placeholder.ts, front/src/components/PageEditor/PageEditor.tsx,
backend/public/block-schema.json.