diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index bfd71cdcb3..804a34f6ac 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -1962,6 +1962,12 @@ function wp_img_tag_add_loading_attr( $image, $context ) { * @return string Converted `img` tag with `decoding` attribute added. */ function wp_img_tag_add_decoding_attr( $image, $context ) { + // 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 ( false === strpos( $image, ' src="' ) ) { + return $image; + } + /** * Filters the `decoding` attribute value to add to an image. Default `async`. * diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php index 0d5ac75863..4d5ba64e29 100644 --- a/tests/phpunit/tests/media.php +++ b/tests/phpunit/tests/media.php @@ -3162,6 +3162,28 @@ EOF; $this->assertStringNotContainsString( ' loading=', $img ); } + /** + * Test that decoding="async" is not applied to img tags with single quotes. + * + * @ticket 56969 + */ + public function test_wp_img_tag_add_decoding_attr_with_single_quotes() { + $img = ""; + $img = wp_img_tag_add_decoding_attr( $img, 'test' ); + $this->assertStringNotContainsString( ' decoding="async"', $img ); + } + + /** + * Test that decoding="async" is not applied to img tags inside JSON. + * + * @ticket 56969 + */ + public function test_decoding_async_not_applied_to_json() { + $content = '{"image": "\"\""}'; + $content = wp_filter_content_tags( $content ); + $this->assertStringNotContainsString( ' decoding="async"', $content ); + } + /** * @ticket 50756 */