Как я могу расширить трансформацию блока таблицы Гутенберга, чтобы разрешить colspans/rowspans в вставленных элементах таблицы?

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

Я пытаюсь позволить пользователям вставлять (относительно) простые таблицы в Gutenberg. Редактор корректно преобразует сырой HTML, но удаляет любые атрибуты/классы. В основном это хорошо – я хочу убедиться, что разметка чистая – но он также удаляет атрибуты colspan и rowspan.

Изучая блок таблицы в репозитории Gutenberg на GitHub и фильтры блоков в руководстве Gutenberg на wordpress.org, я составил следующее:

const { getPhrasingContentSchema } = wp.blocks;

// Частично определяет, что разрешено в таблице при вставке.
// Скопировано из файла основного блока таблицы в репозитории Gutenberg.
const tableContentPasteSchema = {
    tr: {
        children: {
            th: {
                children: getPhrasingContentSchema(),
            },
            td: {
                children: getPhrasingContentSchema(),

                // Это единственная новая часть в схеме
                attributes: [ 'colspan', 'rowspan'],
            },
        },
    },
};

// Частично определяет, что разрешено в таблице при вставке.
// Скопировано из файла основного блока таблицы в репозитории Gutenberg.
const tablePasteSchema = {
    table: {
        children: {
            thead: {
                children: tableContentPasteSchema,
            },
            tfoot: {
                children: tableContentPasteSchema,
            },
            tbody: {
                children: tableContentPasteSchema,
            },
        },
    },
};

// Изменяет настройки трансформаций блока таблицы
function addTableBlockSpanAttributes( settings, name ) {
    if ( name !== 'core/table' ) {
        return settings;
    }

    return lodash.assign({}, settings, {
        transforms: {
            from: [
                {
                    type: 'raw',
                    selector: 'table',
                    schema: tableSchema,
                },
            ],
        },
    });
}

wp.hooks.addFilter(
    'blocks.registerBlockType',
    'my-plugin/transforms/table-block',
    addTableBlockSpanAttributes
);

(Код основан на примере здесь: https://wordpress.org/gutenberg/handbook/designers-developers/developers/filters/block-filters/#blocks-registerblocktype)

Все это кажется правильным, насколько я могу судить, но любые colspan/rowspan удаляются при вставке. Кроме того, вручную редактируя блок в HTML поста, возникает ошибка блока, которую можно устранить только удалением атрибута colspan/rowspan.

Стоит отметить, что если я использую тот же код, но позволяю colspan на <span> внутри <td>, это работает абсолютно нормально (несмотря на то, что <span colspan="2"> не является корректным HTML).

Что я делаю не так? Есть ли другой способ перегрузить разрешенные атрибуты блока core/table? Есть ли что-то еще в ядре, что запрещает атрибуты <td>?

Проблема возникает из-за того, что блок таблицы Gutenberg обеспечивает строгую проверку схемы. Даже если вы измените схему для вставки HTML, сохраненные атрибуты для элементов <td> или <th> (такие как colspan и rowspan) также проверяются в соответствии с логикой сохранения и редактирования блока. Если атрибуты не разрешены в явном виде при регистрации блока, Gutenberg удаляет их, что приводит к ошибкам.

Чтобы решить эту проблему и разрешить атрибуты colspan и rowspan на ячейках таблицы, вам необходимо изменить схему и убедиться, что атрибуты сохраняются во время процессов сохранения и редактирования блока. Вот как вы можете это исправить:


Решение: Измените основной блок таблицы

Это решение предполагает расширение поведения основного блока table для включения поддержки colspan и rowspan.

  1. Измените схему для элементов td и th

Настройте схему так, чтобы colspan и rowspan были разрешены для td и th.

const { assign } = lodash;
const { getPhrasingContentSchema } = wp.blocks;

const tableContentSchema = {
    tr: {
        children: {
            th: {
                children: getPhrasingContentSchema(),
                attributes: [ 'colspan', 'rowspan' ], // Разрешить colspan и rowspan на <th>
            },
            td: {
                children: getPhrasingContentSchema(),
                attributes: [ 'colspan', 'rowspan' ], // Разрешить colspan и rowspan на <td>
            },
        },
    },
};

const tableSchema = {
    table: {
        children: {
            thead: {
                children: tableContentSchema,
            },
            tfoot: {
                children: tableContentSchema,
            },
            tbody: {
                children: tableContentSchema,
            },
        },
    },
};

  1. Переопределите transforms блока таблицы для использования вашей схемы

Подключитесь к процессу регистрации блока и замените логику transforms.from на вашу схему.

function addTableBlockSpanAttributes( settings, name ) {
    if ( name !== 'core/table' ) {
        return settings;
    }

    return assign({}, settings, {
        transforms: {
            from: [
                {
                    type: 'raw',
                    selector: 'table',
                    schema: tableSchema,
                },
            ],
        },
    });
}

wp.hooks.addFilter(
    'blocks.registerBlockType',
    'my-plugin/transforms/table-block',
    addTableBlockSpanAttributes
);

  1. Добавить поддержку атрибутов для colspan и rowspan

Расширьте блок core/table, чтобы сохранить и распознать эти атрибуты.

wp.hooks.addFilter(
    'blocks.getSaveContent.extraProps',
    'my-plugin/table-cell-attributes',
    ( extraProps, blockType, attributes ) => {
        if ( blockType.name === 'core/table' ) {
            // Убедитесь, что colspan и rowspan сохраняются
            if ( attributes.colspan ) {
                extraProps.colspan = attributes.colspan;
            }
            if ( attributes.rowspan ) {
                extraProps.rowspan = attributes.rowspan;
            }
        }
        return extraProps;
    }
);

  1. Сохраняйте атрибуты во время сохранения

Обновите логику save блока таблицы, чтобы убедиться, что атрибуты colspan и rowspan сохраняются корректно. Вы можете достичь этого, расширив логику рендеринга ячеек таблицы.


  1. Тестируйте ваши изменения

  2. Вставьте таблицу:

    • Вставьте HTML с <td colspan="2"> или <th rowspan="3"> в редактор блока.
    • Подтвердите, что атрибуты не удаляются.
  3. Редактировать HTML:

    • Отредактируйте блок в HTML-редакторе и вручную добавьте colspan или rowspan.
    • Подтвердите, что ошибка блока не появляется.

Почему <span> сработал?

Gutenberg менее строг к встроенным элементам, таким как <span>, потому что они не являются частью схемы блока table по умолчанию. Изменив схему таблицы в явном виде, ту же гибкость можно применить к <td> и <th>.


Дополнительные примечания

  • Обновления ядра: Следите за будущими обновлениями Gutenberg. Если поддержка colspan и rowspan будет добавлена нативно, эта пользовательская логика может больше не понадобиться.
  • Пользовательские блоки: Если изменение основного блока оказывается слишком ограничительным или хрупким, подумайте о создании пользовательского блока таблицы, который включает полную поддержку этих атрибутов.

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

Чтобы расширить функциональность блока таблицы в Gutenberg и разрешить использование атрибутов colspan и rowspan при вставке HTML-кода, необходимо внести ряд изменений в схему и логику работы блока. Важно помнить, что Gutenberg применяет строгую проверку схемы, что может приводить к удалению неразрешённых атрибутов при вставке.

Шаги для реализации

1. Изменение схемы для элементов <td> и <th>

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

const { assign } = lodash;
const { getPhrasingContentSchema } = wp.blocks;

const tableContentSchema = {
    tr: {
        children: {
            th: {
                children: getPhrasingContentSchema(),
                attributes: ['colspan', 'rowspan'], // Разрешаем colspan и rowspan для <th>
            },
            td: {
                children: getPhrasingContentSchema(),
                attributes: ['colspan', 'rowspan'], // Разрешаем colspan и rowspan для <td>
            },
        },
    },
};

const tableSchema = {
    table: {
        children: {
            thead: {
                children: tableContentSchema,
            },
            tfoot: {
                children: tableContentSchema,
            },
            tbody: {
                children: tableContentSchema,
            },
        },
    },
};

2. Переопределение трансформаций блока

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

function addTableBlockSpanAttributes(settings, name) {
    if (name !== 'core/table') {
        return settings;
    }

    return assign({}, settings, {
        transforms: {
            from: [
                {
                    type: 'raw',
                    selector: 'table',
                    schema: tableSchema,
                },
            ],
        },
    });
}

wp.hooks.addFilter(
    'blocks.registerBlockType',
    'my-plugin/transforms/table-block',
    addTableBlockSpanAttributes
);

3. Поддержка для атрибутов colspan и rowspan

Чтобы упростить работу с атрибутами, необходимо добавить поддержку этих атрибутов при сохранении и редактировании блока.

wp.hooks.addFilter(
    'blocks.getSaveContent.extraProps',
    'my-plugin/table-cell-attributes',
    (extraProps, blockType, attributes) => {
        if (blockType.name === 'core/table') {
            // Сохраняем colspan и rowspan
            if (attributes.colspan) {
                extraProps.colspan = attributes.colspan;
            }
            if (attributes.rowspan) {
                extraProps.rowspan = attributes.rowspan;
            }
        }
        return extraProps;
    }
);

4. Обеспечение сохранения атрибутов при сохранении

Вам также потребуется внести изменения в логику сохранения блока, чтобы атрибуты colspan и rowspan корректно сохранялись.

5. Тестирование

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

  1. Таблицы с атрибутами colspan и rowspan могут быть вставлены без их удаления.
  2. Редактирование HTML-кода блоков не вызывает проблем.

Почему атрибуты для <span> работали?

Атрибуты для <span> работали, потому что Gutenberg менее строгий по отношению к строчным элементам, поскольку они не входят в состав схемы блока по умолчанию. Ваша задача заключается в том, чтобы явно изменить схему таблицы, обеспечив аналогичную гибкость для элементов <td> и <th>.

Дополнительные замечания

  • Мониторинг обновлений ядра: Следите за будущими обновлениями Gutenberg. Если поддержка атрибутов colspan и rowspan будет внедрена нативно, вам может не понадобиться данное решение.
  • Создание пользовательских блоков: Если внесение изменений в ядро блока окажется слишком сложным или ненадежным, рассмотрите возможность создания кастомного блока таблицы с полной поддержкой этих атрибутов.

Таким образом, эти шаги помогут вам расширить возможности работы с блоками таблиц в Gutenberg, позволив пользователям без проблем вставлять и редактировать таблицы с атрибутами colspan и rowspan.

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

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