Custom Containers
Custom Containers позволяют расширять функционал редактора своими клиентскими контейнерами без разработки отдельного виджета внутри Verstka.
Клиент описывает контейнеры в конфиге: как они называются, какого они размера, какую иконку показывать в панели создания, какой HTML рендерить, какие параметры можно менять в редакторе и какой маркер оставить в итоговом HTML для замены на стороне сайта.
Для чего это нужно
Самый частый сценарий - вставить в статью место под клиентский виджет, а затем заменить это место на сайте клиента обычным строковым replace по HTML-комментарию:
<!-- ReplaceMarker: banner -->Например, редактор расставляет контейнеры banner, article-authors, buy-button, а сайт клиента после получения HTML заменяет маркеры на реальные CMS-виджеты, рекламные блоки, авторские карточки или кнопки покупки.
Другой сценарий - собрать конфиг на стороне клиента уже с реальными данными статьи. Например, если клиентская админка знает авторов статьи, текущую рубрику или товар, она может сразу положить эти данные в html или customProps.
Передача конфига
Конфиг должен передаваться в API вместе с данными сессии или редактора. Бэкенд-часть этого сценария пока не готова, поэтому точный endpoint и формат передачи будут добавлены позже.
Этот раздел описывает целевой формат конфига, который должен прийти в редактор:
type ClientConfig = {
customContainers: CustomContainerDefinition[]
}Контейнеров может быть любое количество. Каждый контейнер должен иметь уникальный id.
Как это работает
- Клиент формирует
customContainersна своей стороне. - Verstka получает конфиг через API.
- В редакторе появляется отдельная кнопка создания для каждого контейнера.
- Дизайнер размещает контейнер в статье и, если нужно, меняет параметры через правую панель.
- В итоговом HTML рендерится контейнер, его атрибуты, HTML из конфига и, если указан
replaceMarker, комментарий вида<!-- ReplaceMarker: value -->. - Сайт клиента заменяет маркер или использует HTML/атрибуты контейнера для собственной логики.
Формат контейнера
type CustomContainerDefinition = {
id: string
name: string
toolIcon: string
width: number
height: number
resizable?: boolean
dummyImageUrl?: string | null
html?: string
replaceMarker?: string | null
attributes?: Record<string, string | number | boolean | null>
customProps?: Record<string, string | number | boolean | null>
tool?: {
sectionsConfig: Record<string, { widgetProperties: string[] }>
controlsConfig: Record<string, CustomControlConfig>
}
}Поля
| Поле | Тип | Описание |
|---|---|---|
id | string | Уникальный технический ID контейнера. Используется в сохраненных данных и маркерах. |
name | string | Название в UI редактора и текст editor-only заглушки внутри пустого контейнера. |
toolIcon | string | Иконка кнопки создания. Рекомендуется передавать inline SVG строкой. |
width | number | Стартовая ширина контейнера в редакторе. |
height | number | Стартовая высота контейнера в редакторе. |
resizable | boolean | Можно ли менять размер контейнера в редакторе. Это общее свойство всех контейнеров. По умолчанию true. |
dummyImageUrl | string | null | URL картинки-заглушки для canvas-редактора. В превью и на сайте клиента не рендерится. |
html | string | HTML, который будет отрендерен внутри контейнера. Может включать <style>. |
replaceMarker | string | null | Если задан, в HTML появится <!-- ReplaceMarker: value -->. |
attributes | Record | Статические параметры контейнера, например slot, placement, provider. |
customProps | Record | Начальные значения параметров, которые могут редактироваться через контролы. |
tool | object | Описание контролов правой панели. Если пустой, у контейнера нет настроек. |
Правила рендера
Custom Container ведет себя по тому, какие поля есть в конфиге:
| Что есть в конфиге | Что рендерится |
|---|---|
html непустой | Санитизированный HTML внутри контейнера. |
html пустой | Пустой контейнер без визуальной заглушки. |
replaceMarker задан | HTML-комментарий <!-- ReplaceMarker: value -->. |
tool.controlsConfig задан | Контролы в правой панели редактора. |
resizable: false | В редакторе скрываются resize-ручки контейнера. |
HTML очищается перед выводом: удаляются <script>, inline-обработчики событий и небезопасные URL вроде javascript:.
dummyImageUrl и fallback с name нужны только в canvas-редакторе, чтобы дизайнер видел пустой контейнер и мог его выбрать. В превью, SSR и на сайте клиента эти заглушки не попадают в разметку: остается сам контейнер с data-vrstk-custom-id, параметрами и комментарием-маркером.
Маркер замены
replaceMarker нужен для простого и надежного server-side replacement на сайте клиента.
Конфиг:
{
id: 'banner',
name: 'Баннер',
replaceMarker: 'banner',
html: '',
dummyImageUrl: null,
width: 970,
height: 250,
resizable: false,
toolIcon: '<svg viewBox="0 0 16 16">...</svg>',
attributes: {},
customProps: {},
tool: {
sectionsConfig: {},
controlsConfig: {}
}
}В HTML появится:
<!-- ReplaceMarker: banner -->На PHP это можно заменить обычным str_replace:
$articleHtml = str_replace(
'<!-- ReplaceMarker: banner -->',
renderBannerWidget($article),
$articleHtml
);HTML с реальными данными
Так как конфиг собирается на клиентской стороне, в html можно положить уже готовую разметку с реальными данными статьи:
- авторы статьи;
- текущая рубрика;
- ID товара;
- название бренда;
- текст дисклеймера;
- HTML, который клиент уже умеет собирать в своей CMS.
Важно: значения из CMS нужно экранировать до вставки в HTML. Verstka дополнительно очищает HTML, но это не заменяет нормальную обработку данных на стороне клиента.
Контролы
Контролы позволяют дать дизайнеру изменить параметры контейнера в редакторе. Эти значения сохраняются в customProps и попадают в итоговый HTML как параметры контейнера.
Подробное описание доступных контролов: Контролы.
Готовые сценарии: Примеры.