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

Parser: Normalize data types and fix default implementation #10107

Merged
merged 5 commits into from
Oct 6, 2018
Merged
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
6 changes: 4 additions & 2 deletions lib/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ function gutenberg_parse_blocks( $content ) {
if ( ! has_blocks( $content ) ) {
return array(
array(
'attrs' => array(),
'innerHTML' => $content,
'blockName' => null,
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => $content,
),
);
}
Expand Down
35 changes: 25 additions & 10 deletions lib/parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,26 +259,26 @@ private function peg_f1($pre, $bs, $post) { return peg_join_blocks( $pre, $bs, $
private function peg_f2($blockName, $a) { return $a; }
private function peg_f3($blockName, $attrs) {
return array(
'blockName' => $blockName,
'attrs' => $attrs,
'blockName' => $blockName,
'attrs' => isset( $attrs ) ? $attrs : array(),
'innerBlocks' => array(),
'innerHTML' => '',
'innerHTML' => '',
);
}
private function peg_f4($s, $children, $e) {
list( $innerHTML, $innerBlocks ) = peg_array_partition( $children, 'is_string' );

return array(
'blockName' => $s['blockName'],
'attrs' => $s['attrs'],
'blockName' => $s['blockName'],
'attrs' => $s['attrs'],
'innerBlocks' => $innerBlocks,
'innerHTML' => implode( '', $innerHTML ),
'innerHTML' => implode( '', $innerHTML ),
);
}
private function peg_f5($blockName, $attrs) {
return array(
'blockName' => $blockName,
'attrs' => $attrs,
'attrs' => isset( $attrs ) ? $attrs : array(),
);
}
private function peg_f6($blockName) {
Expand Down Expand Up @@ -1461,7 +1461,12 @@ function peg_join_blocks( $pre, $tokens, $post ) {
$blocks = array();

if ( ! empty( $pre ) ) {
$blocks[] = array( 'attrs' => array(), 'innerHTML' => $pre );
$blocks[] = array(
'blockName' => null,
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => $pre
);
}

foreach ( $tokens as $token ) {
Expand All @@ -1470,12 +1475,22 @@ function peg_join_blocks( $pre, $tokens, $post ) {
$blocks[] = $token;

if ( ! empty( $html ) ) {
$blocks[] = array( 'attrs' => array(), 'innerHTML' => $html );
$blocks[] = array(
'blockName' => null,
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => $html
);
}
}

if ( ! empty( $post ) ) {
$blocks[] = array( 'attrs' => array(), 'innerHTML' => $post );
$blocks[] = array(
'blockName' => null,
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => $post
);
}

return $blocks;
Expand Down
60 changes: 36 additions & 24 deletions packages/block-serialization-default-parser/parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ function __construct( $block, $token_start, $token_length, $prev_offset = null,
* Parses a document and constructs a list of parsed block objects
*
* @since 3.8.0
* @since 4.0.0 returns arrays not objects, all attributes are arrays
*/
class WP_Block_Parser {
/**
Expand Down Expand Up @@ -244,17 +245,14 @@ function proceed() {
*/
if ( 0 === $stack_depth ) {
if ( isset( $leading_html_start ) ) {
$this->output[] = array(
'attrs' => array(),
'innerHTML' => substr(
$this->document,
$leading_html_start,
$start_offset - $leading_html_start
),
);
$this->output[] = (array) self::freeform( substr(
$this->document,
$leading_html_start,
$start_offset - $leading_html_start
) );
}

$this->output[] = new WP_Block_Parser_Block( $block_name, $attrs, array(), '' );
$this->output[] = (array) new WP_Block_Parser_Block( $block_name, $attrs, array(), '' );
$this->offset = $start_offset + $token_length;
return true;
}
Expand Down Expand Up @@ -370,7 +368,14 @@ function next_token() {
$namespace = ( isset( $namespace ) && -1 !== $namespace[ 1 ] ) ? $namespace[ 0 ] : 'core/';
$name = $namespace . $matches[ 'name' ][ 0 ];
$has_attrs = isset( $matches[ 'attrs' ] ) && -1 !== $matches[ 'attrs' ][ 1 ];
$attrs = $has_attrs ? json_decode( $matches[ 'attrs' ][ 0 ] ) : null;

/*
* Fun fact! It's not trivial in PHP to create "an empty associative array" since all arrays
* are associative arrays. If we use `array()` we get a JSON `[]`
*/
$attrs = $has_attrs
? json_decode( $matches[ 'attrs' ][ 0 ], /* as-associative */ true )
: json_decode( '{}', /* don't ask why, just verify in PHP */ false );

/*
* This state isn't allowed
Expand All @@ -391,6 +396,19 @@ function next_token() {
return array( 'block-opener', $name, $attrs, $started_at, $length );
}

/**
* Returns a new block object for freeform HTML
*
* @internal
* @since 3.9.0
*
* @param string $innerHTML HTML content of block
* @return WP_Block_Parser_Block freeform block object
*/
static function freeform( $innerHTML ) {
return new WP_Block_Parser_Block( null, array(), array(), $innerHTML );
}

/**
* Pushes a length of text from the input document
* to the output list as a freeform block
Expand All @@ -406,10 +424,7 @@ function add_freeform( $length = null ) {
return;
}

$this->output[] = array(
'attrs' => new stdClass(),
'innerHTML' => substr( $this->document, $this->offset, $length ),
);
$this->output[] = (array) self::freeform( substr( $this->document, $this->offset, $length ) );
}

/**
Expand All @@ -423,7 +438,7 @@ function add_freeform( $length = null ) {
* @param int $token_length byte length of entire block from start of opening token to end of closing token
* @param int|null $last_offset last byte offset into document if continuing form earlier output
*/
function add_inner_block(WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) {
function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) {
$parent = $this->stack[ count( $this->stack ) - 1 ];
$parent->block->innerBlocks[] = $block;
$parent->block->innerHTML .= substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset );
Expand All @@ -446,16 +461,13 @@ function add_block_from_stack( $end_offset = null ) {
: substr( $this->document, $prev_offset );

if ( isset( $stack_top->leading_html_start ) ) {
$this->output[] = array(
'attrs' => array(),
'innerHTML' => substr(
$this->document,
$stack_top->leading_html_start,
$stack_top->token_start - $stack_top->leading_html_start
),
);
$this->output[] = (array) self::freeform( substr(
$this->document,
$stack_top->leading_html_start,
$stack_top->token_start - $stack_top->leading_html_start
) );
}

$this->output[] = $stack_top->block;
$this->output[] = (array) $stack_top->block;
}
}
25 changes: 8 additions & 17 deletions packages/block-serialization-default-parser/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ function Block( blockName, attrs, innerBlocks, innerHTML ) {
};
}

function Freeform( innerHTML ) {
return Block( null, {}, [], innerHTML );
}

function Frame( block, tokenStart, tokenLength, prevOffset, leadingHtmlStart ) {
return {
block,
Expand Down Expand Up @@ -78,10 +82,7 @@ function proceed() {
// in the top-level of the document
if ( 0 === stackDepth ) {
if ( null !== leadingHtmlStart ) {
output.push( {
attrs: {},
innerHTML: document.substr( leadingHtmlStart, startOffset - leadingHtmlStart ),
} );
output.push( Freeform( document.substr( leadingHtmlStart, startOffset - leadingHtmlStart ) ) );
}
output.push( Block( blockName, attrs, [], '' ) );
offset = startOffset + tokenLength;
Expand Down Expand Up @@ -196,7 +197,7 @@ function nextToken() {
const namespace = namespaceMatch || 'core/';
const name = namespace + nameMatch;
const hasAttrs = !! attrsMatch;
const attrs = hasAttrs ? parseJSON( attrsMatch ) : null;
const attrs = hasAttrs ? parseJSON( attrsMatch ) : {};

// This state isn't allowed
// This is an error
Expand All @@ -223,14 +224,7 @@ function addFreeform( rawLength ) {
return;
}

// why is this not a Frame? it's because the current grammar
// specifies an object that's different. we can update the
// specification and change here if we want to but for now we
// want this parser to be spec-compliant
output.push( {
attrs: {},
innerHTML: document.substr( offset, length ),
} );
output.push( Freeform( document.substr( offset, length ) ) );
}

function addInnerBlock( block, tokenStart, tokenLength, lastOffset ) {
Expand All @@ -253,10 +247,7 @@ function addBlockFromStack( endOffset ) {
}

if ( null !== leadingHtmlStart ) {
output.push( {
attrs: {},
innerHTML: document.substr( leadingHtmlStart, tokenStart - leadingHtmlStart ),
} );
output.push( Freeform( document.substr( leadingHtmlStart, tokenStart - leadingHtmlStart ) ) );
}

output.push( block );
Expand Down
43 changes: 30 additions & 13 deletions packages/block-serialization-spec-parser/grammar.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,12 @@ if ( ! function_exists( 'peg_join_blocks' ) ) {
$blocks = array();

if ( ! empty( $pre ) ) {
$blocks[] = array( 'attrs' => array(), 'innerHTML' => $pre );
$blocks[] = array(
'blockName' => null,
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => $pre
);
}

foreach ( $tokens as $token ) {
Expand All @@ -80,12 +85,22 @@ if ( ! function_exists( 'peg_join_blocks' ) ) {
$blocks[] = $token;

if ( ! empty( $html ) ) {
$blocks[] = array( 'attrs' => array(), 'innerHTML' => $html );
$blocks[] = array(
'blockName' => null,
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => $html
);
}
}

if ( ! empty( $post ) ) {
$blocks[] = array( 'attrs' => array(), 'innerHTML' => $post );
$blocks[] = array(
'blockName' => null,
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => $post
);
}

return $blocks;
Expand All @@ -96,8 +111,10 @@ if ( ! function_exists( 'peg_join_blocks' ) ) {

function freeform( s ) {
return s.length && {
blockName: null,
attrs: {},
innerHTML: s
innerBlocks: [],
innerHTML: s,
};
}

Expand Down Expand Up @@ -180,16 +197,16 @@ Block_Void
{
/** <?php
return array(
'blockName' => $blockName,
'attrs' => $attrs,
'blockName' => $blockName,
'attrs' => isset( $attrs ) ? $attrs : array(),
'innerBlocks' => array(),
'innerHTML' => '',
'innerHTML' => '',
);
?> **/

return {
blockName: blockName,
attrs: attrs,
attrs: attrs || {},
innerBlocks: [],
innerHTML: ''
};
Expand All @@ -202,10 +219,10 @@ Block_Balanced
list( $innerHTML, $innerBlocks ) = peg_array_partition( $children, 'is_string' );

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

Expand All @@ -230,13 +247,13 @@ Block_Start
/** <?php
return array(
'blockName' => $blockName,
'attrs' => $attrs,
'attrs' => isset( $attrs ) ? $attrs : array(),
);
?> **/

return {
blockName: blockName,
attrs: attrs
attrs: attrs || {}
};
}

Expand Down
Loading