WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.24k stars 4.09k forks source link

Support transforming wrapped content in type: 'shortcode' transforms #17758

Open jakeparis opened 4 years ago

jakeparis commented 4 years ago

I am creating a block which is created when transformed from a shortcode. In other words, this:

[example att1="foo" att2="bar"]
    <p>Inner.</p>
    <p>Content.</p>
[/example]

should transform into this a myplugin/example block with inner blocks of the two p tags.

So far I've got this, which works fine to get the shortcode attributes.

(function(wp){

    wp.blocks.registerBlockType( 'myplugin/example', {
        ...

        attributes: {
            att1 {
                type: 'string',
                default: '',
            },
            att2: {
                type: 'string',
                default: '',
            },
        }, 

        transforms: {
            from: [
                {
                    type: 'shortcode',
                    tag: 'example',
                    attributes: {
                        att1: {
                            type: 'string',
                            shortcode: attributes => {
                                return attributes.named.att1 || '';
                            }
                        },
                        att2: {
                            type: 'string',
                            shortcode: attributes => {
                                return attributes.named.att2 || '';
                            },
                        },
                    },
                },
            ],
        },
        ...

I can get the content by looking at the second parameter in one of those attributes shortcode functions:

attributes: {
    att1: {
        shortcode: (attributes, data) => {
             // data.shortcode.content is the shortcode's inner content
        }
    }
}

But I don't know how to insert that content as innerBlocks in the output block. The block registration "transforms" attribute documentation is not helpful in this area.

I've tried using the transform function along with type: "shortcode", but they don't seem to work together.

simonhammes commented 4 years ago

As far as I know this is currently not possible. The transform mechanism for shortcodes does not allow returning a block object. However, this is something I would like to see in the future, similar to how block -> block transforms work.

In the meantime, one possible hack is to create and insert a new block with the corresponding inner blocks inside of the arrow function. Unfortunately you then have to manually delete the second, empty block.

jakeparis commented 4 years ago

The way I got around this was to add a block -> block transform (from core/shortcode to my custom one) which manually parses out the shortcode attributes and content. But this is still a two-step transform, as first we have to transform to the shortcode block, then transform to my custom block.

It feels like a no-brainer that the "shortcode" type should be able to automatically use the inner content of the shortcode as innerBlocks with no configuration. I wouldn't mind working on that myself and perhaps submitting a PR, but I can't find where that lives in the code.

Can we add a label for "Feature Request" or "Enhancement Request" ?

greatislander commented 4 years ago

Related to #6020.

kadamwhite commented 4 years ago

We ran into this as well. The best interim approach we found was to convert the shortcode's inner content string into a temporary attribute on the block, and then whenever the block's Edit method rendered and that attribute was present, we unset the attribute and used pasteHandler to convert that content to blocks and insert as children of the current block. Clunky; it'd definitely be best to support this conversion natively!

simonhammes commented 4 years ago

@kadamwhite Does this work with nested shortcodes?

kadamwhite commented 4 years ago

Renamed the issue for hopefully greater clarity. cc @ellatrix to make sure this isn't an overstep :)

ocean90 commented 4 years ago

@kadamwhite Can you point me to an example for the workaround with the pasteHandler() in combination with InnerBlocks? Would like to extend this in the callout block on w.org.

kadamwhite commented 4 years ago

@ocean90 i’m overdue to write up that trick, so keep pressing me on that point, but I don’t want the presence of a workaround to distract from fixing the underlying issue

efc commented 1 year ago

Any progress on this? It is really unfortunate that the shortcode transform can't handle such a common shortcode use case!

@kadamwhite, the pasteHandler() workaround sounds very helpful. If you have written that up or have an example, I'd love a pointer.

wpexplorer commented 1 year ago

Any progress on this?