Skip to content

Custom Containers

Custom Containers позволяют расширять функционал редактора своими клиентскими контейнерами без разработки отдельного виджета внутри Verstka.

Клиент описывает контейнеры в конфиге: как они называются, какого они размера, какую иконку показывать в панели создания, какой HTML рендерить, какие параметры можно менять в редакторе и какой маркер оставить в итоговом HTML для замены на стороне сайта.

Для чего это нужно

Самый частый сценарий - вставить в статью место под клиентский виджет, а затем заменить это место на сайте клиента обычным строковым replace по HTML-комментарию:

html
<!-- ReplaceMarker: banner -->

Например, редактор расставляет контейнеры banner, article-authors, buy-button, а сайт клиента после получения HTML заменяет маркеры на реальные CMS-виджеты, рекламные блоки, авторские карточки или кнопки покупки.

Другой сценарий - собрать конфиг на стороне клиента уже с реальными данными статьи. Например, если клиентская админка знает авторов статьи, текущую рубрику или товар, она может сразу положить эти данные в html или customProps.

Передача конфига

Конфиг должен передаваться в API вместе с данными сессии или редактора. Бэкенд-часть этого сценария пока не готова, поэтому точный endpoint и формат передачи будут добавлены позже.

Этот раздел описывает целевой формат конфига, который должен прийти в редактор:

ts
type ClientConfig = {
  customContainers: CustomContainerDefinition[]
}

Контейнеров может быть любое количество. Каждый контейнер должен иметь уникальный id.

Как это работает

  1. Клиент формирует customContainers на своей стороне.
  2. Verstka получает конфиг через API.
  3. В редакторе появляется отдельная кнопка создания для каждого контейнера.
  4. Дизайнер размещает контейнер в статье и, если нужно, меняет параметры через правую панель.
  5. В итоговом HTML рендерится контейнер, его атрибуты, HTML из конфига и, если указан replaceMarker, комментарий вида <!-- ReplaceMarker: value -->.
  6. Сайт клиента заменяет маркер или использует HTML/атрибуты контейнера для собственной логики.

Формат контейнера

ts
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>
  }
}

Поля

ПолеТипОписание
idstringУникальный технический ID контейнера. Используется в сохраненных данных и маркерах.
namestringНазвание в UI редактора и текст editor-only заглушки внутри пустого контейнера.
toolIconstringИконка кнопки создания. Рекомендуется передавать inline SVG строкой.
widthnumberСтартовая ширина контейнера в редакторе.
heightnumberСтартовая высота контейнера в редакторе.
resizablebooleanМожно ли менять размер контейнера в редакторе. Это общее свойство всех контейнеров. По умолчанию true.
dummyImageUrlstring | nullURL картинки-заглушки для canvas-редактора. В превью и на сайте клиента не рендерится.
htmlstringHTML, который будет отрендерен внутри контейнера. Может включать <style>.
replaceMarkerstring | nullЕсли задан, в HTML появится <!-- ReplaceMarker: value -->.
attributesRecordСтатические параметры контейнера, например slot, placement, provider.
customPropsRecordНачальные значения параметров, которые могут редактироваться через контролы.
toolobjectОписание контролов правой панели. Если пустой, у контейнера нет настроек.

Правила рендера

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 на сайте клиента.

Конфиг:

ts
{
  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 появится:

html
<!-- ReplaceMarker: banner -->

На PHP это можно заменить обычным str_replace:

php
$articleHtml = str_replace(
    '<!-- ReplaceMarker: banner -->',
    renderBannerWidget($article),
    $articleHtml
);

HTML с реальными данными

Так как конфиг собирается на клиентской стороне, в html можно положить уже готовую разметку с реальными данными статьи:

  • авторы статьи;
  • текущая рубрика;
  • ID товара;
  • название бренда;
  • текст дисклеймера;
  • HTML, который клиент уже умеет собирать в своей CMS.

Важно: значения из CMS нужно экранировать до вставки в HTML. Verstka дополнительно очищает HTML, но это не заменяет нормальную обработку данных на стороне клиента.

Контролы

Контролы позволяют дать дизайнеру изменить параметры контейнера в редакторе. Эти значения сохраняются в customProps и попадают в итоговый HTML как параметры контейнера.

Подробное описание доступных контролов: Контролы.

Готовые сценарии: Примеры.