Сайт перешел на функционал групп
Читаем новость, обсуждаем, делимся впечатлениями или может есть какие пожелания? Перейти
на сайт, и вы сможете вступить в группу.
Вы сможете подписаться на выход новых материалов группы.
Вы сможете подписаться на новые комментарии к выбранной записи группы.

Редактор блоков WordPress. 3 часть - добавляем кнопку в RichText редактор


В этом руководстве я покажу как добавить свою произвольную кнопку в редактор блоков вордпресс 5.0. А именно: кнопку в RichText редактор (Gutenberg редактор)

В 1-й части мы рассмотрели его анатомию - это простой редактор с кнопками. Вверху содержится BlockToolbar, а уже в нём элементы внутреннего форматирования (inline formatting).

Сейчас там 4-ре кнопки: выделение жирным, курсивом, ссылка и перечеркнутый текст. Вот как это выглядит сейчас:

4-ре стандартных кнопки форматирования
4-ре стандартных кнопки форматирования

Но мы добавим нужную кнопку выделяющую однострочный код - <code>. И получится так:

Добавим кнопку code
Добавим кнопку code

А поняв принцип - вы сможете добавлять любые свои кнопки в гутенберг редактор: хоть в span оборачивать и выделать цветом, хоть тег small, sub, sup. Всё будет в ваших руках.

Добавление кнопки - тоже работа с js кодом. Но никаких регистраций блока не потребуется - на стороне php все будет очень просто.

Поехали!

Добавим кнопку:

Механизм работы с кнопками в внутреннем форматировании названы Format API (API форматирования). Он позволяет указать тег, которым можно оборачивать текст и настройки для тего.

php-файл

Давайте в нашем php файле зарегистрируем наш скрипт:

add_action('enqueue_block_editor_assets', 'otfm_load_code_bttn');
function otfm_load_code_bttn(){
    wp_enqueue_script(
        'othb_code',
        plugins_url( 'src/code-bttn/index.js', __FILE__ ),
        array( 'wp-element', 'wp-rich-text', 'wp-editor' )
    );
}

Обратите внимание на массив зависимостей - т.к. эти пакеты использовать будем внутри скрипта.

Перейдём к index.js - javascript файлу, в котором опишем нашу кнопку.

Функция registerFormatType()

Вся работа идет внутри функции registerFormatType()
Функция находится по пути /packages/rich-text/src/register-format-type.js. Первым аргументом принимает строку - имя. Вторым - объект настроек.

Объект настроек:

  • tagName: строка. Этот HTML-тег обернет выделение.
  • className: строка || null. HTML-класс назначенный тегу.
  • title: строка. Имя.
  • edit: функция. Должен возвращать компонент для взаимодействия пользователя с новым зарегистрированным форматом.

При создании своих span тегов полезна будет настройка className - по этому классу вы сможете стилизовать через css свои теги. Можно выстроить заранее определённые выделения внутреннего текста - и оно будет стандартизировано для вашего сайта.

js-файл

Добавим кнопку, которая будет оборачивать выделенный текст в тег <code>
Добавим в index.js:

(function (richText, element, editor) {
var el = element.createElement,
    fragment = element.Fragment;

var registerFormatType = richText.registerFormatType,
    unregisterFormatType = richText.unregisterFormatType,
    toggleFormat = richText.toggleFormat;

var richTextToolbarButton = editor.RichTextToolbarButton,
    richTextShortcut = editor.RichTextShortcut;

var type = "core/code";

unregisterFormatType(type);
registerFormatType(type, {
    title:      "Code",
    tagName:    "code",
    className:  null,
    edit: function edit(props) {
        var isActive = props.isActive,
            value = props.value,
            onChange = props.onChange;

        var onToggle = function() {
            return onChange(toggleFormat(value, { type: type }));
        };

        return el(
            fragment,
            null,
            el(richTextShortcut, {
                type: "access",
                character: "x",
                onUse: onToggle
            }),
            el(richTextToolbarButton, {
                icon: "editor-code",
                title: "Code",
                onClick: onToggle,
                isActive: isActive,
                shortcutType: "access",
                shortcutCharacter: "x"
            })
        );
    }
});

}(
    window.wp.richText,
    window.wp.element,
    window.wp.editor
));

На первой строке мы получаем наши зависимости.
Потом определяем переменные.
На 15-й строке функция registerFormatType() - задаём ей тайтл, имя тега с которым будем работать и html-класс нам не нужен - null.

Далее функция edit() - определяем переменные и в onChange происходит переключение - оборачиваем в наш тег или снимаем выделение.
На 36-й строке задаем настройки для тулбара:
мы задаем иконку dashicons - 37 строка.
title - для всплывающей подсказки
в shortcutCharacter выставляем сочетание горячих клавиш. В коде стоит "x" - значит что по комбинации "Shift + Alt + X" выделенный участок мы обернем в тег <code>

На этом простое добавление кнопки завершено. Результат:

Добавим кнопку code
Добавим кнопку code

css стили для тега <code> впишите свои.


Замечание и полезные ссылки:

Стоит отметить, что в консоли вы увидите ошибку уведомление сгенерированное самим редактором:

Format "core/code" is already registered. rich-text.min.js:1:10782

визуально:

В обсуждении говорят что можно расслабиться. Если вы знаете больше подробностей - дайте мне знать. Я не задавал им вопрос - в чём дело и не углублялся в решение. На работу это сообщение не влияет - просто мессадж от разработчиков, а не консольная ошибка.

upd: Мы с Михаилом Кобзарёвым нашли причину - если при регистрации скрипта подключить его в подвале, то сообщение из консоли исчезает.
Вот пример итогового php:

add_action('enqueue_block_editor_assets', 'otfm_load_code_bttn');
function otfm_load_code_bttn(){
    wp_enqueue_script(
        'othb_code',
        plugins_url( 'src/blocks/code-bttn/index.js', __FILE__ ),
        array( 'wp-element', 'wp-rich-text', 'wp-editor' ),
        filemtime( dirname( __FILE__ ) . '/src/blocks/code-bttn/index.js' ),
        true
    );
}

Документация по Format API только пишется.
Посмотреть вы можете здесь. Описании функций доступно будет в компоненте RichText или в туториалах: docs/designers-developers/developers/tutorials/format-api/. над черновиком работа ведётся тут или здесь

Готовое решение для выделения кнопками: code, sub, sup вы найдете здесь: advanced-rich-text-tools или в официальном репозитории WordPress

p.s. Спасибо Михаилу Кобзарёву за тестирование данного кода и выявление ошибки. Отсутствие в коде unregisterFormatType(type); приводило к отсутствию кнопки. Обратите на это внимание - если у вас кнопка не появлялась

3 комментария

  1. Добрый день, Владимир.
    Спасибо за полезные статьи. Побольше бы таких.

    Если не затруднит и найдете время ответить (а может это будет идеей для следующей статьи):
    возникла необходимость добавлять параметры к существующим блокам, при изменении которых на блок вешается дополнительный класс, по которому данный блок потом стилится.
    Добавить поле с параметром получилось, а вот с функцией (объектом) save загвоздка - не дает модифицировать свойство element.props.className

    Пример кода:

    // Save block
    var MyBlocksCoreBlockSave = function( element, blockType, attributes ) {
    	if ( blockType.name == 'core/spacer' && attributes.alter_height ) {
    		// Not work
    		//element.props.className += ' sc_height_' + attributes.alter_height;
    		// Not work
    		//lodash.assign( element.props, { className: element.props.className + ' sc_height_' + attributes.alter_height } );
    	}
    	return element;
    };
    
    hooks.addFilter( 'blocks.getSaveElement', 'myblocks/core/block', MyBlocksCoreBlockSave );

    Т.е. в attributes.alter_height содержится нужное значение, но element.props.className не меняется.

    Можно ли как-то изменить класс возвращаемого объекта, не создавая объект заново - блоки бывают довольно сложной структуры и не хочется ее заново пересоздавать

    Заранее спасибо за Ваше время.

    0
      1. Спасибо большое. Да, этот пример помог.
        А я пытался изменить класс прямо в обработчике события editor.BlockEdit, в котором добавлял поля для дополнительного параметра в редакторе

        1

Оставьте комментарий

Авторизация
*
*
Регистрация
*
*
*
Настоящим подтверждаю, что я ознакомлен и согласен с условиями политики конфиденциальности
Генерация пароля
Написать
*
*