Skip to content

Commit

Permalink
Parser: Allow block nesting
Browse files Browse the repository at this point in the history
In this patch we're opening up a new avenue for allowing nested blocks
in the data structure.

For each block:
 - Nested blocks appear as `innerBlocks` as a sequential list
 - The contained HTML _without_ the nested blocks appear as a string
   property `innerHtml` which replaces `rawContent`

Also:
 - Remove `WP_` prefix on grammar terms - not needed - was there
   from the earliest iterations where different parts were prefixed
   by which spec they implemented, such as HTML_, URL_, etc...
  • Loading branch information
dmsnell committed Oct 3, 2017
1 parent 0fde369 commit 395bb69
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 52 deletions.
2 changes: 1 addition & 1 deletion blocks/api/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export function createBlockWithFallback( name, rawContent, attributes ) {
*/
export function parseWithGrammar( content ) {
return grammarParse( content ).reduce( ( memo, blockNode ) => {
const { blockName, rawContent, attrs } = blockNode;
const { blockName, innerBlocks, innerHtml: rawContent, attrs } = blockNode;
const block = createBlockWithFallback( blockName, rawContent.trim(), attrs );
if ( block ) {
memo.push( block );
Expand Down
115 changes: 64 additions & 51 deletions blocks/api/post.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
// are the same as `json_decode`
?> **/

function freeform( s ) {
return s.length && {
blockName: 'core/freeform',
innerHtml: s
};
}

function maybeJSON( s ) {
try {
return JSON.parse( s );
Expand All @@ -15,19 +22,35 @@ function maybeJSON( s ) {

}

Document
= WP_Block_List
Block_List
= pre:$(!Token .)*
ts:(t:Token html:$((!Token .)*) { /** <?php return $t; ?> **/ return [ t, html ] })*
post:$(.*)
{ /** <?php
$blocks = [];
if ( ! empty( $pre ) ) { $blocks[] = $pre; }
foreach ( $ts as $pair ) {
$blocks[] = $pair[ 0 ];
if ( ! empty( $pair[ 1 ] ) ) { $blocks[] = $pair[ 1 ] };
}
if ( ! empty( $post ) ) { $blocks[] = $post; }
WP_Block_List
= WP_Block*
return $blocks;
?> **/

WP_Block
= WP_Tag_More
/ WP_Block_Void
/ WP_Block_Balanced
/ WP_Block_Html
return [
freeform( pre ),
...ts.reduce( ( out, [ t, h ] ) => [ ...out, t, freeform( h ) ], [] ),
freeform( post ),
].filter( a => a )
}

WP_Tag_More
Token
= Tag_More
/ Block_Void
/ Block_Balanced

Tag_More
= "<!--" WS* "more" customText:(WS+ text:$((!(WS* "-->") .)+) { /** <?php return $text; ?> **/ return text })? WS* "-->" noTeaser:(WS* "<!--noteaser-->")?
{ /** <?php
$attrs = array( 'noTeaser' => (bool) $noTeaser );
Expand All @@ -37,7 +60,7 @@ WP_Tag_More
return array(
'blockName' => 'core/more',
'attrs' => $attrs,
'rawContent' => ''
'innerHtml' => ''
);
?> **/
return {
Expand All @@ -46,12 +69,12 @@ WP_Tag_More
customText: customText || undefined,
noTeaser: !! noTeaser
},
rawContent: ''
innerHtml: ''
}
}

WP_Block_Void
= "<!--" WS+ "wp:" blockName:WP_Block_Name WS+ attrs:(a:WP_Block_Attributes WS+ {
Block_Void
= "<!--" WS+ "wp:" blockName:Block_Name WS+ attrs:(a:Block_Attributes WS+ {
/** <?php return $a; ?> **/
return a;
})? "/-->"
Expand All @@ -60,62 +83,52 @@ WP_Block_Void
return array(
'blockName' => $blockName,
'attrs' => $attrs,
'rawContent' => '',
'innerBlocks' => array(),
'innerHtml' => '',
);
?> **/

return {
blockName: blockName,
attrs: attrs,
rawContent: ''
innerBlocks: [],
innerHtml: ''
};
}

WP_Block_Balanced
= s:WP_Block_Start ts:(!WP_Block_End c:Any {
/** <?php return $c; ?> **/
return c;
})* e:WP_Block_End & {
/** <?php return $s['blockName'] === $e['blockName']; ?> **/
return s.blockName === e.blockName;
}
Block_Balanced
= s:Block_Start children:(Token / $(!Block_End .))+ e:Block_End
{
/** <?php
$innerBlocks = array_filter( $children, function( $a ) {
return ! is_string( $a );
} );
$innerHtml = array_filter( $children, function( $a ) {
return is_string( $a );
} );
return array(
'blockName' => $s['blockName'],
'attrs' => $s['attrs'],
'rawContent' => implode( '', $ts ),
'innerBlocks' => $innerBlocks,
'innerHtml' => implode( '', $innerHtml ),
);
?> **/

var innerBlocks = children.filter( a => 'string' !== typeof a );
var innerHtml = children.filter( a => 'string' === typeof a ).join('');

return {
blockName: s.blockName,
attrs: s.attrs,
rawContent: ts.join( '' )
innerBlocks: innerBlocks,
innerHtml: innerHtml
};
}

WP_Block_Html
= ts:(!WP_Block_Balanced !WP_Block_Void !WP_Tag_More c:Any {
/** <?php return $c; ?> **/
return c;
})+
{
/** <?php
return array(
'attrs' => array(),
'rawContent' => implode( '', $ts ),
);
?> **/

return {
attrs: {},
rawContent: ts.join( '' )
}
}

WP_Block_Start
= "<!--" WS+ "wp:" blockName:WP_Block_Name WS+ attrs:(a:WP_Block_Attributes WS+ {
Block_Start
= "<!--" WS+ "wp:" blockName:Block_Name WS+ attrs:(a:Block_Attributes WS+ {
/** <?php return $a; ?> **/
return a;
})? "-->"
Expand All @@ -133,8 +146,8 @@ WP_Block_Start
};
}

WP_Block_End
= "<!--" WS+ "/wp:" blockName:WP_Block_Name WS+ "-->"
Block_End
= "<!--" WS+ "/wp:" blockName:Block_Name WS+ "-->"
{
/** <?php
return array(
Expand All @@ -147,10 +160,10 @@ WP_Block_End
};
}

WP_Block_Name
Block_Name
= $(ASCII_Letter (ASCII_AlphaNumeric / "/" ASCII_AlphaNumeric)*)

WP_Block_Attributes
Block_Attributes
= attrs:$("{" (!("}" WS+ """/"? "-->") .)* "}")
{
/** <?php return json_decode( $attrs, true ); ?> **/
Expand Down

0 comments on commit 395bb69

Please sign in to comment.