Make WordPress Core


Ignore:
Timestamp:
10/17/2025 11:52:41 PM (10 months ago)
Author:
dmsnell
Message:

HTML API: Backport from Gutenberg of layout image container refactor.

For classic themes, image blocks need to create a DIV wrapper which contains alignment classes from the inner FIGURE. This has been processed using PCRE matching.

With this change the HTML API is used instead of PCRE functions to provide more semantic transformation, clearer intent, and to eliminate possible parsing issues.

Developed in https://github.com/WordPress/wordpress-develop/pull/10218
Discussed in https://core.trac.wordpress.org/ticket/63694

Gutenberg patch in https://github.com/WordPress/gutenberg/pull/72264

Props dmsnell, isabel_brison.
See #63694.

File:
1 edited

Legend:

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

    r60651 r60968  
    10751075 */
    10761076function wp_restore_image_outer_container( $block_content, $block ) {
    1077         $image_with_align = "
    1078 /# 1) everything up to the class attribute contents
    1079 (
    1080         ^\s*
    1081         <figure\b
    1082         [^>]*
    1083         \bclass=
    1084         [\"']
    1085 )
    1086 # 2) the class attribute contents
    1087 (
    1088         [^\"']*
    1089         \bwp-block-image\b
    1090         [^\"']*
    1091         \b(?:alignleft|alignright|aligncenter)\b
    1092         [^\"']*
    1093 )
    1094 # 3) everything after the class attribute contents
    1095 (
    1096         [\"']
    1097         [^>]*
    1098         >
    1099         .*
    1100         <\/figure>
    1101 )/iUx";
    1102 
     1077        if ( wp_theme_has_theme_json() ) {
     1078                return $block_content;
     1079        }
     1080
     1081        $figure_processor = new WP_HTML_Tag_Processor( $block_content );
    11031082        if (
    1104                 wp_theme_has_theme_json() ||
    1105                 0 === preg_match( $image_with_align, $block_content, $matches )
     1083                ! $figure_processor->next_tag( 'FIGURE' ) ||
     1084                ! $figure_processor->has_class( 'wp-block-image' ) ||
     1085                ! (
     1086                        $figure_processor->has_class( 'alignleft' ) ||
     1087                        $figure_processor->has_class( 'aligncenter' ) ||
     1088                        $figure_processor->has_class( 'alignright' )
     1089                )
    11061090        ) {
    11071091                return $block_content;
    11081092        }
    11091093
    1110         $wrapper_classnames = array( 'wp-block-image' );
    1111 
    1112         // If the block has a classNames attribute these classnames need to be removed from the content and added back
    1113         // to the new wrapper div also.
    1114         if ( ! empty( $block['attrs']['className'] ) ) {
    1115                 $wrapper_classnames = array_merge( $wrapper_classnames, explode( ' ', $block['attrs']['className'] ) );
    1116         }
    1117         $content_classnames          = explode( ' ', $matches[2] );
    1118         $filtered_content_classnames = array_diff( $content_classnames, $wrapper_classnames );
    1119 
    1120         return '<div class="' . implode( ' ', $wrapper_classnames ) . '">' . $matches[1] . implode( ' ', $filtered_content_classnames ) . $matches[3] . '</div>';
     1094        /*
     1095         * The next section of code wraps the existing figure in a new DIV element.
     1096         * While doing it, it needs to transfer the layout and the additional CSS
     1097         * class names from the original figure upward to the wrapper.
     1098         *
     1099         * Example:
     1100         *
     1101         *     // From this…
     1102         *     <!-- wp:image {"className":"hires"} -->
     1103         *     <figure class="wp-block-image wide hires">…
     1104         *
     1105         *     // To this…
     1106         *     <div class="wp-block-image hires"><figure class="wide">…
     1107         */
     1108        $wrapper_processor = new WP_HTML_Tag_Processor( '<div>' );
     1109        $wrapper_processor->next_token();
     1110        $wrapper_processor->set_attribute(
     1111                'class',
     1112                is_string( $block['attrs']['className'] ?? null )
     1113                        ? "wp-block-image {$block['attrs']['className']}"
     1114                        : 'wp-block-image'
     1115        );
     1116
     1117        // And remove them from the existing content; it has been transferred upward.
     1118        $figure_processor->remove_class( 'wp-block-image' );
     1119        foreach ( $wrapper_processor->class_list() as $class_name ) {
     1120                $figure_processor->remove_class( $class_name );
     1121        }
     1122
     1123        return "{$wrapper_processor->get_updated_html()}{$figure_processor->get_updated_html()}</div>";
    11211124}
    11221125
Note: See TracChangeset for help on using the changeset viewer.