Make WordPress Core

Changeset 58298

Timestamp:
06/03/2024 04:12:00 PM (2 months ago)
Author:
audrasjb
Message:

Editor: Simplify the block bindings HTML replacement logic until the HTML API is ready.

This changeset modifies the block bindings HTML replacement logic to use a hardcoded list of selectors based on the block and a regex to substitute the inner content. The previous logic was too complex because the HTML API does not support CSS selectors yet and it does not have an official way to modify the inner HTML. This made it difficult to understand, iterate on it and add new functionalities.
As it will be solved in the future once the HTML API is ready, it is better for now to keep a simple hardcoded version that is easier to understand and iterate on.

Props santosguillamot, gziolo, petitphp.
Fixes #61351.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-block.php

    r58289 r58298  
    334334            case 'html':
    335335            case 'rich-text':
    336                 $block_reader = new WP_HTML_Tag_Processor( $block_content );
    337 
    338                 // TODO: Support for CSS selectors whenever they are ready in the HTML API.
    339                 // In the meantime, support comma-separated selectors by exploding them into an array.
    340                 $selectors = explode( ',', $block_type->attributes[ $attribute_name ]['selector'] );
    341                 // Add a bookmark to the first tag to be able to iterate over the selectors.
    342                 $block_reader->next_tag();
    343                 $block_reader->set_bookmark( 'iterate-selectors' );
    344 
    345                 // TODO: This shouldn't be needed when the `set_inner_html` function is ready.
    346                 // Store the parent tag and its attributes to be able to restore them later in the button.
    347                 // The button block has a wrapper while the paragraph and heading blocks don't.
    348                 if ( 'core/button' === $this->name ) {
    349                     $button_wrapper                 = $block_reader->get_tag();
    350                     $button_wrapper_attribute_names = $block_reader->get_attribute_names_with_prefix( '' );
    351                     $button_wrapper_attrs           = array();
    352                     foreach ( $button_wrapper_attribute_names as $name ) {
    353                         $button_wrapper_attrs[ $name ] = $block_reader->get_attribute( $name );
     336                // Hardcode the selectors and processing until the HTML API is able to read CSS selectors and replace inner HTML.
     337                // TODO: Use the HTML API instead.
     338                if ( 'core/paragraph' === $this->name && 'content' === $attribute_name ) {
     339                    $selector = 'p';
     340                }
     341                if ( 'core/heading' === $this->name && 'content' === $attribute_name ) {
     342                    $selector = 'h[1-6]';
     343                }
     344                if ( 'core/button' === $this->name && 'text' === $attribute_name ) {
     345                    // Check if it is a <button> or <a> tag.
     346                    if ( preg_match( '/<button[^>]*>.*?<\/button>/', $block_content ) ) {
     347                        $selector = 'button';
     348                    } else {
     349                        $selector = 'a';
    354350                    }
    355351                }
    356 
    357                 foreach ( $selectors as $selector ) {
    358                     // If the parent tag, or any of its children, matches the selector, replace the HTML.
    359                     if ( strcasecmp( $block_reader->get_tag( $selector ), $selector ) === 0 || $block_reader->next_tag(
    360                         array(
    361                             'tag_name' => $selector,
    362                         )
    363                     ) ) {
    364                         $block_reader->release_bookmark( 'iterate-selectors' );
    365 
    366                         // TODO: Use `set_inner_html` method whenever it's ready in the HTML API.
    367                         // Until then, it is hardcoded for the paragraph, heading, and button blocks.
    368                         // Store the tag and its attributes to be able to restore them later.
    369                         $selector_attribute_names = $block_reader->get_attribute_names_with_prefix( '' );
    370                         $selector_attrs           = array();
    371                         foreach ( $selector_attribute_names as $name ) {
    372                             $selector_attrs[ $name ] = $block_reader->get_attribute( $name );
    373                         }
    374                         $selector_markup = "<$selector>" . wp_kses_post( $source_value ) . "</$selector>";
    375                         $amended_content = new WP_HTML_Tag_Processor( $selector_markup );
    376                         $amended_content->next_tag();
    377                         foreach ( $selector_attrs as $attribute_key => $attribute_value ) {
    378                             $amended_content->set_attribute( $attribute_key, $attribute_value );
    379                         }
    380                         if ( 'core/paragraph' === $this->name || 'core/heading' === $this->name ) {
    381                             return $amended_content->get_updated_html();
    382                         }
    383                         if ( 'core/button' === $this->name ) {
    384                             $button_markup  = "<$button_wrapper>{$amended_content->get_updated_html()}</$button_wrapper>";
    385                             $amended_button = new WP_HTML_Tag_Processor( $button_markup );
    386                             $amended_button->next_tag();
    387                             foreach ( $button_wrapper_attrs as $attribute_key => $attribute_value ) {
    388                                 $amended_button->set_attribute( $attribute_key, $attribute_value );
    389                             }
    390                             return $amended_button->get_updated_html();
    391                         }
    392                     } else {
    393                         $block_reader->seek( 'iterate-selectors' );
    394                     }
    395                 }
    396                 $block_reader->release_bookmark( 'iterate-selectors' );
    397                 return $block_content;
     352                if ( empty( $selector ) ) {
     353                    return $block_content;
     354                }
     355                $pattern = '/(<' . $selector . '[^>]*>).*?(<\/' . $selector . '>)/i';
     356                return preg_replace( $pattern, '$1' . wp_kses_post( $source_value ) . '$2', $block_content );
    398357
    399358            case 'attribute':
     
    409368                $amended_content->set_attribute( $block_type->attributes[ $attribute_name ]['attribute'], $source_value );
    410369                return $amended_content->get_updated_html();
    411                 break;
    412370
    413371            default:
    414372                return $block_content;
    415                 break;
    416         }
    417         return;
     373        }
    418374    }
    419375
Note: See TracChangeset for help on using the changeset viewer.