Как я могу добавить классы к тегу body в iframe Gutenberg (editor-canvas)? Добавлено в WP 6.2(?)

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

Я полагаю, что контент Гутенберга был встроен в WP 6.2, если все блоки имеют версию 3. Я использовал функцию, подобную приведенной ниже, чтобы добавить очень важные пользовательские классы к тегам <body> в админке, что, в свою очередь, изменяет способ отображения контента. Это важно для компоновки и последовательности.

add_filter('admin_body_class', function ($classes) {
    global $pagenow;

    //проверка, является ли текущая страница post.php и установлены ли параметры поста
    if ( $pagenow ==='post.php' || $pagenow ==='post-new.php' ) {
        global $post;

        /* ... */

        $classes .= ' super-important-editing-class';

    } 

    return $classes;
});

Я искал, как сумасшедший, чтобы найти фильтр, который позволит мне сделать то же самое с тегом тела iframe ('block-editor-iframe__body editor-styles-wrapper ...').

Кто-то знает, как это сделать?

Наконец, через год у меня есть решение. Думаю, его можно написать более разумно, но это то, что я придумал, если кому-то интересно.

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

functions.php
(обратите внимание на изменение от фильтра admin_body_class к действию enqueue_block_assets).

function site_editor_styles() {
    if ( is_admin() ) {

        global $pagenow;
        $classes="";

        if ( $pagenow ==='post.php' || $pagenow ==='post-new.php' ) {

            global $post;
            $post_type = get_post_type($post->ID);
            $class1 = 'my-default-class-1';
            $class2 = 'my-default-class-2';

            /* Если вы используете ACF, вы можете использовать get_field() */
            if( class_exists('ACF') ) {
                /* Проверяем, находимся ли мы на шаблоне */
                if ($post_type == 'wp_block') {
                    $class1 = 'pattern-class-1';
                    $class2 = 'pattern-class-2';
                } else {
                    $class1 = get_field('my_key', $post->ID);
                    $class1 = get_field('my_key', $post->ID);
                }
            }
            /* Если вы не используете ACF или другую альтернативу, вы можете использовать get_post_meta($post->ID, 'your_meta_key', true); */
            /*
                if ($post_type == 'wp_block') {
                    $class1 = 'pattern-class-1';
                    $class2 = 'pattern-class-2';
                } else {
                    $class1 = get_post_meta($post->ID, 'my_key', true);
                    $class1 = get_post_meta($post->ID, 'my_key', true);
                }

            */

            // Отдельные строки для ясности
            $classes .= 'post-type-' . $post_type . ' ';
            $classes .= 'my-class-' . $class1 . ' ';
            $classes .= 'my-class-' . $class2;
        }

        // Подключение или Javascript
        wp_enqueue_script(
            'custom-iframe-classes',
            get_template_directory_uri() . '/assets/js/editor.js',
            array('wp-blocks', 'wp-dom'),
            filemtime( get_stylesheet_directory() . '/assets/js/editor.js' ),
            true
        );

        // Передаем имена классов в скрипт
        wp_localize_script('custom-iframe-classes', 'iframeBodyData', [
            'classes' => $classes,
        ]);

    }
} 
add_action( 'enqueue_block_assets', 'site_editor_styles' );

editor.js

wp.domReady(() => {
    // Пытаемся добавить классы немедленно, если iframe уже доступен
    function addClassesToIframeBody() {
        const editorIframe = document.querySelector('iframe')

        if (editorIframe) {
            const editorBody= editorIframe.contentDocument.querySelector(".editor-styles-wrapper");

            if (editorBody) {

                editorBody.classList.add(...iframeBodyData.classes.split(' '));
                console.log('Классы добавлены в тело iframe');
                return true;
            }
        }
        return false;
    }

    if (!addClassesToIframeBody()) {
        // Наблюдаем за `document.body`, чтобы увидеть добавление iframe
        const observer = new MutationObserver(() => {

            const editorIframe = document.querySelector('iframe')

            if (editorIframe) {
                const editorBody= editorIframe.contentDocument.querySelector(".editor-styles-wrapper");

                if (editorBody) {
                    if (addClassesToIframeBody()) {
                        observer.disconnect();
                        console.log('Прекратили наблюдение - тело iframe найдено и изменено');
                    }
                } else {
                    console.log('Тело (.editor-styles-wrapper) не найдено')
                }
            }
        });

        console.log('Запуск MutationObserver на document.body');
        observer.observe(document.body, { childList: true, subtree: true });
    }
});

И чтобы заставить что-то произойти с новыми классами, добавленными к <body>, я также подключаю таблицу стилей.
functions.scss

function site_enqueue_editor_styles() {
    if ( is_admin() ) {
        $editor_css_path = get_stylesheet_directory() . '/assets/dist/css/gutenberg.editor.min.css';
        if (file_exists($editor_css_path)) {
            $css_version = filemtime($editor_css_path);
        } else {
            $css_version = mt_rand();
        }

        wp_enqueue_style( 'admin-editor',
            get_stylesheet_directory_uri() . '/assets/dist/css/gutenberg.editor.min.css',
            false,
            $css_version
        );
    }
}
add_action( 'enqueue_block_assets', 'site_enqueue_editor_styles' );

gutenberg.editor.scss

.block-editor-iframe__html.is-zoomed-out {
    /* Стили для уменьшенного масштаба */
    background-color: #e0e0e0;

    .block-editor-iframe__body.editor-styles-wrapper {
        padding: 0 2rem;

        .editor-visual-editor__post-title-wrapper {
            margin-top: 2rem;
        }
    }
}

.block-editor-iframe__body.editor-styles-wrapper {
    /* Это стилизует все тело */
    background-color: darkkhaki;

    &.post-type-post {
        /* стили для постов */
    }
    &.post-type-page {
        /* стили для страниц */
        background-color: lightsalmon;
    }
    &.post-type-cpt {
        /* стили для пользовательского типа поста, измените cpt на имя типа поста */
    }
    &.content-width-editorial-narrow .editor-visual-editor__post-title-wrapper {
        /* это стилизует область заголовка */
        background-color: skyblue;
        padding: 1rem 5rem;
        margin-top: 1rem !important;
    }
    &.content-width-editorial-narrow .wp-block-post-content {
        /* это стилизует область контента */
        background-color: papayawhip;
        padding: 5rem;
    }
}

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

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

Шаг 1: Использование действия enqueue_block_assets

Для начала, добавьте следующий код в файл functions.php вашей темы. Этот код будет обрабатывать добавление классов в iframe на страницах редактирования постов и страниц.

function site_editor_styles() {
    if ( is_admin() ) {
        global $pagenow;
        $classes = "";

        if ( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) {
            global $post;
            $post_type = get_post_type($post->ID);
            $class1 = 'my-default-class-1';
            $class2 = 'my-default-class-2';

            // Получение классов из метаданных
            if( class_exists('ACF') ) {
                if ($post_type == 'wp_block') {
                    $class1 = 'pattern-class-1';
                    $class2 = 'pattern-class-2';
                } else {
                    $class1 = get_field('my_key', $post->ID);
                    $class2 = get_field('my_other_key', $post->ID);
                }
            }

            $classes .= 'post-type-' . $post_type . ' ';
            $classes .= 'my-class-' . $class1 . ' ';
            $classes .= 'my-class-' . $class2;
        }

        // Подключение JavaScript
        wp_enqueue_script(
            'custom-iframe-classes',
            get_template_directory_uri() . '/assets/js/editor.js',
            array('wp-blocks', 'wp-dom'),
            filemtime(get_stylesheet_directory() . '/assets/js/editor.js'),
            true
        );

        // Передача данных классов в JavaScript
        wp_localize_script('custom-iframe-classes', 'iframeBodyData', [
            'classes' => $classes,
        ]);
    }
}
add_action('enqueue_block_assets', 'site_editor_styles');

Шаг 2: JavaScript для добавления классов в iframe

Теперь создайте файл JavaScript (editor.js) в папке assets/js вашей темы и добавьте следующий код. Этот код добавляет классы ко всем нужным элементам внутри iframe.

wp.domReady(() => {
    function addClassesToIframeBody() {
        const editorIframe = document.querySelector('iframe');

        if (editorIframe) {
            const editorBody = editorIframe.contentDocument.querySelector(".editor-styles-wrapper");

            if (editorBody) {
                editorBody.classList.add(...iframeBodyData.classes.split(' '));
                console.log('Классы добавлены к body iframe');
                return true;
            }
        }
        return false;
    }

    if (!addClassesToIframeBody()) {
        const observer = new MutationObserver(() => {
            const editorIframe = document.querySelector('iframe');

            if (editorIframe) {
                const editorBody = editorIframe.contentDocument.querySelector(".editor-styles-wrapper");
                if (editorBody && addClassesToIframeBody()) {
                    observer.disconnect();
                    console.log('Остановка наблюдений - тело iframe найдено и изменено');
                }
            }
        });

        console.log('Запуск MutationObserver на document.body');
        observer.observe(document.body, { childList: true, subtree: true });
    }
});

Шаг 3: Стилизация с помощью CSS

Добавьте соответствующие стили в ваш файл CSS, например, в gutenberg.editor.scss, чтобы применить стили к новым классам, которые вы добавили.

.block-editor-iframe__body.editor-styles-wrapper {
    background-color: darkkhaki;

    &.post-type-post {
        // Стили для постов
    }
    &.post-type-page {
        background-color: lightsalmon;
    }
}

Заключение

С помощью этого подхода вы можете легко добавлять классы к тегу внутри iframe редактирования Gutenberg. Это позволит вам управлять стилями и макетом редактора более эффективно, сохраняя при этом необходимую гибкость при создании пользовательских интерфейсов для админ-панели WordPress.

Ключевые моменты, которые стоит выделить:

  • Используйте enqueue_block_assets, чтобы обеспечить правильное подключение и передачу данных JavaScript.
  • Применяйте MutationObserver для отслеживания изменений, чтобы добавлять классы еще до полной загрузки iframe.
  • Управляйте стилями в соответствии с вашими требованиями через CSS.

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

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

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