filters - How can I extend the Gutenberg table block transform to allow colspansrowspans on pasted table <td> elem

admin2025-01-08  6

I'm trying to allow users to paste (relatively) simple tables into Gutenberg. The editor converts the raw HTML fine but strips out any attributes/classes. For the most part this is good - I want to ensure the markup is clean - but it strips out the colspan and rowspan attributes too.

Looking into the table block in the Gutenberg repo on GitHub and block filters in the Guenberg Handbook on wordpress, I've put together the following:

const { getPhrasingContentSchema } = wp.blocks;

// Partially defines what's allowed in a table when pasted.
// Copied from the core table block file in the Gutenberg repo.
const tableContentPasteSchema = {
    tr: {
        children: {
            th: {
                children: getPhrasingContentSchema(),
            },
            td: {
                children: getPhrasingContentSchema(),

                // This is the only new part in the schema
                attributes: [ 'colspan', 'rowspan'],
            },
        },
    },
};

// Partially defines what's allowed in a table when pasted.
// Copied from the core table block file in the Gutenberg repo.
const tablePasteSchema = {
    table: {
        children: {
            thead: {
                children: tableContentPasteSchema,
            },
            tfoot: {
                children: tableContentPasteSchema,
            },
            tbody: {
                children: tableContentPasteSchema,
            },
        },
    },
};

// Overloads the table block transforms setting
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
);

(Code based on example here: )

This all seems to be correct as far as I can tell, but any colspan/rowspans are stripped when pasted in. In addition, manually editing the block in the post HTML causes a block error which can only be resolved by removing the colspan/rowspan attribute.

It's worth noting that if I use the same code but allow colspan on a <span> inside the <td> that works absolutely fine (despite <span colspan="2"> not being valid HTML).

What am I doing wrong? Is there another approach to overloading the core/table block's allowed attributes? Is there something else in core that's prohibiting <td> attributes?

I'm trying to allow users to paste (relatively) simple tables into Gutenberg. The editor converts the raw HTML fine but strips out any attributes/classes. For the most part this is good - I want to ensure the markup is clean - but it strips out the colspan and rowspan attributes too.

Looking into the table block in the Gutenberg repo on GitHub and block filters in the Guenberg Handbook on wordpress.org, I've put together the following:

const { getPhrasingContentSchema } = wp.blocks;

// Partially defines what's allowed in a table when pasted.
// Copied from the core table block file in the Gutenberg repo.
const tableContentPasteSchema = {
    tr: {
        children: {
            th: {
                children: getPhrasingContentSchema(),
            },
            td: {
                children: getPhrasingContentSchema(),

                // This is the only new part in the schema
                attributes: [ 'colspan', 'rowspan'],
            },
        },
    },
};

// Partially defines what's allowed in a table when pasted.
// Copied from the core table block file in the Gutenberg repo.
const tablePasteSchema = {
    table: {
        children: {
            thead: {
                children: tableContentPasteSchema,
            },
            tfoot: {
                children: tableContentPasteSchema,
            },
            tbody: {
                children: tableContentPasteSchema,
            },
        },
    },
};

// Overloads the table block transforms setting
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
);

(Code based on example here: https://wordpress.org/gutenberg/handbook/designers-developers/developers/filters/block-filters/#blocks-registerblocktype)

This all seems to be correct as far as I can tell, but any colspan/rowspans are stripped when pasted in. In addition, manually editing the block in the post HTML causes a block error which can only be resolved by removing the colspan/rowspan attribute.

It's worth noting that if I use the same code but allow colspan on a <span> inside the <td> that works absolutely fine (despite <span colspan="2"> not being valid HTML).

What am I doing wrong? Is there another approach to overloading the core/table block's allowed attributes? Is there something else in core that's prohibiting <td> attributes?

Share Improve this question edited Nov 20, 2019 at 7:18 Amol Bhandari SJ 2611 silver badge16 bronze badges asked Feb 26, 2019 at 10:47 Tommy FerryTommy Ferry 715 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

The issue arises because Gutenberg’s table block enforces strict schema validation. Even if you adjust the schema for pasting HTML, the saved attributes for <td> or <th> elements (like colspan and rowspan) are also validated against the block's save and edit logic. If the attributes aren’t explicitly allowed in the block's registration, Gutenberg will strip them out, leading to errors.

To resolve this and allow colspan and rowspan attributes on table cells, you’ll need to modify the schema and ensure the attributes are preserved during the block's save and edit processes. Here’s how you can fix it:


Solution: Modify the Core Table Block

This solution involves extending the core table block's behavior to include support for colspan and rowspan.

  1. Modify the Schema for the td and th Elements

Adjust the schema so that colspan and rowspan are allowed for td and th.

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

const tableContentSchema = {
    tr: {
        children: {
            th: {
                children: getPhrasingContentSchema(),
                attributes: [ 'colspan', 'rowspan' ], // Allow colspan and rowspan on <th>
            },
            td: {
                children: getPhrasingContentSchema(),
                attributes: [ 'colspan', 'rowspan' ], // Allow colspan and rowspan on <td>
            },
        },
    },
};

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

  1. Override the Table Block's transforms to Use Your Schema

Hook into the block registration process and replace the transforms.from logic with your schema.

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. Add Attribute Support for colspan and rowspan

Extend the core/table block to save and recognize these attributes.

wp.hooks.addFilter(
    'blocks.getSaveContent.extraProps',
    'my-plugin/table-cell-attributes',
    ( extraProps, blockType, attributes ) => {
        if ( blockType.name === 'core/table' ) {
            // Ensure colspan and rowspan are preserved
            if ( attributes.colspan ) {
                extraProps.colspan = attributes.colspan;
            }
            if ( attributes.rowspan ) {
                extraProps.rowspan = attributes.rowspan;
            }
        }
        return extraProps;
    }
);

  1. Preserve Attributes During Save

Update the save logic of the table block to ensure the colspan and rowspan attributes are saved properly. You can accomplish this by extending the table cell rendering logic.


  1. Test Your Changes

  2. Paste a Table:

    • Paste HTML with <td colspan="2"> or <th rowspan="3"> into the block editor.
    • Confirm that the attributes are not stripped.
  3. Edit HTML:

    • Edit the block in the HTML editor and manually add colspan or rowspan.
    • Confirm no block error appears.

Why <span> Worked?

Gutenberg is less restrictive with inline elements like <span> because they aren't part of the default table block schema. By explicitly modifying the table schema, the same flexibility can be applied to <td> and <th>.


Additional Notes

  • Core Updates: Monitor future Gutenberg updates. If colspan and rowspan support are added natively, this custom logic may no longer be needed.
  • Custom Blocks: If modifying the core block proves too restrictive or brittle, consider creating a custom table block that includes full support for these attributes.
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1736265738a1064.html

最新回复(0)