diff --git a/wp-includes/deprecated.php b/wp-includes/deprecated.php
index a341958a4e..607843e989 100644
--- a/wp-includes/deprecated.php
+++ b/wp-includes/deprecated.php
@@ -5994,3 +5994,43 @@ function wp_update_https_detection_errors() {
update_option( 'https_detection_errors', $support_errors );
}
+
+/**
+ * Adds `decoding` attribute to an `img` HTML tag.
+ *
+ * The `decoding` attribute allows developers to indicate whether the
+ * browser can decode the image off the main thread (`async`), on the
+ * main thread (`sync`) or as determined by the browser (`auto`).
+ *
+ * By default WordPress adds `decoding="async"` to images but developers
+ * can use the {@see 'wp_img_tag_add_decoding_attr'} filter to modify this
+ * to remove the attribute or set it to another accepted value.
+ *
+ * @since 6.1.0
+ * @deprecated 6.4.0 Use wp_img_tag_add_loading_optimization_attrs() instead.
+ * @see wp_img_tag_add_loading_optimization_attrs()
+ *
+ * @param string $image The HTML `img` tag where the attribute should be added.
+ * @param string $context Additional context to pass to the filters.
+ * @return string Converted `img` tag with `decoding` attribute added.
+ */
+function wp_img_tag_add_decoding_attr( $image, $context ) {
+ _deprecated_function( __FUNCTION__, '6.4.0', 'wp_img_tag_add_loading_optimization_attrs()' );
+
+ /*
+ * Only apply the decoding attribute to images that have a src attribute that
+ * starts with a double quote, ensuring escaped JSON is also excluded.
+ */
+ if ( ! str_contains( $image, ' src="' ) ) {
+ return $image;
+ }
+
+ /** This action is documented in wp-includes/media.php */
+ $value = apply_filters( 'wp_img_tag_add_decoding_attr', 'async', $image, $context );
+
+ if ( in_array( $value, array( 'async', 'sync', 'auto' ), true ) ) {
+ $image = str_replace( ' $src,
- 'class' => "attachment-$size_class size-$size_class",
- 'alt' => trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ),
- 'decoding' => 'async',
+ 'src' => $src,
+ 'class' => "attachment-$size_class size-$size_class",
+ 'alt' => trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ),
);
/**
@@ -1892,11 +1891,6 @@ function wp_filter_content_tags( $content, $context = null ) {
// Add loading optimization attributes if applicable.
$filtered_image = wp_img_tag_add_loading_optimization_attrs( $filtered_image, $context );
- // Add 'decoding=async' attribute unless a 'decoding' attribute is already present.
- if ( ! str_contains( $filtered_image, ' decoding=' ) ) {
- $filtered_image = wp_img_tag_add_decoding_attr( $filtered_image, $context );
- }
-
/**
* Filters an img tag within the content for a given context.
*
@@ -1957,6 +1951,7 @@ function wp_img_tag_add_loading_optimization_attrs( $image, $context ) {
$height = preg_match( '/ height=["\']([0-9]+)["\']/', $image, $match_height ) ? (int) $match_height[1] : null;
$loading_val = preg_match( '/ loading=["\']([A-Za-z]+)["\']/', $image, $match_loading ) ? $match_loading[1] : null;
$fetchpriority_val = preg_match( '/ fetchpriority=["\']([A-Za-z]+)["\']/', $image, $match_fetchpriority ) ? $match_fetchpriority[1] : null;
+ $decoding_val = preg_match( '/ decoding=["\']([A-Za-z]+)["\']/', $image, $match_decoding ) ? $match_decoding[1] : null;
/*
* Get loading optimization attributes to use.
@@ -1970,12 +1965,53 @@ function wp_img_tag_add_loading_optimization_attrs( $image, $context ) {
'height' => $height,
'loading' => $loading_val,
'fetchpriority' => $fetchpriority_val,
+ 'decoding' => $decoding_val,
),
$context
);
- // Images should have source and dimension attributes for the loading optimization attributes to be added.
- if ( ! str_contains( $image, ' src="' ) || ! str_contains( $image, ' width="' ) || ! str_contains( $image, ' height="' ) ) {
+ // Images should have source for the loading optimization attributes to be added.
+ if ( ! str_contains( $image, ' src="' ) ) {
+ return $image;
+ }
+
+ if ( empty( $decoding_val ) ) {
+ /**
+ * Filters the `decoding` attribute value to add to an image. Default `async`.
+ *
+ * Returning a falsey value will omit the attribute.
+ *
+ * @since 6.1.0
+ *
+ * @param string|false|null $value The `decoding` attribute value. Returning a falsey value
+ * will result in the attribute being omitted for the image.
+ * Otherwise, it may be: 'async', 'sync', or 'auto'. Defaults to false.
+ * @param string $image The HTML `img` tag to be filtered.
+ * @param string $context Additional context about how the function was called
+ * or where the img tag is.
+ */
+ $filtered_decoding_attr = apply_filters(
+ 'wp_img_tag_add_decoding_attr',
+ isset( $optimization_attrs['decoding'] ) ? $optimization_attrs['decoding'] : false,
+ $image,
+ $context
+ );
+
+ // Validate the values after filtering.
+ if ( isset( $optimization_attrs['decoding'] ) && ! $filtered_decoding_attr ) {
+ // Unset `decoding` attribute if `$filtered_decoding_attr` is set to `false`.
+ unset( $optimization_attrs['decoding'] );
+ } elseif ( in_array( $filtered_decoding_attr, array( 'async', 'sync', 'auto' ), true ) ) {
+ $optimization_attrs['decoding'] = $filtered_decoding_attr;
+ }
+
+ if ( ! empty( $optimization_attrs['decoding'] ) ) {
+ $image = str_replace( ' null,
'fetchpriority' => null,
'extra_attr' => '',
- 'decoding' => 'async',
);
if ( empty( $args ) ) {
diff --git a/wp-includes/theme.php b/wp-includes/theme.php
index ba88a83fde..087d563352 100644
--- a/wp-includes/theme.php
+++ b/wp-includes/theme.php
@@ -1288,11 +1288,10 @@ function get_header_image_tag( $attr = array() ) {
$attr = wp_parse_args(
$attr,
array(
- 'src' => $header->url,
- 'width' => $width,
- 'height' => $height,
- 'alt' => $alt,
- 'decoding' => 'async',
+ 'src' => $header->url,
+ 'width' => $width,
+ 'height' => $height,
+ 'alt' => $alt,
)
);
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 12c498d428..49eedfd198 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '6.4-alpha-56689';
+$wp_version = '6.4-alpha-56690';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
diff --git a/wp-includes/widgets/class-wp-widget-media-image.php b/wp-includes/widgets/class-wp-widget-media-image.php
index 23822fb425..2505f26b88 100644
--- a/wp-includes/widgets/class-wp-widget-media-image.php
+++ b/wp-includes/widgets/class-wp-widget-media-image.php
@@ -240,12 +240,11 @@ class WP_Widget_Media_Image extends WP_Widget_Media {
}
$attr = array(
- 'class' => $classes,
- 'src' => $instance['url'],
- 'alt' => $instance['alt'],
- 'width' => $instance['width'],
- 'height' => $instance['height'],
- 'decoding' => 'async',
+ 'class' => $classes,
+ 'src' => $instance['url'],
+ 'alt' => $instance['alt'],
+ 'width' => $instance['width'],
+ 'height' => $instance['height'],
);
$loading_optimization_attr = wp_get_loading_optimization_attributes(