Make WordPress Core


Ignore:
Timestamp:
04/08/2020 12:53:18 AM (6 years ago)
Author:
azaozz
Message:

Media: Enable lazy-loading of images by automatically adding the new loading="lazy" attribute to image tags on the front-end.

  • Introduces wp_lazy_loading_enabled(), wp_filter_content_tags(), wp_img_tag_add_loading_attr(), and wp_img_tag_add_srcset_and_sizes_attr() functions.
  • Introduces wp_lazy_loading_enabled, wp_img_tag_add_loading_attr, and wp_img_tag_add_srcset_and_sizes_attr filters.

Props flixos90, addyosmani, mor10, swissspidy, pierlo, westonruter, spacedmonkey, mikeschroder, jonoaldersonwp, peterwilsoncc, narwen, jeffpaul, OptimizingMatters, futtta, mukeshpanchal27, azaozz.

Fixes #44427.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/media.php

    r47122 r47554  
    13331333        function test_wp_get_attachment_image_defaults() {
    13341334                $image    = image_downsize( self::$large_id, 'thumbnail' );
    1335                 $expected = sprintf( '<img width="%1$d" height="%2$d" src="%3$s" class="attachment-thumbnail size-thumbnail" alt="" />', $image[1], $image[2], $image[0] );
     1335                $expected = sprintf( '<img width="%1$d" height="%2$d" src="%3$s" class="attachment-thumbnail size-thumbnail" alt="" loading="lazy" />', $image[1], $image[2], $image[0] );
    13361336
    13371337                $this->assertEquals( $expected, wp_get_attachment_image( self::$large_id ) );
     
    13481348
    13491349                $image    = image_downsize( self::$large_id, 'thumbnail' );
    1350                 $expected = sprintf( '<img width="%1$d" height="%2$d" src="%3$s" class="attachment-thumbnail size-thumbnail" alt="Some very clever alt text" />', $image[1], $image[2], $image[0] );
     1350                $expected = sprintf( '<img width="%1$d" height="%2$d" src="%3$s" class="attachment-thumbnail size-thumbnail" alt="Some very clever alt text" loading="lazy" />', $image[1], $image[2], $image[0] );
    13511351
    13521352                $this->assertEquals( $expected, wp_get_attachment_image( self::$large_id ) );
     
    19651965         * @ticket 33641
    19661966         */
    1967         function test_wp_make_content_images_responsive() {
     1967        function test_wp_filter_content_tags() {
    19681968                $image_meta = wp_get_attachment_metadata( self::$large_id );
    19691969                $size_array = $this->_get_image_size_array_from_meta( $image_meta, 'medium' );
     
    19741974                // Function used to build HTML for the editor.
    19751975                $img                  = get_image_tag( self::$large_id, '', '', '', 'medium' );
     1976                $img                  = wp_img_tag_add_loading_attr( $img, 'test' );
    19761977                $img_no_size_in_class = str_replace( 'size-', '', $img );
    19771978                $img_no_width_height  = str_replace( ' width="' . $size_array[0] . '"', '', $img );
     
    20152016                $content_filtered   = sprintf( $content, $respimg, $respimg_no_size_in_class, $respimg_no_width_height, $img_no_size_id, $respimg_with_sizes_attr, $respimg_xhtml, $respimg_html5 );
    20162017
    2017                 $this->assertSame( $content_filtered, wp_make_content_images_responsive( $content_unfiltered ) );
     2018                $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
    20182019        }
    20192020
     
    20292030         * @ticket 33641
    20302031         */
    2031         function test_wp_make_content_images_responsive_wrong() {
    2032                 $image = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2032        function test_wp_filter_content_tags_wrong() {
     2033                $img = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2034                $img = wp_img_tag_add_loading_attr( $img, 'test' );
    20332035
    20342036                // Replace the src URL.
    2035                 $image_wrong_src = preg_replace( '|src="[^"]+"|', 'src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/foo.jpg"', $image );
    2036 
    2037                 $this->assertSame( $image_wrong_src, wp_make_content_images_responsive( $image_wrong_src ) );
     2037                $image_wrong_src = preg_replace( '|src="[^"]+"|', 'src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/foo.jpg"', $img );
     2038
     2039                $this->assertSame( $image_wrong_src, wp_filter_content_tags( $image_wrong_src ) );
    20382040        }
    20392041
     
    20412043         * @ticket 33641
    20422044         */
    2043         function test_wp_make_content_images_responsive_with_preexisting_srcset() {
     2045        function test_wp_filter_content_tags_with_preexisting_srcset() {
    20442046                // Generate HTML and add a dummy srcset attribute.
    2045                 $image_html = get_image_tag( self::$large_id, '', '', '', 'medium' );
    2046                 $image_html = preg_replace( '|<img ([^>]+) />|', '<img $1 ' . 'srcset="image2x.jpg 2x" />', $image_html );
     2047                $img = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2048                $img = wp_img_tag_add_loading_attr( $img, 'test' );
     2049                $img = preg_replace( '|<img ([^>]+) />|', '<img $1 ' . 'srcset="image2x.jpg 2x" />', $img );
    20472050
    20482051                // The content filter should return the image unchanged.
    2049                 $this->assertSame( $image_html, wp_make_content_images_responsive( $image_html ) );
     2052                $this->assertSame( $img, wp_filter_content_tags( $img ) );
    20502053        }
    20512054
     
    20982101         * @ticket 33641
    20992102         */
    2100         function test_wp_make_content_images_responsive_schemes() {
     2103        function test_wp_filter_content_tags_schemes() {
    21012104                $image_meta = wp_get_attachment_metadata( self::$large_id );
    21022105                $size_array = $this->_get_image_size_array_from_meta( $image_meta, 'medium' );
     
    21072110                // Build HTML for the editor.
    21082111                $img          = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2112                $img          = wp_img_tag_add_loading_attr( $img, 'test' );
    21092113                $img_https    = str_replace( 'http://', 'https://', $img );
    21102114                $img_relative = str_replace( 'http://', '//', $img );
     
    21272131                $unfiltered = sprintf( $content, $img, $img_https, $img_relative );
    21282132                $expected   = sprintf( $content, $respimg, $respimg_https, $respimg_relative );
    2129                 $actual     = wp_make_content_images_responsive( $unfiltered );
     2133                $actual     = wp_filter_content_tags( $unfiltered );
    21302134
    21312135                $this->assertSame( $expected, $actual );
     
    22612265
    22622266                $expected = '<img width="999" height="999" src="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . $year . '/' . $month . '/test-image-testsize-999x999.png"' .
    2263                         ' class="attachment-testsize size-testsize" alt=""' .
     2267                        ' class="attachment-testsize size-testsize" alt="" loading="lazy"' .
    22642268                        ' srcset="http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . $year . '/' . $month . '/test-image-testsize-999x999.png 999w,' .
    22652269                                ' http://' . WP_TESTS_DOMAIN . '/wp-content/uploads/' . $year . '/' . $month . '/test-image-large-150x150.png 150w"' .
     
    25242528                $this->assertSame( $expected, $url );
    25252529        }
     2530
     2531        /**
     2532         * @ticket 44427
     2533         */
     2534        function test_wp_lazy_load_content_media() {
     2535                $img       = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2536                $img_xhtml = str_replace( ' />', '/>', $img );
     2537                $img_html5 = str_replace( ' />', '>', $img );
     2538                $iframe    = '<iframe src="https://www.example.com"></iframe>';
     2539
     2540                $lazy_img       = wp_img_tag_add_loading_attr( $img, 'test' );
     2541                $lazy_img_xhtml = wp_img_tag_add_loading_attr( $img_xhtml, 'test' );
     2542                $lazy_img_html5 = wp_img_tag_add_loading_attr( $img_html5, 'test' );
     2543
     2544                // The following should not be modified because there already is a 'loading' attribute.
     2545                $img_eager = str_replace( ' />', ' loading="eager" />', $img );
     2546
     2547                $content = '
     2548                        <p>Image, standard.</p>
     2549                        %1$s
     2550                        <p>Image, XHTML 1.0 style (no space before the closing slash).</p>
     2551                        %2$s
     2552                        <p>Image, HTML 5.0 style.</p>
     2553                        %3$s
     2554                        <p>Image, with pre-existing "loading" attribute.</p>
     2555                        %5$s
     2556                        <p>Iframe, standard. Should not be modified.</p>
     2557                        %4$s';
     2558
     2559                $content_unfiltered = sprintf( $content, $img, $img_xhtml, $img_html5, $iframe, $img_eager );
     2560                $content_filtered   = sprintf( $content, $lazy_img, $lazy_img_xhtml, $lazy_img_html5, $iframe, $img_eager );
     2561
     2562                // Do not add srcset and sizes.
     2563                add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2564
     2565                $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
     2566
     2567                remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2568        }
     2569
     2570        /**
     2571         * @ticket 44427
     2572         */
     2573        function test_wp_lazy_load_content_media_opted_in() {
     2574                $img      = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2575                $lazy_img = wp_img_tag_add_loading_attr( $img, 'test' );
     2576
     2577                $content = '
     2578                        <p>Image, standard.</p>
     2579                        %1$s';
     2580
     2581                $content_unfiltered = sprintf( $content, $img );
     2582                $content_filtered   = sprintf( $content, $lazy_img );
     2583
     2584                // Do not add srcset and sizes while testing.
     2585                add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2586
     2587                // Enable globally for all tags.
     2588                add_filter( 'wp_lazy_loading_enabled', '__return_true' );
     2589
     2590                $this->assertSame( $content_filtered, wp_filter_content_tags( $content_unfiltered ) );
     2591                remove_filter( 'wp_lazy_loading_enabled', '__return_true' );
     2592                remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2593        }
     2594
     2595        /**
     2596         * @ticket 44427
     2597         */
     2598        function test_wp_lazy_load_content_media_opted_out() {
     2599                $img = get_image_tag( self::$large_id, '', '', '', 'medium' );
     2600
     2601                $content = '
     2602                        <p>Image, standard.</p>
     2603                        %1$s';
     2604                $content = sprintf( $content, $img );
     2605
     2606                // Do not add srcset and sizes while testing.
     2607                add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2608
     2609                // Disable globally for all tags.
     2610                add_filter( 'wp_lazy_loading_enabled', '__return_false' );
     2611
     2612                $this->assertSame( $content, wp_filter_content_tags( $content ) );
     2613                remove_filter( 'wp_lazy_loading_enabled', '__return_false' );
     2614                remove_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' );
     2615        }
     2616
     2617        /**
     2618         * @ticket 44427
     2619         */
     2620        function test_wp_img_tag_add_loading_attr_single_quote() {
     2621                $img = "<img src='example.png' alt='' width='300' height='225' />";
     2622                $img = wp_img_tag_add_loading_attr( $img, 'test' );
     2623
     2624                $this->assertContains( " loading='lazy'", $img );
     2625        }
    25262626}
    25272627
Note: See TracChangeset for help on using the changeset viewer.