Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Parser: Add tokens for inner blocks in inner HTML #11309

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/block-serialization-default-parser/parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -440,8 +440,9 @@ function add_freeform( $length = null ) {
*/
function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) {
$parent = $this->stack[ count( $this->stack ) - 1 ];
$next_html = substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset );
$parent->block->innerHTML .= $next_html . '<!-- {' . count( $parent->block->innerBlocks ) . '} -->';
$parent->block->innerBlocks[] = $block;
$parent->block->innerHTML .= substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset );
$parent->prev_offset = $last_offset ? $last_offset : $token_start + $token_length;
}

Expand Down
9 changes: 4 additions & 5 deletions packages/block-serialization-default-parser/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,10 @@ function addFreeform( rawLength ) {

function addInnerBlock( block, tokenStart, tokenLength, lastOffset ) {
const parent = stack[ stack.length - 1 ];
parent.block.innerBlocks.push( block );
parent.block.innerHTML += document.substr(
parent.prevOffset,
tokenStart - parent.prevOffset,
);
const parentBlock = parent.block;
const nextHTML = document.substr( parent.prevOffset, tokenStart - parent.prevOffset );
parentBlock.innerHTML += `${ nextHTML }<!-- {${ parentBlock.innerBlocks.length }} -->`;
parentBlock.innerBlocks.push( block );
parent.prevOffset = lastOffset ? lastOffset : tokenStart + tokenLength;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`block-serialization-default-parser-js basic parsing parse() works properly 1`] = `
Array [
Object {
"attrs": Object {},
"blockName": "core/more",
"innerBlocks": Array [],
"innerHTML": "<!--more-->",
},
]
`;

exports[`block-serialization-default-parser-php basic parsing parse() works properly 1`] = `
Array [
Object {
"attrs": Object {},
"blockName": "core/more",
"innerBlocks": Array [],
"innerHTML": "<!--more-->",
},
]
`;
85 changes: 18 additions & 67 deletions packages/block-serialization-default-parser/test/index.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,24 @@
/**
* External dependencies
*/
import path from 'path';
import { spawnSync } from 'child_process';

/**
* Internal dependencies
*/
import { testParser } from '../../block-serialization-spec-parser/shared-tests';
import { parse } from '../';

describe( 'block-serialization-spec-parser', () => {
test( 'parse() accepts inputs with multiple Reusable blocks', () => {
const result = parse(
'<!-- wp:block {"ref":313} /--><!-- wp:block {"ref":482} /-->'
);

expect( result ).toEqual( [
{
blockName: 'core/block',
attrs: { ref: 313 },
innerBlocks: [],
innerHTML: '',
},
{
blockName: 'core/block',
attrs: { ref: 482 },
innerBlocks: [],
innerHTML: '',
},
] );
} );

test( 'treats void blocks and empty blocks identically', () => {
expect( parse(
'<!-- wp:block /-->'
) ).toEqual( parse(
'<!-- wp:block --><!-- /wp:block -->'
) );

expect( parse(
'<!-- wp:my/bus { "is": "fast" } /-->'
) ).toEqual( parse(
'<!-- wp:my/bus { "is": "fast" } --><!-- /wp:my/bus -->'
) );
} );

test( 'should grab HTML soup before block openers', () => {
[
'<p>Break me</p><!-- wp:block /-->',
'<p>Break me</p><!-- wp:block --><!-- /wp:block -->',
].forEach( ( input ) => expect( parse( input ) ).toEqual( [
expect.objectContaining( { innerHTML: '<p>Break me</p>' } ),
expect.objectContaining( { blockName: 'core/block', innerHTML: '' } ),
] ) );
} );

test( 'should grab HTML soup before inner block openers', () => {
[
'<!-- wp:outer --><p>Break me</p><!-- wp:block /--><!-- /wp:outer -->',
'<!-- wp:outer --><p>Break me</p><!-- wp:block --><!-- /wp:block --><!-- /wp:outer -->',
].forEach( ( input ) => expect( parse( input ) ).toEqual( [
expect.objectContaining( {
innerBlocks: [ expect.objectContaining( { blockName: 'core/block', innerHTML: '' } ) ],
innerHTML: '<p>Break me</p>',
} ),
] ) );
} );
describe( 'block-serialization-default-parser-js', testParser( parse ) );

test( 'should grab HTML soup after blocks', () => {
[
'<!-- wp:block /--><p>Break me</p>',
'<!-- wp:block --><!-- /wp:block --><p>Break me</p>',
].forEach( ( input ) => expect( parse( input ) ).toEqual( [
expect.objectContaining( { blockName: 'core/block', innerHTML: '' } ),
expect.objectContaining( { innerHTML: '<p>Break me</p>' } ),
] ) );
} );
} );
describe( 'block-serialization-default-parser-php', testParser( ( document ) => JSON.parse(
spawnSync(
'php',
[ '-f', path.join( __dirname, 'test-parser.php' ) ],
{
input: document,
encoding: 'utf8',
}
).stdout
) ) );
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

require_once __DIR__ . '/../parser.php';

$parser = new WP_Block_Parser();

echo json_encode( $parser->parse( file_get_contents( 'php://stdin' ) ) );
46 changes: 26 additions & 20 deletions packages/block-serialization-spec-parser/grammar.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,21 @@
// are the same as `json_decode`

// array arguments are backwards because of PHP
if ( ! function_exists( 'peg_array_partition' ) ) {
function peg_array_partition( $array, $predicate ) {
$truthy = array();
$falsey = array();
if ( ! function_exists( 'peg_process_inner_content' ) ) {
function peg_process_inner_content( $array ) {
$innerHTML = '';
$innerBlocks = array();

foreach ( $array as $item ) {
call_user_func( $predicate, $item )
? $truthy[] = $item
: $falsey[] = $item;
if ( is_string( $item ) ) {
$innerHTML .= $item;
} else {
$innerHTML .= '<!-- {' . count( $innerBlocks ) . '} -->';
$innerBlocks[] = $item;
}
}

return array( $truthy, $falsey );
return array( $innerHTML, $innerBlocks );
}
}

Expand Down Expand Up @@ -151,22 +154,25 @@ function maybeJSON( s ) {
}
}

function partition( predicate, list ) {
function processInnerContent( list ) {
var i, l, item;
var truthy = [];
var falsey = [];
var innerHTML = '';
var innerBlocks = [];

// nod to performance over a simpler reduce
// and clone model we could have taken here
for ( i = 0, l = list.length; i < l; i++ ) {
item = list[ i ];

predicate( item )
? truthy.push( item )
: falsey.push( item )
};
if ( 'string' === typeof item ) {
innerHTML += item;
} else {
innerHTML += '<!-- {' + innerBlocks.length + '} -->';
innerBlocks.push( item );
}
}

return [ truthy, falsey ];
return [ innerHTML, innerBlocks ];
}

}
Expand Down Expand Up @@ -216,25 +222,25 @@ Block_Balanced
= s:Block_Start children:(Block / $(!Block_End .))* e:Block_End
{
/** <?php
list( $innerHTML, $innerBlocks ) = peg_array_partition( $children, 'is_string' );
list( $innerHTML, $innerBlocks ) = peg_process_inner_content( $children );

return array(
'blockName' => $s['blockName'],
'attrs' => $s['attrs'],
'innerBlocks' => $innerBlocks,
'innerHTML' => implode( '', $innerHTML ),
'innerHTML' => $innerHTML,
);
?> **/

var innerContent = partition( function( a ) { return 'string' === typeof a }, children );
var innerContent = processInnerContent( children );
var innerHTML = innerContent[ 0 ];
var innerBlocks = innerContent[ 1 ];

return {
blockName: s.blockName,
attrs: s.attrs,
innerBlocks: innerBlocks,
innerHTML: innerHTML.join( '' )
innerHTML: innerHTML
};
}

Expand Down
46 changes: 26 additions & 20 deletions packages/block-serialization-spec-parser/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading