Make WordPress Core


Ignore:
Timestamp:
02/09/2024 06:20:12 PM (9 months ago)
Author:
youknowriad
Message:

Editor: Update the WordPress packages to Gutenberg 17.7RC1.

This brings the latest and greatest from Gutenberg.
The full changelog is available here
https://github.com/WordPress/gutenberg/releases/tag/v17.7.0-rc.1

Props youknowriad, get_dave.
See #60315.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/blocks/image.php

    r57377 r57578  
    2121    }
    2222
    23     $processor = new WP_HTML_Tag_Processor( $content );
    24 
    25     if ( ! $processor->next_tag( 'img' ) || null === $processor->get_attribute( 'src' ) ) {
     23    $p = new WP_HTML_Tag_Processor( $content );
     24
     25    if ( ! $p->next_tag( 'img' ) || null === $p->get_attribute( 'src' ) ) {
    2626        return '';
    2727    }
    2828
    2929    if ( isset( $attributes['data-id'] ) ) {
    30         // Add the data-id="$id" attribute to the img element
    31         // to provide backwards compatibility for the Gallery Block,
    32         // which now wraps Image Blocks within innerBlocks.
    33         // The data-id attribute is added in a core/gallery `render_block_data` hook.
    34         $processor->set_attribute( 'data-id', $attributes['data-id'] );
     30        // Adds the data-id="$id" attribute to the img element to provide backwards
     31        // compatibility for the Gallery Block, which now wraps Image Blocks within
     32        // innerBlocks. The data-id attribute is added in a core/gallery
     33        // `render_block_data` hook.
     34        $p->set_attribute( 'data-id', $attributes['data-id'] );
    3535    }
    3636
     
    3939
    4040    /*
    41      * If the lightbox is enabled and the image is not linked, add the filter
    42      * and the JavaScript view file.
     41     * If the lightbox is enabled and the image is not linked, adds the filter and
     42     * the JavaScript view file.
    4343     */
    4444    if (
     
    4848        true === $lightbox_settings['enabled']
    4949    ) {
     50        $suffix = wp_scripts_get_suffix();
     51        if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
     52            $module_url = gutenberg_url( '/build/interactivity/image.min.js' );
     53        }
     54
     55        wp_register_script_module(
     56            '@wordpress/block-library/image',
     57            isset( $module_url ) ? $module_url : includes_url( "blocks/image/view{$suffix}.js" ),
     58            array( '@wordpress/interactivity' ),
     59            defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
     60        );
     61
    5062        wp_enqueue_script_module( '@wordpress/block-library/image' );
    5163
     
    5466         * it runs after the duotone filter and that duotone styles are applied to
    5567         * the image in the lightbox. Lightbox has to work with any plugins that
    56          * might use filters as well. Removing this can be considered in the
    57          * future if the way the blocks are rendered changes, or if a
    58          * new kind of filter is introduced.
     68         * might use filters as well. Removing this can be considered in the future
     69         * if the way the blocks are rendered changes, or if a new kind of filter is
     70         * introduced.
    5971         */
    6072        add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 );
     
    6678    }
    6779
    68     return $processor->get_updated_html();
     80    return $p->get_updated_html();
    6981}
    7082
     
    7991 */
    8092function block_core_image_get_lightbox_settings( $block ) {
    81     // Get the lightbox setting from the block attributes.
     93    // Gets the lightbox setting from the block attributes.
    8294    if ( isset( $block['attrs']['lightbox'] ) ) {
    8395        $lightbox_settings = $block['attrs']['lightbox'];
     
    90102        //
    91103        // NOTE: If no block-level settings are found, the previous call to
    92         // `wp_get_global_settings` will return the whole `theme.json`
    93         // structure in which case we can check if the "lightbox" key is present at
    94         // the top-level of the global settings and use its value.
     104        // `wp_get_global_settings` will return the whole `theme.json` structure in
     105        // which case we can check if the "lightbox" key is present at the top-level
     106        // of the global settings and use its value.
    95107        if ( isset( $lightbox_settings['lightbox'] ) ) {
    96108            $lightbox_settings = wp_get_global_settings( array( 'lightbox' ) );
     
    111123function block_core_image_render_lightbox( $block_content, $block ) {
    112124    /*
    113      * If it's not possible that an IMG element exists then return the given
    114      * block content as-is. It may be that there's no actual image in the block
    115      * or it could be that another plugin already modified this HTML.
     125     * If there's no IMG tag in the block then return the given block content
     126     * as-is. There's nothing that this code can knowingly modify to add the
     127     * lightbox behavior.
    116128     */
    117     if ( false === stripos( $block_content, '<img' ) ) {
     129    $p = new WP_HTML_Tag_Processor( $block_content );
     130    if ( $p->next_tag( 'figure' ) ) {
     131        $p->set_bookmark( 'figure' );
     132    }
     133    if ( ! $p->next_tag( 'img' ) ) {
    118134        return $block_content;
    119135    }
    120136
    121     $processor = new WP_HTML_Tag_Processor( $block_content );
    122 
    123     $aria_label = __( 'Enlarge image' );
    124 
    125     /*
    126      * If there's definitely no IMG element in the block then return the given
    127      * block content as-is. There's nothing that this code can knowingly modify
    128      * to add the lightbox behavior.
    129      */
    130     if ( ! $processor->next_tag( 'img' ) ) {
    131         return $block_content;
    132     }
    133 
    134     $alt_attribute = $processor->get_attribute( 'alt' );
    135 
    136     // An empty alt attribute `alt=""` is valid for decorative images.
    137     if ( is_string( $alt_attribute ) ) {
    138         $alt_attribute = trim( $alt_attribute );
    139     }
    140 
    141     // It only makes sense to append the alt text to the button aria-label when the alt text is non-empty.
    142     if ( $alt_attribute ) {
     137    $alt              = $p->get_attribute( 'alt' );
     138    $img_uploaded_src = $p->get_attribute( 'src' );
     139    $img_class_names  = $p->get_attribute( 'class' );
     140    $img_styles       = $p->get_attribute( 'style' );
     141    $img_width        = 'none';
     142    $img_height       = 'none';
     143    $aria_label       = __( 'Enlarge image' );
     144
     145    if ( $alt ) {
    143146        /* translators: %s: Image alt text. */
    144         $aria_label = sprintf( __( 'Enlarge image: %s' ), $alt_attribute );
    145     }
    146 
    147     // Currently, we are only enabling the zoom animation.
    148     $lightbox_animation = 'zoom';
    149 
    150     // Note: We want to store the `src` in the context so we
    151     // can set it dynamically when the lightbox is opened.
     147        $aria_label = sprintf( __( 'Enlarge image: %s' ), $alt );
     148    }
     149
    152150    if ( isset( $block['attrs']['id'] ) ) {
    153151        $img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] );
     
    155153        $img_width        = $img_metadata['width'] ?? 'none';
    156154        $img_height       = $img_metadata['height'] ?? 'none';
    157     } else {
    158         $img_uploaded_src = $processor->get_attribute( 'src' );
    159         $img_width        = 'none';
    160         $img_height       = 'none';
    161     }
    162 
    163     if ( isset( $block['attrs']['scale'] ) ) {
    164         $scale_attr = $block['attrs']['scale'];
    165     } else {
    166         $scale_attr = false;
    167     }
    168 
    169     $w = new WP_HTML_Tag_Processor( $block_content );
    170     $w->next_tag( 'figure' );
    171     $w->add_class( 'wp-lightbox-container' );
    172     $w->set_attribute( 'data-wp-interactive', '{"namespace":"core/image"}' );
    173 
    174     $w->set_attribute(
     155    }
     156
     157    // Figure.
     158    $p->seek( 'figure' );
     159    $figure_class_names = $p->get_attribute( 'class' );
     160    $figure_styles      = $p->get_attribute( 'style' );
     161    $p->add_class( 'wp-lightbox-container' );
     162    $p->set_attribute( 'data-wp-interactive', '{"namespace":"core/image"}' );
     163    $p->set_attribute(
    175164        'data-wp-context',
    176         sprintf(
    177             '{  "imageLoaded": false,
    178                 "initialized": false,
    179                 "lightboxEnabled": false,
    180                 "hideAnimationEnabled": false,
    181                 "preloadInitialized": false,
    182                 "lightboxAnimation": "%s",
    183                 "imageUploadedSrc": "%s",
    184                 "imageCurrentSrc": "",
    185                 "targetWidth": "%s",
    186                 "targetHeight": "%s",
    187                 "scaleAttr": "%s",
    188                 "dialogLabel": "%s"
    189             }',
    190             $lightbox_animation,
    191             $img_uploaded_src,
    192             $img_width,
    193             $img_height,
    194             $scale_attr,
    195             __( 'Enlarged image' )
     165        wp_json_encode(
     166            array(
     167                'uploadedSrc'      => $img_uploaded_src,
     168                'figureClassNames' => $figure_class_names,
     169                'figureStyles'     => $figure_styles,
     170                'imgClassNames'    => $img_class_names,
     171                'imgStyles'        => $img_styles,
     172                'targetWidth'      => $img_width,
     173                'targetHeight'     => $img_height,
     174                'scaleAttr'        => $block['attrs']['scale'] ?? false,
     175                'ariaLabel'        => $aria_label,
     176                'alt'              => $alt,
     177            ),
     178            JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
    196179        )
    197180    );
    198     $w->next_tag( 'img' );
    199     $w->set_attribute( 'data-wp-init', 'callbacks.initOriginImage' );
    200     $w->set_attribute( 'data-wp-on--load', 'actions.handleLoad' );
    201     $w->set_attribute( 'data-wp-watch', 'callbacks.setButtonStyles' );
    202     // We need to set an event callback on the `img` specifically
    203     // because the `figure` element can also contain a caption, and
    204     // we don't want to trigger the lightbox when the caption is clicked.
    205     $w->set_attribute( 'data-wp-on--click', 'actions.showLightbox' );
    206     $w->set_attribute( 'data-wp-watch--setStylesOnResize', 'callbacks.setStylesOnResize' );
    207     $body_content = $w->get_updated_html();
    208 
    209     // Add a button alongside image in the body content.
     181
     182    // Image.
     183    $p->next_tag( 'img' );
     184    $p->set_attribute( 'data-wp-init', 'callbacks.setButtonStyles' );
     185    $p->set_attribute( 'data-wp-on--load', 'callbacks.setButtonStyles' );
     186    $p->set_attribute( 'data-wp-on-window--resize', 'callbacks.setButtonStyles' );
     187    // Sets an event callback on the `img` because the `figure` element can also
     188    // contain a caption, and we don't want to trigger the lightbox when the
     189    // caption is clicked.
     190    $p->set_attribute( 'data-wp-on--click', 'actions.showLightbox' );
     191
     192    $body_content = $p->get_updated_html();
     193
     194    // Adds a button alongside image in the body content.
    210195    $img = null;
    211196    preg_match( '/<img[^>]+>/', $body_content, $img );
     
    230215    $body_content = preg_replace( '/<img[^>]+>/', $button, $body_content );
    231216
    232     // We need both a responsive image and an enlarged image to animate
    233     // the zoom seamlessly on slow internet connections; the responsive
    234     // image is a copy of the one in the body, which animates immediately
    235     // as the lightbox is opened, while the enlarged one is a full-sized
    236     // version that will likely still be loading as the animation begins.
    237     $m = new WP_HTML_Tag_Processor( $block_content );
    238     $m->next_tag( 'figure' );
    239     $m->add_class( 'responsive-image' );
    240     $m->next_tag( 'img' );
    241     // We want to set the 'src' attribute to an empty string in the responsive image
    242     // because otherwise, as of this writing, the wp_filter_content_tags() function in
    243     // WordPress will automatically add a 'srcset' attribute to the image, which will at
    244     // times cause the incorrectly sized image to be loaded in the lightbox on Firefox.
    245     // Because of this, we bind the 'src' attribute explicitly the current src to reliably
    246     // use the exact same image as in the content when the lightbox is first opened while
    247     // we wait for the larger image to load.
    248     $m->set_attribute( 'src', '' );
    249     $m->set_attribute( 'data-wp-bind--src', 'context.imageCurrentSrc' );
    250     $m->set_attribute( 'data-wp-style--object-fit', 'state.lightboxObjectFit' );
    251     $initial_image_content = $m->get_updated_html();
    252 
    253     $q = new WP_HTML_Tag_Processor( $block_content );
    254     $q->next_tag( 'figure' );
    255     $q->add_class( 'enlarged-image' );
    256     $q->next_tag( 'img' );
    257 
    258     // We set the 'src' attribute to an empty string to prevent the browser from loading the image
    259     // on initial page load, then bind the attribute to a selector that returns the full-sized image src when
    260     // the lightbox is opened. We could use 'loading=lazy' in combination with the 'hidden' attribute to
    261     // accomplish the same behavior, but that approach breaks progressive loading of the image in Safari
    262     // and Chrome (see https://github.com/WordPress/gutenberg/pull/52765#issuecomment-1674008151). Until that
    263     // is resolved, manually setting the 'src' seems to be the best solution to load the large image on demand.
    264     $q->set_attribute( 'src', '' );
    265     $q->set_attribute( 'data-wp-bind--src', 'state.enlargedImgSrc' );
    266     $q->set_attribute( 'data-wp-style--object-fit', 'state.lightboxObjectFit' );
    267     $enlarged_image_content = $q->get_updated_html();
    268 
    269     // If the current theme does NOT have a `theme.json`, or the colors are not defined,
    270     // we need to set the background color & close button color to some default values
    271     // because we can't get them from the Global Styles.
     217    add_action( 'wp_footer', 'block_core_image_print_lightbox_overlay' );
     218
     219    return $body_content;
     220}
     221
     222function block_core_image_print_lightbox_overlay() {
     223    $close_button_label = esc_attr__( 'Close' );
     224
     225    // If the current theme does NOT have a `theme.json`, or the colors are not
     226    // defined, it needs to set the background color & close button color to some
     227    // default values because it can't get them from the Global Styles.
    272228    $background_color   = '#fff';
    273229    $close_button_color = '#000';
     
    282238    }
    283239
    284     $close_button_icon  = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg>';
    285     $close_button_label = esc_attr__( 'Close' );
    286 
    287     $lightbox_html = <<<HTML
    288         <div data-wp-body="" class="wp-lightbox-overlay $lightbox_animation"
    289             data-wp-bind--role="state.roleAttribute"
    290             data-wp-bind--aria-label="state.dialogLabel"
    291             data-wp-class--initialized="context.initialized"
    292             data-wp-class--active="context.lightboxEnabled"
    293             data-wp-class--hideAnimationEnabled="context.hideAnimationEnabled"
    294             data-wp-bind--aria-modal="state.ariaModal"
    295             data-wp-watch="callbacks.initLightbox"
    296             data-wp-on--keydown="actions.handleKeydown"
    297             data-wp-on--touchstart="actions.handleTouchStart"
    298             data-wp-on--touchmove="actions.handleTouchMove"
    299             data-wp-on--touchend="actions.handleTouchEnd"
    300             data-wp-on--click="actions.hideLightbox"
    301             tabindex="-1"
    302             >
    303                 <button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button" data-wp-on--click="actions.hideLightbox">
    304                     $close_button_icon
    305                 </button>
    306                 <div class="lightbox-image-container">$initial_image_content</div>
    307                 <div class="lightbox-image-container">$enlarged_image_content</div>
    308                 <div class="scrim" style="background-color: $background_color" aria-hidden="true"></div>
    309         </div>
     240    echo <<<HTML
     241        <div
     242            class="wp-lightbox-overlay zoom"
     243            data-wp-interactive='{"namespace":"core/image"}'
     244            data-wp-context='{}'
     245            data-wp-bind--role="state.roleAttribute"
     246            data-wp-bind--aria-label="state.currentImage.ariaLabel"
     247            data-wp-bind--aria-modal="state.ariaModal"
     248            data-wp-class--active="state.overlayEnabled"
     249            data-wp-class--show-closing-animation="state.showClosingAnimation"
     250            data-wp-watch="callbacks.setOverlayFocus"
     251            data-wp-on--keydown="actions.handleKeydown"
     252            data-wp-on--touchstart="actions.handleTouchStart"
     253            data-wp-on--touchmove="actions.handleTouchMove"
     254            data-wp-on--touchend="actions.handleTouchEnd"
     255            data-wp-on--click="actions.hideLightbox"
     256            data-wp-on-window--resize="callbacks.setOverlayStyles"
     257            data-wp-on-window--scroll="actions.handleScroll"
     258            tabindex="-1"
     259            >
     260                <button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button">
     261                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg>
     262                </button>
     263                <div class="lightbox-image-container">
     264                    <figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.currentImage.figureStyles">
     265                        <img data-wp-bind--alt="state.currentImage.alt" data-wp-bind--class="state.currentImage.imgClassNames" data-wp-bind--style="state.imgStyles" data-wp-bind--src="state.currentImage.currentSrc">
     266                    </figure>
     267                </div>
     268                <div class="lightbox-image-container">
     269                    <figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.currentImage.figureStyles">
     270                        <img data-wp-bind--alt="state.currentImage.alt" data-wp-bind--class="state.currentImage.imgClassNames" data-wp-bind--style="state.imgStyles" data-wp-bind--src="state.enlargedSrc">
     271                    </figure>
     272                </div>
     273                <div class="scrim" style="background-color: $background_color" aria-hidden="true"></div>
     274                <style data-wp-text="state.overlayStyles"></style>
     275        </div>
    310276HTML;
    311 
    312     return str_replace( '</figure>', $lightbox_html . '</figure>', $body_content );
    313277}
    314278
     
    323287        )
    324288    );
    325 
    326     wp_register_script_module(
    327         '@wordpress/block-library/image',
    328         defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ? gutenberg_url( '/build/interactivity/image.min.js' ) : includes_url( 'blocks/image/view.min.js' ),
    329         array( '@wordpress/interactivity' ),
    330         defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
    331     );
    332289}
    333290add_action( 'init', 'register_block_core_image' );
Note: See TracChangeset for help on using the changeset viewer.