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

Block supports: Restore root DOMDocument save #25028

Merged
merged 10 commits into from
Sep 7, 2020
25 changes: 18 additions & 7 deletions lib/block-supports/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,18 @@ function gutenberg_apply_block_supports( $block_content, $block ) {
return $block_content;
}

// We need to wrap the block in order to handle UTF-8 properly.
$wrapper_left = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>';
$wrapper_right = '</body></html>';

$dom = new DOMDocument( '1.0', 'utf-8' );

// Suppress DOMDocument::loadHTML warnings from polluting the front-end.
$previous = libxml_use_internal_errors( true );

$success = $dom->loadHTML( $wrapper_left . $block_content . $wrapper_right, LIBXML_HTML_NODEFDTD | LIBXML_COMPACT );
// We need to wrap the block in order to handle UTF-8 properly.
$wrapped_block_html =
'<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>'
. $block_content
. '</body></html>';

$success = $dom->loadHTML( $wrapped_block_html, LIBXML_HTML_NODEFDTD | LIBXML_COMPACT );

// Clear errors and reset the use_errors setting.
libxml_clear_errors();
Expand All @@ -71,9 +73,13 @@ function gutenberg_apply_block_supports( $block_content, $block ) {
return $block_content;
}

// Structure is like `<html><head/><body/></html>`, so body is the `lastChild` of our document.
$body_element = $dom->documentElement->lastChild; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase

$xpath = new DOMXPath( $dom );
$block_root = $xpath->query( '/html/body/*' )[0];
$block_root = $xpath->query( './*', $body_element )[0];
sirreal marked this conversation as resolved.
Show resolved Hide resolved

// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
if ( empty( $block_root ) ) {
return $block_content;
}
Expand All @@ -98,7 +104,12 @@ function gutenberg_apply_block_supports( $block_content, $block ) {
$block_root->setAttribute( 'style', implode( '; ', $new_styles ) . ';' );
}

return $dom->saveHtml( $block_root );
$result = '';
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
foreach ( $body_element->childNodes as $child_node ) {
$result .= $dom->saveHtml( $child_node );
sirreal marked this conversation as resolved.
Show resolved Hide resolved
}
return $result;
}
add_filter( 'render_block', 'gutenberg_apply_block_supports', 10, 2 );

Expand Down
36 changes: 36 additions & 0 deletions phpunit/class-block-supported-styles-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -861,4 +861,40 @@ public function test_render_block_attribute() {
$this->assertEquals( $expected, $result );
}
}

/**
* Ensure that HTML appended to the block content is preserved.
*/
public function test_render_block_includes_appended_html() {
$this->register_block_type(
'core/example',
array(
'render_callback' => function( $attributes, $content ) {
return $content . '<div>Appended</div>';
},
)
);

$result = do_blocks( '<!-- wp:core/example --><p>Hello from the block content!</p><!-- /wp:core/example -->' );

$this->assertEquals( '<p class="wp-block-example">Hello from the block content!</p><div>Appended</div>', $result );
}

/**
* Should not error when the rendered block is text only.
*/
public function test_render_block_rendered_text_node() {
$this->register_block_type(
'core/example',
array(
'render_callback' => function() {
return 'This is rendered as just text.';
},
)
);

$result = do_blocks( '<!-- wp:core/example /-->' );

$this->assertEquals( 'This is rendered as just text.', $result );
}
}