Как получить выделенную строку при использовании кнопки на панели инструментов в Gutenberg?

Вопрос или проблема

Я добавил кнопку в редактор блоков. В настоящее время она добавляет <span class="lqdnotes-blank-it"> перед выбранным текстом и </span> после него следующим образом:

<span class="lqdnotes-blank-it">Выбранный текст.</span>

Вот текущий код:

(function ( wp ) {
    var lqdNotesButton = function( props ) {
        return wp.element.createElement(
            wp.blockEditor.RichTextToolbarButton, {
                icon: 'editor-code',
                title: 'Blank It',
                onClick: function () {
                    props.onChange( wp.richText.toggleFormat(
                        props.value,
                        { type: 'lqdnotes/blankit' }
                    ));
                },
            }
        );
    };

    wp.richText.registerFormatType(
        'lqdnotes/blankit', {
            title: 'Blank It',
            tagName: 'span',
            className: 'lqdnotes-blank-it',
            edit: lqdNotesButton,
        }
    );
} )( window.wp );

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

<input type="text" class="lqdnotes-blanked" id="FirstFifteenCharsOfSelectedTextUniqueID">

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

“Гражданская война в США началась в 1861 и закончилась в 1865.”

Если человек включит кнопку для 1861 и 1865, вывод может выглядеть так:

“Гражданская война в США началась в <input type="text" class="lqdnotes-blanked" id="1861lqd0001"> и закончилась в <input type="text" class="lqdnotes-blanked" id="1865lqd0002">.”

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

Вы получаете выбранный контент с помощью getTextContent(). Поэтому вам следует добавить ваш HTML до и после этого контента.

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

    registerFormatType(type, {
        title,
        tagName,
        tagEnd,
        className,
        edit({isActive, value, onChange}) {
            // Получение выбранной строки.
            const text = getTextContent(slice(value));
            const toInsert = tagName + text + tagEnd;
            //const onClick = () => onChange( insert( value, toInsert ) );
            const onClick = () => {
                element = create({
                    'html' : toInsert
                });
                if( element.formats.length === 0 ) {
                    return;
                }
                for ( let i = element.formats[0].length - 1; i >= 0; i-- ) {
                    value = toggleFormat(value, element.formats[0][i]);
                }
                onChange(value);
            };

            return (
                createElement(Fragment, null,
                    createElement(RichTextShortcut, {
                        type : 'primary',
                        character,
                        onUse: onClick
                    }),
                    createElement(RichTextToolbarButton, {
                        icon,
                        title,
                        onClick          : onClick,
                        isActive         : isActive,
                        shortcutType     : 'primary',
                        shortcutCharacter: character,
                        className        : `toolbar-button-with-text toolbar-button__advanced-${name}`
                    })
                )
            )
        }
    });

Вам также следует посмотреть этот код из ядра этой темы.
https://github.com/WordPress/gutenberg/blob/4741104c2e035a6b80ab7e01031a9d4086b3f75d/packages/rich-text/src/register-format-type.js#L17

.

Ответ или решение

Чтобы решить вашу задачу с заменой выделенного текста на элемент input в редакторе блоков Gutenberg, необходимо более детально разобраться в API, предоставляемом WordPress для работы с форматами текста. Вы планируете заменять выделенный текст на элемент <input> с классом и уникальным идентификатором, основанным на первых 15 символах выделенного текста. Для реализации этого функционала важно учитывать как получить текст из выделения, так и правильно модифицировать редактор для добавления необходимых элементов. Рассмотрим теоретическую часть, пример и применение этого решения на практике.

Теория

Gutenberg предоставляет API для работы с форматами в текстовых блоках редактора. Функции для работы с выделениями, такими как getTextContent() и slice(), позволяют вам извлекать текст, который был выделен пользователем. Когда мы используем эти функции в нашем расширении, мы можем не только изменять формат текста, обернув его определёнными HTML тегами, но также полностью заменять его другим содержимым, например элементом <input>.

Основные шаги, которые будут задействованы в решении:

  1. Получение выделенного текста из блока.
  2. Создание нового элемента <input>, который заменит выделенный текст.
  3. Назначение этому элементу уникального идентификатора, который будет основан на содержимом выделенного текста.
  4. Внедрение нового элемента обратно в текстовый блок с помощью соответствующих API функций Gutenberg.

Пример

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

(function (wp) {
    const { registerFormatType, toggleFormat, getActiveFormat } = wp.richText;
    const { RichTextToolbarButton } = wp.blockEditor;
    const { Fragment } = wp.element;

    const createInputWithID = (selectedText, index) => {
        // Создание уникального ID из первых 15 символов текста
        const truncatedText = selectedText.substring(0, 15).replace(/\s+/g, '');
        const uniqueID = `${truncatedText}lqd${index.toString().padStart(4, '0')}`;
        return `<input type="text" class="lqdnotes-blanked" id="${uniqueID}"/>`;
    };

    const lqdNotesButton = function (props) {
        return wp.element.createElement(
            RichTextToolbarButton, {
                icon: 'editor-code',
                title: 'Blank It',
                onClick: function () {
                    const selectedText = wp.richText.getTextContent(wp.richText.slice(props.value));
                    if (selectedText) {
                        const toInsert = createInputWithID(selectedText, Math.floor(Math.random() * 10000));
                        // Здесь добавьте логику для замены текста новым элементом input
                        // Например, используя wp.richText.insert или аналогичную функцию
                        props.onChange(wp.richText.insert(props.value, toInsert));
                    }
                },
            }
        );
    };

    registerFormatType('lqdnotes/blankit', {
        title: 'Blank It',
        tagName: 'span', // Можно оставить пустым, так как мы заменяем это на input
        className: 'lqdnotes-blank-it',
        edit: lqdNotesButton,
    });
})(window.wp);

Применение

Теперь, когда у вас есть эта структура кода, вы можете протестировать её в вашем окружении WordPress и при необходимости адаптировать. Этот код должен быть частью плагина или custom script для вашего сайта. Убедитесь, что используются все зависимости и скрипты были корректно подключены.

Кроме того, важно обратить внимание на такие моменты:

  • Соответствие идентификаторов, чтобы избежать конфликтов, если несколько полей создаются с одним и тем же текстом.
  • Устойчивость скрипта к потенциальным ошибкам (если, например, выделенный текст пустой или слишком короткий).
  • Проверьте, что работает с различными типами текстовых блоков, если планируете использовать это решение в разных контекстах.

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

Оцените материал
Добавить комментарий

Капча загружается...