diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 4d024400a324aa..cdac5b719d6d39 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -22,7 +22,36 @@ function render_block_core_image( $attributes, $content, $block ) { return ''; } - $p = new WP_HTML_Tag_Processor( $content ); + $p = new class( $content ) extends WP_HTML_Tag_Processor { + /** + * Return input span for an empty FIGCAPTION element. + * + * Returns span of input for an empty FIGCAPTION, if currently matched on a + * FIGCAPTION opening tag and if the element is properly closed and empty. + * + * @since 6.9.0 + * + * @return WP_HTML_Span|false Span of input if the element is empty; otherwise false. + */ + public function block_core_image_extract_empty_figcaption_element() { + $this->set_bookmark( 'here' ); + $opener = $this->bookmarks['here']; + + // Allow comments within the definition of “empty.” + while ( $this->next_token() && '#comment' === $this->get_token_name() ) { + continue; + } + + if ( 'FIGCAPTION' !== $this->get_tag() || ! $this->is_tag_closer() ) { + return false; + } + + $this->set_bookmark( 'here' ); + $closer = $this->bookmarks['here']; + + return new WP_HTML_Span( $opener->start, $closer->start + $closer->length - $opener->start ); + } + }; if ( ! $p->next_tag( 'img' ) || ! $p->get_attribute( 'src' ) ) { return ''; @@ -57,6 +86,14 @@ function render_block_core_image( $attributes, $content, $block ) { $p->set_attribute( 'data-id', $data_id ); } + /* + * If the `caption` attribute is empty and we encounter a `
` element, + * we take note of its span so we can remove it later. + */ + if ( $p->next_tag( 'FIGCAPTION' ) && empty( $attributes['caption'] ) ) { + $figcaption_span = $p->block_core_image_extract_empty_figcaption_element(); + } + $link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none'; $lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block ); @@ -88,7 +125,11 @@ function render_block_core_image( $attributes, $content, $block ) { remove_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15 ); } - return $p->get_updated_html(); + $output = $p->get_updated_html(); + if ( ! empty( $figcaption_span ) ) { + return substr( $output, 0, $figcaption_span->start ) . substr( $output, $figcaption_span->start + $figcaption_span->length ); + } + return $output; } /** diff --git a/phpunit/blocks/render-block-image-test.php b/phpunit/blocks/render-block-image-test.php index fe39aee8c50b9d..ec65d5537ca2f2 100644 --- a/phpunit/blocks/render-block-image-test.php +++ b/phpunit/blocks/render-block-image-test.php @@ -12,6 +12,14 @@ * @group blocks */ class Tests_Blocks_Render_Image extends WP_UnitTestCase { + public function tear_down() { + if ( get_block_bindings_source( 'test/source' ) ) { + unregister_block_bindings_source( 'test/source' ); + } + + parent::tear_down(); + } + /** * @covers ::render_block_core_image */ @@ -59,4 +67,63 @@ public function test_should_not_render_block_core_image_when_src_is_empty_string $rendered_block = gutenberg_render_block_core_image( $attributes, $content, $block ); $this->assertEquals( '', $rendered_block ); } + + public function test_should_use_image_id_from_block_bindings_in_classname() { + register_block_bindings_source( + 'test/source', + array( + 'label' => array( 'label' => 'Test Source' ), + 'get_value_callback' => function () { + return 123; + }, + ) + ); + + $attributes = array( + 'metadata' => array( + 'bindings' => array( + 'id' => array( + 'source' => 'test/source', + ), + ), + ), + 'id' => 456, + ); + $content = '
'; + $parsed_blocks = parse_blocks( + '' + ); + $parsed_block = $parsed_blocks[0]; + $block = new WP_Block( $parsed_block ); + + $rendered_block = gutenberg_render_block_core_image( $attributes, $content, $block ); + $this->assertSame( '
', $rendered_block ); + } + + public function test_should_keep_figcaption_if_it_is_not_empty() { + $content = '
Image caption
'; + $parsed_blocks = parse_blocks( + '' + ); + $parsed_block = $parsed_blocks[0]; + $block = new WP_Block( $parsed_block ); + + $rendered_block = gutenberg_render_block_core_image( array(), $content, $block ); + $this->assertSame( '
Image caption
', $rendered_block ); + } + + public function test_should_remove_figcaption_when_caption_is_empty() { + $attributes = array( + 'caption' => '', + ); + $content = '
'; + $parsed_blocks = parse_blocks( + '' + ); + $parsed_block = $parsed_blocks[0]; + $block = new WP_Block( $parsed_block ); + + $rendered_block = gutenberg_render_block_core_image( $attributes, $content, $block ); + $this->assertSame( '
', $rendered_block ); + } }