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
attribute in the block definition, but that doesn't seem to work.
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
attribute in the block definition, but that doesn't seem to work.
1 Answer
Reset to default 1There is no built-in solution to use a shortcode's inner content as a new block's innerBlocks
. The best I was able to do is a two step process which first transforms a raw shortcode to the core shortcode block, then transform that into the new block. In that way I was able to use the inner content as innerBlocks.
The reason to do it that way is the "block" transform type has access to a more granular transform function. It ends up looking something like this:
type: 'block',
blocks: ['core/shortcode'],
isMatch: function( {text} ) {
return /^\[slidetoggle /.test(text);
},
transform: ({text}) => {
const initialStateVal = getAttributeValue('slidetoggle', 'initialstate', text);
const content = getInnerContent('slidetoggle', text);
const innerBlocks = wp.blocks.rawHandler({
HTML: content,
});
return wp.blocks.createBlock('example/slidetoggle', {
initiallyClosed: initiallyClosed,
}, innerBlocks);
},
},
and the getAttributeValue
and getInnerContent
functions look like this:
export const getAttributeValue = function(tag, att, content){
var re = new RegExp(`\\[${tag}[^\\]]* ${att}="([^"]*)"`, 'im');
var result = content.match(re);
if( result != null && result.length > 0 )
return result[1];
re = new RegExp(`\\[${tag}[^\\]]* ${att}='([^']*)'`, 'im');
result = content.match(re);
if( result != null && result.length > 0 )
return result[1];
re = new RegExp(`\\[${tag}[^\\]]* ${att}=([^\\s]*)\\s`, 'im');
result = content.match(re);
if( result != null && result.length > 0 )
return result[1];
return false;
};
export const getInnerContent = function(tag, content, shouldAutoP=true) {
const re = new RegExp(`\\[${tag}[^\\]]*?]([\\S\\s]*?)\\[\\/${tag}]`, 'i');
var result = content.match(re);
if( result == null || result.length < 1 )
return '';
if( shouldAutoP == true)
result[1] = wp.autop(result[1]);
return result[1];
};
For more details on this process, I wrote a detailed post about this.