-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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 Bindings: Add support to image caption attribute in block bindings #61255
Open
SantosGuillamot
wants to merge
39
commits into
trunk
Choose a base branch
from
add/support-all-image-attributes-in-block-bindings
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
6939eb5
Add support in the JS hook
SantosGuillamot 33ebfd8
Add support in the PHP array
SantosGuillamot 1539bb5
Transform figure > a selector into a
SantosGuillamot 47bac8c
Modify the image rendering if bindings are set
SantosGuillamot 841165d
Add support for image caption
SantosGuillamot 31a78b8
Adapt Gutenberg compatibility filters
SantosGuillamot 2abb001
Use regex (temporary)
SantosGuillamot 49f327c
Fix regex
SantosGuillamot c85de98
Another approach: Remove tags in render
SantosGuillamot f69662d
Update supported binding attribtues in another file
talldan d1734c5
Update client side pattern override supported attributes
talldan 953eea5
Add `set_inner_text` private method instead of using regex
SantosGuillamot 7f00489
Support only caption
SantosGuillamot cac2dd1
Only run `set_inner_text` when figcaption exists
SantosGuillamot fd58bcf
Go back to existing `save.js`
SantosGuillamot c5abad9
Fix typo
SantosGuillamot 3a9c6e8
Remove comment
SantosGuillamot 01ca7ee
Hide caption controls if the caption is binded
cbravobernal 2967e88
Remove user permissions check
cbravobernal ec0e52c
Add caption e2e tests
SantosGuillamot fa01364
Copy latest changes from core
SantosGuillamot f39fa0b
Remove extra return
SantosGuillamot 45cd9e4
Fix bookmarks
SantosGuillamot da0886d
Fix compatibility with older versions
SantosGuillamot 75fc917
Move logic to 6.6 compat folder
SantosGuillamot 0fe9b31
Only process image caption in 6.6 compat
SantosGuillamot 435058e
Remove extra spaces
SantosGuillamot 895110a
Don't grab bookmarks until the end
SantosGuillamot 3e183b7
Remove release_bookmark
SantosGuillamot a2b825c
Add warning
SantosGuillamot 77d7116
Make filter caption specific
SantosGuillamot dc568a9
Only process caption in WP 6.5
SantosGuillamot 6eeb7c2
Change conditional
SantosGuillamot 0e3b174
Add support for 6.4
SantosGuillamot 7311680
Clarify methods only apply to figcaption
SantosGuillamot d38d635
Remove check to always run caption processing
SantosGuillamot 586d7df
Add backport changelog
SantosGuillamot ac597ee
Move changelog to 6.7 folder
SantosGuillamot be4c4c2
Remove caption restriction in pattern overrides
SantosGuillamot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
https://github.com/WordPress/wordpress-develop/pull/6838 | ||
|
||
* https://github.com/WordPress/gutenberg/pull/61255 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ function gutenberg_replace_pattern_override_default_binding( $parsed_block ) { | |
$supported_block_attrs = array( | ||
'core/paragraph' => array( 'content' ), | ||
'core/heading' => array( 'content' ), | ||
'core/image' => array( 'id', 'url', 'title', 'alt' ), | ||
'core/image' => array( 'id', 'url', 'title', 'alt', 'caption' ), | ||
'core/button' => array( 'url', 'text', 'linkTarget', 'rel' ), | ||
); | ||
|
||
|
@@ -44,3 +44,237 @@ function gutenberg_replace_pattern_override_default_binding( $parsed_block ) { | |
} | ||
|
||
add_filter( 'render_block_data', 'gutenberg_replace_pattern_override_default_binding', 10, 1 ); | ||
|
||
/** | ||
* Replace the caption value in the HTML based on the binding value. | ||
* | ||
* @param string $block_content Block Content. | ||
* @param string $block_name The name of the block to process. | ||
* @param string $attribute_name The attribute name to replace. | ||
* @param mixed $source_value The value used to replace in the HTML. | ||
* @return string The modified block content. | ||
*/ | ||
function gutenberg_block_bindings_replace_caption( $block_content, $block_name, string $attribute_name, $source_value ) { | ||
// Create private anonymous class until the HTML API provides `set_inner_html` method. | ||
$block_reader = new class($block_content) extends WP_HTML_Tag_Processor{ | ||
/** | ||
* THESE METHODS ARE A TEMPORARY SOLUTION NOT TO BE EMULATED. | ||
* IT IS A TEMPORARY SOLUTION THAT JUST WORKS FOR THIS SPECIFIC | ||
* USE CASE UNTIL THE HTML PROCESSOR PROVIDES ITS OWN METHOD. | ||
*/ | ||
|
||
/** | ||
* Replace the inner content of a figcaption element with the passed content. | ||
* | ||
* @param string $new_content New content to insert in the figcaption element. | ||
* @return bool Whether the inner content was properly replaced. | ||
*/ | ||
public function gutenberg_set_content_between_figcaption_balanced_tags( $new_content ) { | ||
// Check that the processor is paused on an opener tag. | ||
if ( $this->is_tag_closer() || 'FIGCAPTION' !== $this->get_tag() ) { | ||
return false; | ||
} | ||
|
||
// Set position of the opener tag. | ||
$this->set_bookmark( 'opener_tag' ); | ||
|
||
/* | ||
* This is a best-effort guess to visit the closer tag and check it exists. | ||
* In the future, this code should rely on the HTML Processor for this kind of operation. | ||
*/ | ||
$tag_name = $this->get_tag(); | ||
if ( ! $this->next_tag( | ||
array( | ||
'tag_name' => $tag_name, | ||
'tag_closers' => 'visit', | ||
) | ||
) || ! $this->is_tag_closer() ) { | ||
return false; | ||
} | ||
|
||
// Set position of the closer tag. | ||
$this->set_bookmark( 'closer_tag' ); | ||
|
||
// Get opener and closer tag bookmarks. | ||
$opener_tag_bookmark = $this->bookmarks['opener_tag']; | ||
$closer_tag_bookmark = $this->bookmarks['closer_tag']; | ||
|
||
// Appends the new content. | ||
// Compat for 6.4, where bookmarks and WP_HTML_Text_Replacement are different. | ||
if ( ! empty( $opener_tag_bookmark->end ) ) { | ||
$this->lexical_updates[] = new WP_HTML_Text_Replacement( $opener_tag_bookmark->end + 1, $closer_tag_bookmark->start, $new_content ); | ||
return true; | ||
} | ||
|
||
$after_opener_tag = $opener_tag_bookmark->start + $opener_tag_bookmark->length; | ||
/* | ||
* There was a bug in the HTML Processor token length fixed after 6.5. | ||
* This check is needed to add compatibility for that. | ||
* Related issue: https://github.com/WordPress/wordpress-develop/pull/6625 | ||
*/ | ||
if ( '>' === $this->html[ $after_opener_tag ] ) { | ||
++$after_opener_tag; | ||
} | ||
$inner_content_length = $closer_tag_bookmark->start - $after_opener_tag; | ||
$this->lexical_updates[] = new WP_HTML_Text_Replacement( $after_opener_tag, $inner_content_length, $new_content ); | ||
return true; | ||
} | ||
|
||
/** | ||
* Add a new figcaption element after the `img` or `a` tag. | ||
* | ||
* @param string $new_element New figcaption element to append after the tag. | ||
* @return bool Whether the element was properly appended. | ||
*/ | ||
public function gutenberg_append_figcaption_element_after_tag( $new_element ) { | ||
$tag_name = $this->get_tag(); | ||
// Ensure figcaption is only added in the correct place. | ||
if ( 'IMG' !== $tag_name && 'A' !== $tag_name ) { | ||
return false; | ||
} | ||
$this->set_bookmark( 'current_tag' ); | ||
// Visit the closing tag if exists. | ||
if ( ! $this->next_tag( | ||
array( | ||
'tag_name' => $tag_name, | ||
'tag_closers' => 'visit', | ||
) | ||
) || ! $this->is_tag_closer() ) { | ||
$this->seek( 'current_tag' ); | ||
$this->release_bookmark( 'current_tag' ); | ||
} | ||
|
||
// Get position of the closer tag. | ||
$this->set_bookmark( 'closer_tag' ); | ||
$closer_tag_bookmark = $this->bookmarks['closer_tag']; | ||
// Compat for 6.4, where bookmarks and WP_HTML_Text_Replacement are different. | ||
if ( ! empty( $closer_tag_bookmark->end ) ) { | ||
$this->lexical_updates[] = new WP_HTML_Text_Replacement( $closer_tag_bookmark->end + 1, $closer_tag_bookmark->end + 1, $new_element ); | ||
return true; | ||
} | ||
$after_closer_tag = $closer_tag_bookmark->start + $closer_tag_bookmark->length; | ||
/* | ||
* There was a bug in the HTML Processor token length fixed after 6.5. | ||
* This check is needed to add compatibility for that. | ||
* Related issue: https://github.com/WordPress/wordpress-develop/pull/6625 | ||
*/ | ||
if ( '>' === $this->html[ $after_closer_tag ] ) { | ||
++$after_closer_tag; | ||
} | ||
|
||
// Append the new element. | ||
$this->lexical_updates[] = new WP_HTML_Text_Replacement( $after_closer_tag, 0, $new_element ); | ||
return true; | ||
} | ||
|
||
/** | ||
* Remove the current figcaption tag element. | ||
* | ||
* @return bool Whether the element was properly removed. | ||
*/ | ||
public function gutenberg_remove_figcaption_tag_element() { | ||
$tag_name = $this->get_tag(); | ||
// Ensure only figcaption is removed. | ||
if ( 'FIGCAPTION' !== $tag_name ) { | ||
return false; | ||
} | ||
// Set position of the opener tag. | ||
$this->set_bookmark( 'opener_tag' ); | ||
|
||
// Visit the closing tag. | ||
if ( ! $this->next_tag( | ||
array( | ||
'tag_name' => $tag_name, | ||
'tag_closers' => 'visit', | ||
) | ||
) || ! $this->is_tag_closer() ) { | ||
return false; | ||
} | ||
|
||
// Set position of the closer tag. | ||
$this->set_bookmark( 'closer_tag' ); | ||
|
||
// Get position of the tags. | ||
$opener_tag_bookmark = $this->bookmarks['opener_tag']; | ||
$closer_tag_bookmark = $this->bookmarks['closer_tag']; | ||
|
||
// Compat for 6.4, where bookmarks and WP_HTML_Text_Replacement are different. | ||
if ( ! empty( $closer_tag_bookmark->end ) ) { | ||
$this->lexical_updates[] = new WP_HTML_Text_Replacement( $opener_tag_bookmark->start, $closer_tag_bookmark->end + 1, '' ); | ||
return true; | ||
} | ||
|
||
$after_closer_tag = $closer_tag_bookmark->start + $closer_tag_bookmark->length; | ||
/* | ||
* There was a bug in the HTML Processor token length fixed after 6.5. | ||
* This check is needed to add compatibility for that. | ||
* Related issue: https://github.com/WordPress/wordpress-develop/pull/6625 | ||
*/ | ||
if ( '>' === $this->html[ $after_closer_tag ] ) { | ||
++$after_closer_tag; | ||
} | ||
$current_tag_length = $after_closer_tag - $opener_tag_bookmark->start; | ||
|
||
// Remove the current tag. | ||
$this->lexical_updates[] = new WP_HTML_Text_Replacement( $opener_tag_bookmark->start, $current_tag_length, '' ); | ||
return true; | ||
} | ||
}; | ||
|
||
/* | ||
* For backward compatibility, the logic from the image render needs to be replicated. | ||
* This is because the block attributes can't be modified with the binding value with `render_block_data` filter, | ||
* as it doesn't have access to the block instance. | ||
*/ | ||
if ( $block_reader->next_tag( 'figure' ) ) { | ||
$block_reader->set_bookmark( 'figure' ); | ||
} | ||
|
||
$new_value = wp_kses_post( $source_value ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can move this escaping to |
||
|
||
if ( $block_reader->next_tag( 'figcaption' ) ) { | ||
if ( empty( $new_value ) ) { | ||
$block_reader->gutenberg_remove_figcaption_tag_element(); | ||
} else { | ||
$block_reader->gutenberg_set_content_between_figcaption_balanced_tags( $new_value ); | ||
} | ||
} else { | ||
$block_reader->seek( 'figure' ); | ||
if ( ! $block_reader->next_tag( 'a' ) ) { | ||
$block_reader->seek( 'figure' ); | ||
$block_reader->next_tag( 'img' ); | ||
} | ||
$block_reader->gutenberg_append_figcaption_element_after_tag( '<figcaption class="wp-element-caption">' . $new_value . '</figcaption>' ); | ||
} | ||
|
||
return $block_reader->get_updated_html(); | ||
} | ||
|
||
/** | ||
* Process the block bindings attribute. | ||
* | ||
* @param string $block_content Block Content. | ||
* @param array $parsed_block The full block, including name and attributes. | ||
* @param WP_Block $block_instance The block instance. | ||
* @return string Block content with the bind applied. | ||
*/ | ||
function gutenberg_process_image_caption_binding( $block_content, $parsed_block, $block_instance ) { | ||
if ( ! isset( $parsed_block['attrs']['metadata']['bindings']['caption'] ) ) { | ||
return $block_content; | ||
} | ||
|
||
$caption_binding = $parsed_block['attrs']['metadata']['bindings']['caption']; | ||
|
||
$caption_binding_source = get_block_bindings_source( $caption_binding['source'] ); | ||
$source_args = ! empty( $caption_binding['args'] ) && is_array( $caption_binding['args'] ) ? $caption_binding['args'] : array(); | ||
$source_value = $caption_binding_source->get_value( $source_args, $block_instance, 'caption' ); | ||
|
||
// If the value is not null, process the HTML based on the block and the attribute. | ||
if ( is_null( $source_value ) ) { | ||
return $block_content; | ||
} | ||
|
||
return gutenberg_block_bindings_replace_caption( $block_content, $block_instance->name, 'caption', $source_value ); | ||
} | ||
|
||
add_filter( 'render_block_core/image', 'gutenberg_process_image_caption_binding', 20, 3 ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we escape
$new_element
here?We are passing
<figcaption html>$attributes['caption']</figcaption>
.