Анатомия блока
Блок — переиспользуемый кусок страницы. Страница собирается из блоков, каждый блок описывает что можно настроить (схема полей) и как это выглядит (шаблон Liquid, CSS, JS).
Две половины блока
Заголовок раздела «Две половины блока»Блок физически состоит из двух частей, и их важно не путать: карточка блока меняется свободно, а его содержимое версионируется.
| Часть | Что там | Что происходит при правке |
|---|---|---|
| Карточка блока | имя, описание, документация, тип, теги, обложка | перезаписывается на месте |
| Ревизия | template, css, js, schema_content, changelog |
создаётся новая ревизия, старая остаётся в истории |
Правка имени или описания не создаёт версию. Правка шаблона, стилей, скрипта или схемы полей — создаёт. Подробности — Ревизии и версии.
Поля карточки
Заголовок раздела «Поля карточки»| Поле | Тип | Назначение |
|---|---|---|
name |
строка, 1–255 | название блока в библиотеке; обязательно |
description |
строка | короткое описание для списка блоков |
docs |
строка (Markdown) | инструкция для того, кто ставит блок на страницу |
block_type |
schema | markdown | html |
см. ниже; по умолчанию schema |
role |
content | layout |
роль блока: обычный блок страницы или лэйаут; по умолчанию content, после создания не меняется |
tags |
список id тегов | фильтрация в библиотеке |
| обложка | картинка | превью в библиотеке, грузится отдельным запросом |
Поля ревизии
Заголовок раздела «Поля ревизии»| Поле | Назначение |
|---|---|
template |
HTML с разметкой Liquid — то, что превращается в HTML страницы |
css |
стили блока |
js |
скрипт блока |
schema_content |
схема полей: что редактор покажет в форме — полный справочник |
changelog |
текст «что изменилось» для этой версии |
Версия ревизии — два числа, major.minor (например 1.3). Первая ревизия любого
блока — 1.0.
Типы блока
Заголовок раздела «Типы блока»Тип задаётся полем block_type и определяет, что редактор показывает контентщику.
schema — по умолчанию. Форма собирается из schema_content.fields, значения
уезжают в шаблон Liquid. Это основной тип, и вся остальная документация написана
прежде всего про него.
markdown — то же самое плюс WYSIWYG-редактор текста. Текст хранится
в зарезервированном ключе _markdown (его не нужно объявлять в fields),
при рендере конвертируется в HTML и приходит в шаблон как {{ content }}.
Markdown-блок может дополнительно объявлять обычные поля — например цвет фона —
и они работают ровно как у schema-блока.
html — легаси-тип без схемы полей. Новые блоки в нём не делают.
Роль блока: обычный блок или лэйаут
Заголовок раздела «Роль блока: обычный блок или лэйаут»Роль — отдельное поле role, и она не про устройство шаблона (это block_type),
а про то, где блок применяется.
content — по умолчанию. Обычный блок: ставится на любую страницу и в слоты
блоков-контейнеров.
layout — лэйаут: обёртка вокруг страниц. Такой блок кладётся только
на верхний уровень документа-макета (kind = layout), по одному на документ, и в слот
другого блока не помещается. Лэйаут описывает документ целиком — назначенный макет
подменяет собой разметку витрины, а не вставляется внутрь неё:
<!DOCTYPE html><html lang="ru"><head> <meta charset="utf-8"> {{ cms_assets_head }}</head><body> {{ cms_assets_body_start }} <div class="frame"> <aside>{{ slots.sidebar }}</aside> <main>{{ content }}</main> </div> {{ cms_assets_body_end }}</body></html>Точки вставки
Заголовок раздела «Точки вставки»| Тег | Куда ставить | Обязателен | Что подставит витрина |
|---|---|---|---|
{{ content }} |
тело документа | да | страницу |
{{ cms_assets_head }} |
внутрь <head> |
да | CSS сайта, цветовые схемы, счётчики |
{{ cms_assets_body_start }} |
сразу после <body> |
нет | то, что обязано идти первым в теле |
{{ cms_assets_body_end }} |
перед </body> |
нет | скрипты конца документа |
Без обязательных блок не сохранится: API ответит 422 с описанием, чего не хватает.
Тот же отказ приходит при публикации документа-макета — на случай лэйаутов, собранных
до появления правила.
В опубликованном шаблоне все четыре остаются маркерами: подставляет их витрина.
В предпросмотре PageCraft на месте {{ content }} плашка «здесь будет страница»,
а ассеты не видны — локально подставлять нечего.
Во всём остальном лэйаут — обычный блок библиотеки: своя схема полей, свои слоты композиции для шапки, сайдбара и подвала, свои CSS и JS, история ревизий, теги, форк.
Лэйаут бывает только типа schema: у markdown-блока {{ content }} уже занят текстом
из WYSIWYG-редактора, и точке вставки страницы там нет места. Пара role: layout +
block_type: markdown отклоняется с 422.
Взяв на себя весь документ, лэйаут берёт на себя и его <head>: заголовок, мету
и canonical собирайте блоками — источник page.info отдаёт их для текущей страницы.
Ассеты самого магазина подставит витрина через cms_assets_*.
Как собрать из лэйаута макет — Макеты.
Как значение поля попадает в HTML
Заголовок раздела «Как значение поля попадает в HTML»- Автор блока объявляет поле в
schema_content.fields, напримерtitle. - Контентщик заполняет форму — значения сохраняются в
placeholder_valuesтого экземпляра блока, который стоит на странице. - При рендере весь объект значений кладётся в переменную
props, и шаблон обращается к полю как{{ props.title }}.
<section class="hero"> <h1>{{ props.title }}</h1> <p>{{ props.subtitle }}</p> {% for slide in props.slides %} <img src="{{ slide.image }}" alt="{{ slide.caption }}" /> {% endfor %}</section>Если у экземпляра блока значений нет вовсе, PageCraft подставляет значения по умолчанию из схемы — правила описаны в разделе Значения по умолчанию.
Шаблон рендерится в «мягком» режиме: неизвестная переменная даёт пустую строку,
а ошибка шаблона не роняет страницу — на её месте остаётся HTML-комментарий
<!-- Liquid render error: … -->. Это удобно при отладке: сломанный блок видно
в исходном коде страницы, а остальные блоки продолжают работать.
Минимальный блок целиком
Заголовок раздела «Минимальный блок целиком»Схема:
{ "type": "object", "label": "Заголовок секции", "fields": { "title": { "type": "text", "label": "Заголовок", "default": "Привет" }, "align": { "type": "select", "label": "Выравнивание", "options": [ { "label": "Слева", "value": "left" }, { "label": "По центру", "value": "center" } ], "default": "center" } }}Шаблон:
<h2 style="text-align: {{ props.align }}">{{ props.title }}</h2>Через публичное API это один запрос:
curl -X POST https://page-craft.4partners.io/api/v1/blocks \ -H "Authorization: Bearer pb_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Заголовок секции", "block_type": "schema", "template": "<h2 style=\"text-align: {{ props.align }}\">{{ props.title }}</h2>", "schema_content": { "type": "object", "fields": { "title": { "type": "text" } } }, "changelog": "Начальная версия" }'Приватные и глобальные блоки
Заголовок раздела «Приватные и глобальные блоки»У блока есть область видимости scope:
private— блок виден только владельцу. Так создаётся любой новый блок.global— блок из общего каталога, доступен всем.
Глобальным блок становится не напрямую, а через заявку: автор отправляет блок
в каталог (POST /api/v1/blocks/{id}/submit), администратор одобряет или отклоняет.
Пока заявка на рассмотрении, повторную подать нельзя — вернётся ошибка 409.
Форк (POST /api/v1/blocks/{id}/fork) делает личную копию глобального блока:
копируются шаблон, стили, скрипт, схема, теги, обложка и номер версии, у копии
появляется ссылка на источник (forked_from_block_id), а у источника растёт счётчик
форков. Форкать можно только глобальные блоки — попытка форкнуть чужой приватный
вернёт ошибку. Форк — штатный способ доработать чужой блок под себя и уйти
с устаревающего глобального блока.
Перенос блока между аккаунтами
Заголовок раздела «Перенос блока между аккаунтами»Блок выгружается ZIP-архивом (GET /api/blocks/{id}/export) и загружается обратно
(POST /api/blocks/import). Внутри архива пять файлов с фиксированными именами:
| Файл | Содержимое |
|---|---|
meta.json |
имя, описание, docs, тип, теги, версия, changelog, format_version: "1" |
template.html |
шаблон |
styles.css |
стили |
script.js |
скрипт |
schema.json |
schema_content |
Отсутствие любого из пяти файлов — ошибка импорта. При импорте своего же блока
(совпал автор и id из meta.json) создаётся новая ревизия существующего блока,
иначе — новый блок. Теги подхватываются только те, что уже есть в системе.
Что дальше
Заголовок раздела «Что дальше»- Схема полей: полный справочник — все типы полей и валидация.
- Пресеты — готовые наборы значений для формы.
- Ревизии и версии — как работает версионирование.
- Устаревание и апгрейды — что делать с блоками на страницах.
Источники: backend/src/Entity/Block.php, backend/src/Entity/BlockRevision.php,
backend/src/Service/Block/{CreateBlockService,ForkBlockService,ExportBlockService,ImportBlockService}.php,
backend/src/Publishing/BlockRenderer.php,
backend/src/Controller/V1/Block/Request/CreateBlockPublicRequest.php,
backend/public/block-schema.json.