Plugin Directory

Changeset 3735231


Ignore:
Timestamp:
10/08/2026 05:19:09 PM (2 weeks ago)
Author:
thesid66
Message:

Release 1.1.15: add per-image frontend fetch priority

Location:
lightweight-modern-media
Files:
6 edited
1 copied

Legend:

Unmodified
Added
Removed
  • lightweight-modern-media/tags/1.1.15/lightweight-modern-media.php

    r3730748 r3735231  
    55 * Plugin Name: Rupanta Media Converter
    66 * Description: Generates WebP and AVIF copies for uploaded images and serves modern formats with picture markup.
    7  * Version: 1.1.14
     7 * Version: 1.1.15
    88 * Requires at least: 6.0
    99 * Tested up to: 7.1
    … …  
    2020
    2121define( 'RUPANTA_PLUGIN_FILE', __FILE__ );
    22 define( 'RUPANTA_PLUGIN_VERSION', '1.1.14' );
     22define( 'RUPANTA_PLUGIN_VERSION', '1.1.15' );
    2323
    2424final class RUPANTA_Image_Converter {
    … …  
    2626        private const META = '_rupanta_image_converter_files';
    2727        private const META_VERSION = '_rupanta_image_converter_version';
     28        private const META_PRIORITY = '_rupanta_image_converter_priority';
    2829
    2930        private static $instance = null;
    … …  
    3132        private $settings = null;
    3233        private $last_generation_result = array();
     34        private $priority_applied = false;
    3335
    3436        public static function instance(): self {
    … …  
    4951                add_filter( 'the_content', array( $this, 'rewrite_frontend_image_html' ), 20 );
    5052                add_filter( 'attachment_fields_to_edit', array( $this, 'add_media_modal_conversion_status' ), 20, 2 );
     53                add_filter( 'attachment_fields_to_save', array( $this, 'save_media_priority_setting' ), 20, 2 );
    5154                add_filter( 'plugin_action_links_' . plugin_basename( RUPANTA_PLUGIN_FILE ), array( $this, 'add_plugin_action_links' ) );
    5255                add_action( 'wp_ajax_rupanta_image_converter_status', array( $this, 'ajax_status' ) );
    … …  
    785788                        ),
    786789                );
     790                $form_fields['rupanta_priority'] = array(
     791                        'label' => __( 'Frontend priority', 'lightweight-modern-media' ),
     792                        'input' => 'html',
     793                        'html'  => sprintf(
     794                                '<input type="hidden" name="attachments[%1$d][rupanta_priority]" value="0"><label><input type="checkbox" name="attachments[%1$d][rupanta_priority]" value="1"%2$s> %3$s</label>',
     795                                (int) $attachment->ID,
     796                                checked( '1', get_post_meta( $attachment->ID, self::META_PRIORITY, true ), false ),
     797                                esc_html__( 'Prioritize this image on the front end', 'lightweight-modern-media' )
     798                        ),
     799                        'helps' => __( 'Adds fetchpriority="high" and loading="eager" when this is the first selected priority image rendered on a page. Select only a hero or likely LCP image.', 'lightweight-modern-media' ),
     800                );
    787801
    788802                return $form_fields;
     803        }
     804
     805        public function save_media_priority_setting( array $post, array $attachment ): array {
     806                $attachment_id = isset( $post['ID'] ) ? absint( $post['ID'] ) : 0;
     807
     808                if ( ! $attachment_id || ! current_user_can( 'edit_post', $attachment_id ) || ! array_key_exists( 'rupanta_priority', $attachment ) ) {
     809                        return $post;
     810                }
     811
     812                if ( '1' === sanitize_text_field( wp_unslash( $attachment['rupanta_priority'] ) ) ) {
     813                        update_post_meta( $attachment_id, self::META_PRIORITY, '1' );
     814                } else {
     815                        delete_post_meta( $attachment_id, self::META_PRIORITY );
     816                }
     817
     818                return $post;
    789819        }
    790820
    … …  
    11681198
    11691199        public function add_picture_sources( string $html, int $attachment_id, $size, $icon, array $attr ): string {
    1170                 if ( is_admin() || ! $this->settings()['serve_picture'] || false !== strpos( $html, '<picture' ) ) {
     1200                if ( is_admin() ) {
    11711201                        return $html;
    11721202                }
    11731203
     1204                $html = $this->maybe_add_frontend_priority( $html, $attachment_id );
     1205
     1206                if ( ! $this->settings()['serve_picture'] || false !== strpos( $html, '<picture' ) ) {
     1207                        return $html;
     1208                }
     1209
    11741210                return $this->picture_markup_for_image_html( $html, $attachment_id, $size, $attr );
    11751211        }
    11761212
    11771213        public function rewrite_frontend_image_html( string $html ): string {
    1178                 if ( ! $this->settings()['serve_picture'] || false === stripos( $html, '<img' ) || false === strpos( $html, 'wp-image-' ) ) {
     1214                if ( false === stripos( $html, '<img' ) || false === strpos( $html, 'wp-image-' ) ) {
    11791215                        return $html;
    11801216                }
    … …  
    12231259                }
    12241260
    1225                 if ( $this->is_inside_picture_element( $full_html, $offset ) ) {
     1261                $attachment_id = absint( $matches[1] );
     1262                $img           = $this->maybe_add_frontend_priority( $img, $attachment_id );
     1263
     1264                if ( $this->is_inside_picture_element( $full_html, $offset ) || ! $this->settings()['serve_picture'] ) {
    12261265                        return $img;
    12271266                }
    12281267
    1229                 $attachment_id = absint( $matches[1] );
    12301268                $attr          = array();
    12311269                $sizes         = $this->extract_image_attribute( $img, 'sizes' );
    … …  
    12441282
    12451283                return $this->picture_markup_for_image_html( $img, $attachment_id, 'full', $attr );
     1284        }
     1285
     1286        private function maybe_add_frontend_priority( string $img, int $attachment_id ): string {
     1287                if ( preg_match( '/\sfetchpriority\s*=\s*([\'\"])high\1/i', $img ) ) {
     1288                        $this->priority_applied = true;
     1289
     1290                        return $img;
     1291                }
     1292
     1293                if ( $this->priority_applied || '1' !== get_post_meta( $attachment_id, self::META_PRIORITY, true ) ) {
     1294                        return $img;
     1295                }
     1296
     1297                $img = preg_replace( '/\s+(?:fetchpriority|loading)\s*=\s*(?:"[^"]*"|\'[^\']*\'|[^\s>]+)/i', '', $img );
     1298
     1299                if ( ! is_string( $img ) ) {
     1300                        return '';
     1301                }
     1302
     1303                $img = preg_replace( '/<img\b/i', '<img fetchpriority="high" loading="eager"', $img, 1 );
     1304
     1305                if ( is_string( $img ) ) {
     1306                        $this->priority_applied = true;
     1307                        return $img;
     1308                }
     1309
     1310                return '';
    12461311        }
    12471312
  • lightweight-modern-media/tags/1.1.15/readme.txt

    r3730748 r3735231  
    55Tested up to: 7.1
    66Requires PHP: 7.4
    7 Stable tag: 1.1.14
     7Stable tag: 1.1.15
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    9292
    9393== Changelog ==
     94
     95= 1.1.15 =
     96
     97* Added a per-image Media Library option for applying high frontend fetch priority to a selected hero or LCP image.
     98* Adds `fetchpriority="high"` with `loading="eager"` to only the first selected priority image rendered per page.
     99* Supports standard WordPress images, block content, Elementor markup, and existing picture elements independently of modern-format delivery.
    94100
    95101= 1.1.14 =
  • lightweight-modern-media/tags/1.1.15/tests/dimension-regression.php

    r3730748 r3735231  
    138138        }
    139139
     140        $priority_property = new ReflectionProperty( $plugin, 'priority_applied' );
     141        $priority_property->setAccessible( true );
     142        update_post_meta( $attachment_id, '_rupanta_image_converter_priority', '1' );
     143        $attachment_fields = $plugin->add_media_modal_conversion_status( array(), get_post( $attachment_id ) );
     144
     145        if ( empty( $attachment_fields['rupanta_priority']['html'] ) || false === strpos( $attachment_fields['rupanta_priority']['html'], 'checked=' ) ) {
     146                $failures[] = 'Media Library priority selection was not rendered as checked.';
     147        }
     148
     149        update_option(
     150                'rupanta_image_converter_settings',
     151                array_merge( (array) $original_settings, array( 'serve_picture' => 0 ) )
     152        );
     153        $settings_property->setValue( $plugin, null );
     154        $priority_property->setValue( $plugin, false );
     155        $priority_html = $plugin->add_picture_sources(
     156                '<img class="wp-image-' . $attachment_id . '" src="example.png" loading="lazy">',
     157                $attachment_id,
     158                'full',
     159                false,
     160                array()
     161        );
     162
     163        if ( false === strpos( $priority_html, 'fetchpriority="high"' ) || false === strpos( $priority_html, 'loading="eager"' ) || false !== strpos( $priority_html, 'loading="lazy"' ) ) {
     164                $failures[] = 'Selected priority image did not receive the expected frontend attributes.';
     165        }
     166
     167        if ( false !== strpos( $priority_html, '<picture' ) ) {
     168                $failures[] = 'Priority attributes unexpectedly enabled picture delivery.';
     169        }
     170
     171        $second_priority_html = $plugin->add_picture_sources(
     172                '<img class="wp-image-' . $attachment_id . '" src="second.png">',
     173                $attachment_id,
     174                'full',
     175                false,
     176                array()
     177        );
     178
     179        if ( false !== strpos( $second_priority_html, 'fetchpriority="high"' ) ) {
     180                $failures[] = 'More than one selected image received high priority in the same request.';
     181        }
     182
     183        delete_post_meta( $attachment_id, '_rupanta_image_converter_priority' );
     184        update_option( 'rupanta_image_converter_settings', $original_settings );
     185        $settings_property->setValue( $plugin, null );
     186        $priority_property->setValue( $plugin, false );
     187
    140188        foreach ( array( 'webp', 'avif' ) as $format ) {
    141189                if ( empty( $manifest[ $format ] ) ) {
  • lightweight-modern-media/trunk/lightweight-modern-media.php

    r3730748 r3735231  
    55 * Plugin Name: Rupanta Media Converter
    66 * Description: Generates WebP and AVIF copies for uploaded images and serves modern formats with picture markup.
    7  * Version: 1.1.14
     7 * Version: 1.1.15
    88 * Requires at least: 6.0
    99 * Tested up to: 7.1
    … …  
    2020
    2121define( 'RUPANTA_PLUGIN_FILE', __FILE__ );
    22 define( 'RUPANTA_PLUGIN_VERSION', '1.1.14' );
     22define( 'RUPANTA_PLUGIN_VERSION', '1.1.15' );
    2323
    2424final class RUPANTA_Image_Converter {
    … …  
    2626        private const META = '_rupanta_image_converter_files';
    2727        private const META_VERSION = '_rupanta_image_converter_version';
     28        private const META_PRIORITY = '_rupanta_image_converter_priority';
    2829
    2930        private static $instance = null;
    … …  
    3132        private $settings = null;
    3233        private $last_generation_result = array();
     34        private $priority_applied = false;
    3335
    3436        public static function instance(): self {
    … …  
    4951                add_filter( 'the_content', array( $this, 'rewrite_frontend_image_html' ), 20 );
    5052                add_filter( 'attachment_fields_to_edit', array( $this, 'add_media_modal_conversion_status' ), 20, 2 );
     53                add_filter( 'attachment_fields_to_save', array( $this, 'save_media_priority_setting' ), 20, 2 );
    5154                add_filter( 'plugin_action_links_' . plugin_basename( RUPANTA_PLUGIN_FILE ), array( $this, 'add_plugin_action_links' ) );
    5255                add_action( 'wp_ajax_rupanta_image_converter_status', array( $this, 'ajax_status' ) );
    … …  
    785788                        ),
    786789                );
     790                $form_fields['rupanta_priority'] = array(
     791                        'label' => __( 'Frontend priority', 'lightweight-modern-media' ),
     792                        'input' => 'html',
     793                        'html'  => sprintf(
     794                                '<input type="hidden" name="attachments[%1$d][rupanta_priority]" value="0"><label><input type="checkbox" name="attachments[%1$d][rupanta_priority]" value="1"%2$s> %3$s</label>',
     795                                (int) $attachment->ID,
     796                                checked( '1', get_post_meta( $attachment->ID, self::META_PRIORITY, true ), false ),
     797                                esc_html__( 'Prioritize this image on the front end', 'lightweight-modern-media' )
     798                        ),
     799                        'helps' => __( 'Adds fetchpriority="high" and loading="eager" when this is the first selected priority image rendered on a page. Select only a hero or likely LCP image.', 'lightweight-modern-media' ),
     800                );
    787801
    788802                return $form_fields;
     803        }
     804
     805        public function save_media_priority_setting( array $post, array $attachment ): array {
     806                $attachment_id = isset( $post['ID'] ) ? absint( $post['ID'] ) : 0;
     807
     808                if ( ! $attachment_id || ! current_user_can( 'edit_post', $attachment_id ) || ! array_key_exists( 'rupanta_priority', $attachment ) ) {
     809                        return $post;
     810                }
     811
     812                if ( '1' === sanitize_text_field( wp_unslash( $attachment['rupanta_priority'] ) ) ) {
     813                        update_post_meta( $attachment_id, self::META_PRIORITY, '1' );
     814                } else {
     815                        delete_post_meta( $attachment_id, self::META_PRIORITY );
     816                }
     817
     818                return $post;
    789819        }
    790820
    … …  
    11681198
    11691199        public function add_picture_sources( string $html, int $attachment_id, $size, $icon, array $attr ): string {
    1170                 if ( is_admin() || ! $this->settings()['serve_picture'] || false !== strpos( $html, '<picture' ) ) {
     1200                if ( is_admin() ) {
    11711201                        return $html;
    11721202                }
    11731203
     1204                $html = $this->maybe_add_frontend_priority( $html, $attachment_id );
     1205
     1206                if ( ! $this->settings()['serve_picture'] || false !== strpos( $html, '<picture' ) ) {
     1207                        return $html;
     1208                }
     1209
    11741210                return $this->picture_markup_for_image_html( $html, $attachment_id, $size, $attr );
    11751211        }
    11761212
    11771213        public function rewrite_frontend_image_html( string $html ): string {
    1178                 if ( ! $this->settings()['serve_picture'] || false === stripos( $html, '<img' ) || false === strpos( $html, 'wp-image-' ) ) {
     1214                if ( false === stripos( $html, '<img' ) || false === strpos( $html, 'wp-image-' ) ) {
    11791215                        return $html;
    11801216                }
    … …  
    12231259                }
    12241260
    1225                 if ( $this->is_inside_picture_element( $full_html, $offset ) ) {
     1261                $attachment_id = absint( $matches[1] );
     1262                $img           = $this->maybe_add_frontend_priority( $img, $attachment_id );
     1263
     1264                if ( $this->is_inside_picture_element( $full_html, $offset ) || ! $this->settings()['serve_picture'] ) {
    12261265                        return $img;
    12271266                }
    12281267
    1229                 $attachment_id = absint( $matches[1] );
    12301268                $attr          = array();
    12311269                $sizes         = $this->extract_image_attribute( $img, 'sizes' );
    … …  
    12441282
    12451283                return $this->picture_markup_for_image_html( $img, $attachment_id, 'full', $attr );
     1284        }
     1285
     1286        private function maybe_add_frontend_priority( string $img, int $attachment_id ): string {
     1287                if ( preg_match( '/\sfetchpriority\s*=\s*([\'\"])high\1/i', $img ) ) {
     1288                        $this->priority_applied = true;
     1289
     1290                        return $img;
     1291                }
     1292
     1293                if ( $this->priority_applied || '1' !== get_post_meta( $attachment_id, self::META_PRIORITY, true ) ) {
     1294                        return $img;
     1295                }
     1296
     1297                $img = preg_replace( '/\s+(?:fetchpriority|loading)\s*=\s*(?:"[^"]*"|\'[^\']*\'|[^\s>]+)/i', '', $img );
     1298
     1299                if ( ! is_string( $img ) ) {
     1300                        return '';
     1301                }
     1302
     1303                $img = preg_replace( '/<img\b/i', '<img fetchpriority="high" loading="eager"', $img, 1 );
     1304
     1305                if ( is_string( $img ) ) {
     1306                        $this->priority_applied = true;
     1307                        return $img;
     1308                }
     1309
     1310                return '';
    12461311        }
    12471312
  • lightweight-modern-media/trunk/readme.txt

    r3730748 r3735231  
    55Tested up to: 7.1
    66Requires PHP: 7.4
    7 Stable tag: 1.1.14
     7Stable tag: 1.1.15
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    9292
    9393== Changelog ==
     94
     95= 1.1.15 =
     96
     97* Added a per-image Media Library option for applying high frontend fetch priority to a selected hero or LCP image.
     98* Adds `fetchpriority="high"` with `loading="eager"` to only the first selected priority image rendered per page.
     99* Supports standard WordPress images, block content, Elementor markup, and existing picture elements independently of modern-format delivery.
    94100
    95101= 1.1.14 =
  • lightweight-modern-media/trunk/tests/dimension-regression.php

    r3730748 r3735231  
    138138        }
    139139
     140        $priority_property = new ReflectionProperty( $plugin, 'priority_applied' );
     141        $priority_property->setAccessible( true );
     142        update_post_meta( $attachment_id, '_rupanta_image_converter_priority', '1' );
     143        $attachment_fields = $plugin->add_media_modal_conversion_status( array(), get_post( $attachment_id ) );
     144
     145        if ( empty( $attachment_fields['rupanta_priority']['html'] ) || false === strpos( $attachment_fields['rupanta_priority']['html'], 'checked=' ) ) {
     146                $failures[] = 'Media Library priority selection was not rendered as checked.';
     147        }
     148
     149        update_option(
     150                'rupanta_image_converter_settings',
     151                array_merge( (array) $original_settings, array( 'serve_picture' => 0 ) )
     152        );
     153        $settings_property->setValue( $plugin, null );
     154        $priority_property->setValue( $plugin, false );
     155        $priority_html = $plugin->add_picture_sources(
     156                '<img class="wp-image-' . $attachment_id . '" src="example.png" loading="lazy">',
     157                $attachment_id,
     158                'full',
     159                false,
     160                array()
     161        );
     162
     163        if ( false === strpos( $priority_html, 'fetchpriority="high"' ) || false === strpos( $priority_html, 'loading="eager"' ) || false !== strpos( $priority_html, 'loading="lazy"' ) ) {
     164                $failures[] = 'Selected priority image did not receive the expected frontend attributes.';
     165        }
     166
     167        if ( false !== strpos( $priority_html, '<picture' ) ) {
     168                $failures[] = 'Priority attributes unexpectedly enabled picture delivery.';
     169        }
     170
     171        $second_priority_html = $plugin->add_picture_sources(
     172                '<img class="wp-image-' . $attachment_id . '" src="second.png">',
     173                $attachment_id,
     174                'full',
     175                false,
     176                array()
     177        );
     178
     179        if ( false !== strpos( $second_priority_html, 'fetchpriority="high"' ) ) {
     180                $failures[] = 'More than one selected image received high priority in the same request.';
     181        }
     182
     183        delete_post_meta( $attachment_id, '_rupanta_image_converter_priority' );
     184        update_option( 'rupanta_image_converter_settings', $original_settings );
     185        $settings_property->setValue( $plugin, null );
     186        $priority_property->setValue( $plugin, false );
     187
    140188        foreach ( array( 'webp', 'avif' ) as $format ) {
    141189                if ( empty( $manifest[ $format ] ) ) {
Note: See TracChangeset for help on using the changeset viewer.