Пять способов расширения функциональности стандартных блоков в WordPress

Стандартные блоки в WordPress позволяют создавать страницы разной сложности. От простейших текстовых до сложных с многоколоночной структурой, изображениями, аудио и видеоконтентом.

Но бывают ситуации, когда стандартных блоков недостаточно. Например, блоку нужно добавить отступ, или обернуть блок в дополнительный div. Бывает и наоборот, стандартный блок предоставляет слишком много опций, которые лучше спрятать от клиента.

Пять способов расширения функциональности стандартных блоков в WordPress

Для таких ситуаций в WordPress cуществует несколько инструментов о которых я расскажу в этой статье.

1. Дополнительный CSS Класс

Начнем с самого простого способа. К любому стандартному блоку в WordPress можно добавить дополнительный CSS класс, который потом можно использовать в стилях темы или вкладке Дополнительные стили в настройках.

Допустим нам необходимо добавить нижний отступ в 100 px к блоку Обложка на одной из страниц. Для этого добавим к нему класс mb-large:

Пять способов расширения функциональности стандартных блоков в WordPress

… и затем в дополнительных стилях создадим новое CSS правило:

.mb-large { margin-bottom: 100px; }

Этот способ подходит для случаев, когда нужно быстро добавить небольшое изменение на одной-двух страницах.

Если вы планируете использовать это изменение постоянно, лучше использовать другой способ — стиль блока.

2. Стили Блоков

Так же как и в первом способе, дополнительные стили добавляют к блоку CSS класс. Разница заключается в том, что зарегистрированные стили появляются в специальном разделе в редакторе, и чтобы добавить стиль не нужно вводить СSS класс вручную, достаточно просто кликнуть на него. Разберем на примере.

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

Пять способов расширения функциональности стандартных блоков в WordPress

Это отличный кейс чтобы использовать блок Группа и создать для него дополнительный стиль Карточка, потому что такая комбинация элементов повторялась на большом количестве страниц.

Чтобы добавить стиль, используем функцию registerBlockStyle():

const { __ } = wp.i18n; const { registerBlockStyle } = wp.blocks; registerBlockStyle('core/group', [ { name: 'card', label: __('Card', 'textdomain'), }, ]);

Если вы не писали код для нового редактора ранее, советую прочитать статью в которой я подробно рассказал как настроить проект для Gutenberg.

После того как мы добавили код из примера выше, в редакторе должен появиться дополнительный стиль для блока Группа:

Пять способов расширения функциональности стандартных блоков в WordPress

Если кликнуть на этот стиль, то к блоку добавится новый CSS класс is-style-card.

Последнее, что нужно сделать это написать стили для этого класса:

.is-style-card { background-color: #ffffff; border: 1px solid #caced7; padding: 1.5rem; }

Как я уже писал ранее, этот способ хорошо применять, в случае если вы планируете использовать эту модификацию блока постоянно.

У этого способа есть ограничения — у каждого блока может быть активен только один стиль. То есть мы не можем создать отдельный стиль для внешнего вида блока, и отдельный стиль для отступа, и использовать их вместе. Для таких случаев стоит использовать Вариации или Фильтры, о которых я расскажу далее.

3. Вариации Блоков

Вариации блоков очень похожи на стили блоков, но позволяют делать намного больше. Основная разница заключается в том, что вариация появляется в редакторе в виде отдельного блока (хоть таковым и не является) и позволяет задать иконку, заполнить атрибуты блока и добавить внутренние блоки.

Чтобы разобраться, создадим вариацию на основе предыдущего примера. Основная идея — позволить пользователям добавлять на страницу блок Группа с уже включенным стилем Карточка, заполненным заголовком, параграфом текста и ссылкой.

Регистрация вариации выполняется с помощью функции registerBlockVariation():

const { __ } = wp.i18n; const { registerBlockVariation } = wp.blocks; registerBlockVariation('core/group', { name: 'cta', title: __('CTA', 'textdomain'), icon: 'admin-links', scope: ['inserter'], attributes: { className: 'is-style-card' }, innerBlocks: [ ['core/heading', { level: 2, content: __('Card Title', 'textdomain') }], ['core/paragraph', { content: __('Card content…', 'textdomain') }], ['core/paragraph', { content: `<a href="#">${__('Learn more', 'textdomain')}</a>` }], ], });

Обратите внимание на параметр className внутри параметра attributes — так мы указываем какой стиль будет использоваться блоком. Шаблон внутренних блоков задан внутри параметра innerBlocks.

Если мы все сделали правильно, то в меню вставки блоков должен появиться новый «блок» СTA (Call To Action):

Пять способов расширения функциональности стандартных блоков в WordPress

… кликнув на который, пользователь сможет добавить блок Группа, с уже заданными внутренними блоками и стилем Карточка.

Этот способ пригодится если функционала стандартных блоков достаточно и нужно просто сэкономить время на создании повторяющихся элементов.

Одно из ограничений этого способа — возможность создать вариацию только для одно блока. Да, можно создать вариацию для блока Группа и добавить сколько угодно внутренних блоков, но если вам нужно создать более сложную повторяющуюся структуру страницы, лучше использовать Паттерны. О них и поговорим далее.

4. Паттерны Блоков

Паттерны — относительно новый инструмент в WordPress, который позволяет регистрировать структуру из нескольких блоков и далее вставлять ее на страницы в несколько кликов.

Я подробно рассказал о паттернах в отдельной статье. Прочитайте ее, чтобы подробно ознакомиться с этим инструментом.

Вкратце рассмотрим, как зарегистрировать новый паттерн. Допустим мы часто используем следующую структуру страницы:

Пять способов расширения функциональности стандартных блоков в WordPress

На изображении видно, что мы используем следующие блоки:

Заголовок Параграф Разделитель Колонки ├─ Колонка │ ├─ Заголовок │ ├─ Параграф │ ├─ Параграф со ссылкой ├─ Колонка │ ├─ Заголовок │ ├─ Параграф │ ├─ Параграф со ссылкой

Для того чтобы зарегистрировать подобный паттерн, необходимо сначала создать такую комбинацию на пустой странице и скопировать ее содержимое в режиме кода.

Далее используем функцию register_block_pattern():

function prefix_register_demo_patterns() { register_block_pattern( 'demo-patterns/intro-with-two-columns', [ 'title' => esc_html__( 'Intro With Two Columns', 'textdomain' ), 'categories' => ['columns'], 'content' => '<!-- wp:heading --><h2>Заголовок</h2><!-- /wp:heading --><!-- wp:paragraph --><p>Лорем ипсум долор сит амет, дицерет молестиае нец цу. Уллум дицунт воцибус при ин, меа бонорум маиорум персецути цу. Веритус симилияуе ат еос, пробо ассум регионе цу вим, ид ноструд вертерем вим. Еним бонорум адверсариум про ут, нец еирмод импетус фацилис ид, еи яуас лаборамус еос. Не яуо аугуе улламцорпер.</p><!-- /wp:paragraph --><!-- wp:separator --><hr class="wp-block-separator"/><!-- /wp:separator --><!-- wp:columns --><div class="wp-block-columns"><!-- wp:column --><div class="wp-block-column"><!-- wp:heading {"level":3} --><h3>Подзаголовок</h3><!-- /wp:heading --><!-- wp:paragraph {"fontSize":"extra-small"} --><p class="has-extra-small-font-size">Еним бонорум адверсариум про ут, нец еирмод импетус фацилис ид, еи яуас лаборамус еос. Не яуо аугуе улламцорпер.</p><!-- /wp:paragraph --><!-- wp:paragraph {"fontSize":"extra-small"} --><p class="has-extra-small-font-size"><a href="#"><strong>Заказать</strong></a></p><!-- /wp:paragraph --></div><!-- /wp:column --><!-- wp:column --><div class="wp-block-column"><!-- wp:heading {"level":3} --><h3 id="block-aeb0df31-4377-4647-8970-76da5465b475">Подзаголовок</h3><!-- /wp:heading --><!-- wp:paragraph {"fontSize":"extra-small"} --><p class="has-extra-small-font-size" id="block-b5279988-8af3-494a-a8d3-7e1267674ae4">Еним бонорум адверсариум про ут, нец еирмод импетус фацилис ид, еи яуас лаборамус еос. Не яуо аугуе улламцорпер.</p><!-- /wp:paragraph --><!-- wp:paragraph {"fontSize":"extra-small"} --><p class="has-extra-small-font-size" id="block-fce9e860-568b-4d07-9e5b-fa79c30fd89a"><a href="https://default.test/wp-admin/post.php?post=103&amp;action=edit#"><strong>Заказать</strong></a></p><!-- /wp:paragraph --></div><!-- /wp:column --></div><!-- /wp:columns -->', ] ); } add_action( 'init', 'prefix_register_demo_patterns' );

Обратите внимание, что свойство 'content' должно быть подготовлено для вывода на экран (escaped). Это можно сделать с помощью инструмента CodeBeautify.

Если все сделано верно, то в редакторе должен появится новый паттерн:

Пять способов расширения функциональности стандартных блоков в WordPress

Паттерны — один из моих любимых инструментов, потому что ими просто пользоваться, их быстро регистрировать и они во многих случаях заменяют шаблоны страниц.

5. Фильтры Блоков

Методы, которые я описал выше позволяют совершать большое количество манипуляций со стандартными блоками, но бывают ситуации, когда этого и этого не достаточно. Приведу несколько примеров. Допустим вам необходимо:

  • добавить нижний отступ к блоку, у которого уже активен один из стилей. И такой же отступ нужно добавить к нескольким другим блокам;
  • отключить некоторые опции у отдельного блока, например выравнивание, и оставить при этом глобальные настройки без изменений
  • добавить дополнительный div вокруг блока
  • добавить CSS класс всем блокам одного типа

Эти и другие задачи можно решить с помощью фильтров.

Фильтры — пожалуй самый гибкий и в то же время сложный инструмент для работы со стандартными блоками. Раздела статьи однозначно не хватит чтобы подробно описать работу фильтров, поэтому мы кратко разберм какие бывают фильтры и рассмотрим несколько примеров.

Фильтры блоков можно условно разделить на две группы: PHP и JavaScript.

5.1 PHP Фильтры

Блоки в PHP можно фильтровать с помощью знакомой функции addFilter() и хука render_block.

Предположим, что нам необходимо добавить div c классом wp-block-list-wrapper ко всем блокам Список:

/** * Add wrapper to list block * * @param string $block_content Block content to be rendered. * @param array $block Block attributes. * @return string */ function prefix_add_list_block_wrap( $block_content = '', $block = [] ) { if ( isset( $block['blockName'] ) && 'core/list' === $block['blockName'] ) { return '<div class="wp-block-list-wrapper">' . $block_content . '</div>'; } return $block_content; } add_filter( 'render_block', 'prefix_add_list_block_wrap', 10, 2 );

Из примера видно, что функция prefix_add_list_block_wrap() сначала проверяет с каким блоком мы имеем дело, и если это core/list } — оборачивает контент блока в дополнительный div.

Если мы все сделали правильно то маркап всех списков будет выглядеть вот так:

<div class="wp-block-list-wrapper"> <ul> <li>...</li> <li>...</li> </ul> </div>

Стоит отметить, что этот способ не изменяет вывод блока в редакторе, а работает только с фронтэндом. Если вам необходимо изменить блок в обоих контекстах, стоит использовать JS фильтры.

5.2 JavaScript Фильтры

JavaScript фильтры работают похожим образом. Они используют функцию addFilter() из пакета wp.hooks и в самой простой форме JS фильтр выглядят примерно так:

function filterSomething(something) { // Логика фильтра. return something; } wp.hooks.addFilter( 'hookName', 'namespace', filterSomething );

Первое что бросается в глаза в отличии от add_filter() в PHP, это дополнительный параметр namespace (не путать с PHP namespace). Согласно официальной документации этот параметр должен содержать уникальный идентификатор функции обратного вызова: vendor/plugin/function. Но примеры из той же статьи используют другую структуру: plugin/what-filter-does или plugin/component-name/what-filter-does. Я использую последний вариант.

Другое отличие заключается в том, что именно JavaScript фильтры могут фильтровать. Некоторые работают с простыми строками, другие с объектами, третьи с React компонентами.

Разберем простой пример, допустим нам необходимо урбать опции выравнивания у блока Обложка. На практике это будет выглядеть примерно так:

function filterCoverBlockAlignments(settings, name) { if (name === 'core/cover') { return lodash.assign({}, settings, { supports: lodash.merge(settings.supports, { align: [], }), }); } return settings; } wp.hooks.addFilter( 'blocks.registerBlockType', 'plugin-name/cover-block/alignment-settings', filterCoverBlockAlignments, );

Этот пример использует фильтр registerBlockType для модификации объекта supports в опциях блока.

Сначала мы проверяем что работаем именно с блоком Обложка (core/cover) далее с помощью lodash.assign создаем новый объект опций блока и с помощью lodash.merge заменяем в нем свойство align. Методы lodash нужны чтобы избежать мутации оригинального объекта settings.

Если мы все сделали правильно, возможность выбора выравнивания исчезнет из тулбара:

До и после применения фильтра
До и после применения фильтра

В этом примере мы рассмотрели один из доступных фильтров. Если вы хотите узнать о JS фильтрах больше советую изучить официальную документацию и прочитать статью которую я написал для CSS-Tricks в которой я рассматриваю более сложный пример.

Заключение

В этой статье мы разобрали пять способов расширения блоков WordPress. Подводя итог, повторим когда какой способ использовать

  • Дополнительный CSS — небольшая модификация на одной-двух страницах.
  • Стиль блока — повторяющаяся на нескольких страницах модификация блока. Каждый блок может иметь только один активный стиль.
  • Вариация блока — повторяющаяся на нескольких страницах модификация блока, с более сложной структурой. Может включать стиль блока, заполнять атрибуты, и иметь внутренние блоки.
  • Паттерн блока — похож на вариацию но может включать несколько блоков верхнего уровня. Подходит для создания полных страниц.
  • Фильтр блока — позволяет добавлять и отключать некоторые свойства блоков, а так же редактировать маркап стандартных блоков.

Полезные ссылки

77
2 комментария

Спасибо, отличная статья! Просто и понятно. Добавил в закладки.

Ответить

про хук render_block - не знал.
а на js wp.hooks давно смотрю и думаю засунуть в SvelteJS - чтобы получить модульность, расширяемость и позднее связывание как у wp.

Ответить