Как добавить кнопку «Копировать код» в блок кода Gutenberg

В WordPress у редактора Gutenberg есть стандартный блок Code / Код. Он хорошо подходит для публикации CSS, PHP, JavaScript и других фрагментов кода. Но по умолчанию в опубликованной записи у такого блока нет кнопки «Копировать». Посетителю приходится выделять код вручную, что неудобно, особенно если код длинный. Эту кнопку можно добавить небольшим сниппетом. Что получится После…

В WordPress у редактора Gutenberg есть стандартный блок Code / Код. Он хорошо подходит для публикации CSS, PHP, JavaScript и других фрагментов кода.

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

Эту кнопку можно добавить небольшим сниппетом.

Как выглядит иконка «Скопировать код»
Как выглядит иконка «Скопировать код»

Что получится

После добавления кода у каждого блока Gutenberg Code появится маленькая иконка копирования в правом верхнем углу.

При наведении появится подсказка:

Копировать код

После клика иконка на короткое время превратится в галочку, а подсказка изменится на:

Скопировано

Куда добавлять код

Удобнее всего использовать плагин WPCode или Code Snippets.

В WPCode создайте новый сниппет:

Code Type: PHP Snippet
Location: Frontend Only
Auto Insert: Run Everywhere
Status: Active

Итоговый код

/**
 * Clean copy button for Gutenberg code blocks.
 */
add_action( 'wp_footer', function () {
    if ( is_admin() ) {
        return;
    }
    ?>
    <style>
        .wp-block-code {
            position: relative;
        }

        .alx-copy-code {
            position: absolute !important;
            top: 14px;
            right: 14px;
            z-index: 5;
            width: 30px;
            height: 30px;
            padding: 4px !important;
            border: 0 !important;
            border-radius: 7px !important;
            background: transparent !important;
            box-shadow: none !important;
            color: #6b7280 !important;
            cursor: pointer;
            opacity: .88;
            appearance: none;
            -webkit-appearance: none;
        }

        .alx-copy-code:hover,
        .alx-copy-code:focus {
            background: rgba(15, 23, 42, .055) !important;
            color: #374151 !important;
            box-shadow: none !important;
            opacity: 1;
        }

        .alx-copy-code svg {
            width: 22px;
            height: 22px;
            display: block;
            fill: none;
            stroke: currentColor;
            stroke-width: 2;
            stroke-linecap: round;
            stroke-linejoin: round;
        }

        .alx-copy-code.is-copied {
            color: #16a34a !important;
            background: rgba(22, 163, 74, .075) !important;
        }

        .alx-copy-code::before {
            content: attr(data-tooltip);
            position: absolute;
            top: 50%;
            right: calc(100% + 8px);
            padding: 6px 8px;
            border: 1px solid rgba(17, 24, 39, .08);
            border-radius: 7px;
            background: rgba(255, 255, 255, .96);
            color: #4b5563;
            box-shadow: 0 8px 24px rgba(15, 23, 42, .08);
            font-size: 12px;
            font-weight: 500;
            line-height: 1;
            white-space: nowrap;
            opacity: 0;
            pointer-events: none;
            transform: translate(4px, -50%);
            transition: opacity .15s ease, transform .15s ease;
        }

        .alx-copy-code:hover::before,
        .alx-copy-code:focus::before {
            opacity: 1;
            transform: translate(0, -50%);
        }
    </style>

    <script>
    document.addEventListener('DOMContentLoaded', function () {
        var copyIcon = '<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>';
        var checkIcon = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg>';

        function copyText(text) {
            if (navigator.clipboard && window.isSecureContext) {
                return navigator.clipboard.writeText(text);
            }

            var textarea = document.createElement('textarea');
            textarea.value = text;
            textarea.style.position = 'fixed';
            textarea.style.left = '-9999px';
            document.body.appendChild(textarea);
            textarea.focus();
            textarea.select();

            return new Promise(function (resolve, reject) {
                document.execCommand('copy') ? resolve() : reject();
                textarea.remove();
            });
        }

        document.querySelectorAll('.wp-block-code').forEach(function (block) {
            if (block.querySelector('.alx-copy-code')) {
                return;
            }

            var code = block.querySelector('code');

            if (!code) {
                return;
            }

            var button = document.createElement('button');
            button.type = 'button';
            button.className = 'alx-copy-code';
            button.setAttribute('aria-label', 'Копировать код');
            button.setAttribute('data-tooltip', 'Копировать код');
            button.innerHTML = copyIcon;

            button.addEventListener('click', function () {
                copyText(code.innerText).then(function () {
                    button.classList.add('is-copied');
                    button.setAttribute('data-tooltip', 'Скопировано');
                    button.innerHTML = checkIcon;

                    setTimeout(function () {
                        button.classList.remove('is-copied');
                        button.setAttribute('data-tooltip', 'Копировать код');
                        button.innerHTML = copyIcon;
                    }, 1600);
                });
            });

            block.appendChild(button);
        });
    });
    </script>
    <?php
});

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

Сниппет добавляется в футер сайта через хук WordPress:

add_action( 'wp_footer', function () {

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

Проверка:

if ( is_admin() ) {
    return;
}

нужна, чтобы код не запускался внутри админки WordPress.

Поиск блоков кода

Gutenberg выводит блок кода с классом:

.wp-block-code

А сам код находится внутри тега:

<code>

Скрипт находит все такие блоки:

document.querySelectorAll('.wp-block-code')

и добавляет внутрь каждого маленькую кнопку.

Копирование текста

При клике код берет текст из блока:

code.innerText

и копирует его в буфер обмена.

Сначала используется современный метод:

navigator.clipboard.writeText(text)

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

Иконка и галочка

По умолчанию кнопка показывает иконку копирования.

После успешного копирования:

  • добавляется класс is-copied;
  • иконка меняется на галочку;
  • подсказка меняется на Скопировано.

Через 1.6 секунды кнопка возвращается в исходное состояние.

Почему кнопка сделана через код, а не плагином

Такой способ легкий и не требует отдельного плагина для одной маленькой функции. Код не меняет сам Gutenberg и не редактирует файлы темы. Он просто добавляет улучшение на стороне сайта.

Если вы обновите WordPress, тему или плагины, кнопка продолжит работать, потому что сниппет живет отдельно в WPCode или Code Snippets.

Итог

Этот сниппет добавляет к стандартным блокам кода Gutenberg аккуратную кнопку копирования: без тяжелых библиотек, без лишнего дизайна и без изменения файлов темы.

Похожие записи

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *