Autoptimize - Version 2.8.2

Version Description

  • Images: only show "did you know shortpixel" notice on Autoptimize settings pages (no more littering all over the backend)
  • Images: update lazysizes from upstream
  • Images: misc. improvements such as fix for PHP "undefined index" notice, updated copy, ...
  • HTML: rename HTML minify class from minify_HTML to AO_minify_HTML to avoid conflicts with e.g. W3TC
  • Critical CSS: misc. improvements such as detect is_front_page before any other conditional, fix for conditional rules without an actual condition, improved debug logging, ...
  • JS/ CSS: fix for AO not optimizing multisite child sites when CDN set
Download this release

Release Info

Developer futtta
Plugin Icon 128x128 Autoptimize
Version 2.8.2
Comparing to
See all releases

Code changes from version 2.8.1 to 2.8.2

autoptimize.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Autoptimize
4
  * Plugin URI: https://autoptimize.com/
5
  * Description: Makes your site faster by optimizing CSS, JS, Images, Google fonts and more.
6
- * Version: 2.8.1
7
  * Author: Frank Goossens (futtta)
8
  * Author URI: https://autoptimize.com/
9
  * Text Domain: autoptimize
@@ -21,7 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) {
21
  exit;
22
  }
23
 
24
- define( 'AUTOPTIMIZE_PLUGIN_VERSION', '2.8.1' );
25
 
26
  // plugin_dir_path() returns the trailing slash!
27
  define( 'AUTOPTIMIZE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
@@ -44,7 +44,7 @@ if ( version_compare( PHP_VERSION, '5.6', '<' ) ) {
44
  }
45
 
46
  function autoptimize_autoload( $class_name ) {
47
- if ( in_array( $class_name, array( 'Minify_HTML', 'JSMin' ) ) ) {
48
  $file = strtolower( $class_name );
49
  $file = str_replace( '_', '-', $file );
50
  $path = dirname( __FILE__ ) . '/classes/external/php/';
3
  * Plugin Name: Autoptimize
4
  * Plugin URI: https://autoptimize.com/
5
  * Description: Makes your site faster by optimizing CSS, JS, Images, Google fonts and more.
6
+ * Version: 2.8.2
7
  * Author: Frank Goossens (futtta)
8
  * Author URI: https://autoptimize.com/
9
  * Text Domain: autoptimize
21
  exit;
22
  }
23
 
24
+ define( 'AUTOPTIMIZE_PLUGIN_VERSION', '2.8.2' );
25
 
26
  // plugin_dir_path() returns the trailing slash!
27
  define( 'AUTOPTIMIZE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
44
  }
45
 
46
  function autoptimize_autoload( $class_name ) {
47
+ if ( in_array( $class_name, array( 'AO_Minify_HTML', 'JSMin' ) ) ) {
48
  $file = strtolower( $class_name );
49
  $file = str_replace( '_', '-', $file );
50
  $path = dirname( __FILE__ ) . '/classes/external/php/';
classes/autoptimizeBase.php CHANGED
@@ -144,6 +144,14 @@ abstract class autoptimizeBase
144
  // As we replaced the content-domain with the site-domain, we should match against that.
145
  $tmp_ao_root = preg_replace( '/https?:/', '', AUTOPTIMIZE_WP_SITE_URL );
146
  }
 
 
 
 
 
 
 
 
147
 
148
  $tmp_url = preg_replace( '/https?:/', '', $url );
149
  $path = str_replace( $tmp_ao_root, '', $tmp_url );
@@ -156,7 +164,7 @@ abstract class autoptimizeBase
156
  }
157
 
158
  // Prepend with WP_ROOT_DIR to have full path to file.
159
- $path = str_replace( '//', '/', WP_ROOT_DIR . $path );
160
 
161
  // Final check: does file exist and is it readable?
162
  if ( file_exists( $path ) && is_file( $path ) && is_readable( $path ) ) {
144
  // As we replaced the content-domain with the site-domain, we should match against that.
145
  $tmp_ao_root = preg_replace( '/https?:/', '', AUTOPTIMIZE_WP_SITE_URL );
146
  }
147
+
148
+ if ( is_multisite() && ! is_main_site() && ! empty( $this->cdn_url ) ) {
149
+ // multisite child sites with CDN need the network_site_url as tmp_ao_root but only if directory-based multisite.
150
+ $_network_site_url = network_site_url();
151
+ if ( strpos( AUTOPTIMIZE_WP_SITE_URL, $_network_site_url ) !== false ) {
152
+ $tmp_ao_root = preg_replace( '/https?:/', '', $_network_site_url );
153
+ }
154
+ }
155
 
156
  $tmp_url = preg_replace( '/https?:/', '', $url );
157
  $path = str_replace( $tmp_ao_root, '', $tmp_url );
164
  }
165
 
166
  // Prepend with WP_ROOT_DIR to have full path to file.
167
+ $path = str_replace( '//', '/', trailingslashit( WP_ROOT_DIR ) . $path );
168
 
169
  // Final check: does file exist and is it readable?
170
  if ( file_exists( $path ) && is_file( $path ) && is_readable( $path ) ) {
classes/autoptimizeCache.php CHANGED
@@ -827,6 +827,9 @@ class autoptimizeCache
827
  prune_super_cache( $cache_path . 'supercache/', true );
828
  prune_super_cache( $cache_path, true );
829
  }
 
 
 
830
  }
831
  }
832
  // @codingStandardsIgnoreEnd
827
  prune_super_cache( $cache_path . 'supercache/', true );
828
  prune_super_cache( $cache_path, true );
829
  }
830
+ } elseif ( class_exists( 'NginxCache' ) ) {
831
+ $nginx_cache = new NginxCache();
832
+ $nginx_cache->purge_zone_once();
833
  }
834
  }
835
  // @codingStandardsIgnoreEnd
classes/autoptimizeCriticalCSSCron.php CHANGED
@@ -227,8 +227,8 @@ class autoptimizeCriticalCSSCron {
227
  $apireq['resultStatus'] = 'GOOD';
228
  }
229
 
230
- if ( 'GOOD' == $apireq['resultStatus'] && 'GOOD' == $apireq['validationStatus'] ) {
231
- // SUCCESS: GOOD job with GOOD validation
232
  // Update job properties.
233
  $jprops['file'] = $this->ao_ccss_save_file( $apireq['css'], $trule, false );
234
  $jprops['jqstat'] = $apireq['status'];
@@ -237,8 +237,8 @@ class autoptimizeCriticalCSSCron {
237
  $jprops['jftime'] = microtime( true );
238
  $rule_update = true;
239
  autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '>, file saved <' . $jprops['file'] . '>', 3 );
240
- } elseif ( 'GOOD' == $apireq['resultStatus'] && ( 'WARN' == $apireq['validationStatus'] || 'BAD' == $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' == $apireq['validationStatus'] ) ) {
241
- // SUCCESS: GOOD job with WARN or BAD validation
242
  // Update job properties.
243
  $jprops['jqstat'] = $apireq['status'];
244
  $jprops['jrstat'] = $apireq['resultStatus'];
@@ -249,7 +249,7 @@ class autoptimizeCriticalCSSCron {
249
  $rule_update = true;
250
  autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file saved <' . $jprops['file'] . '> but requires REVIEW', 3 );
251
  } else {
252
- autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file saved <' . $jprops['file'] . '> but required REVIEW so not saved.', 3 );
253
  }
254
  } elseif ( 'GOOD' != $apireq['resultStatus'] && ( 'GOOD' != $apireq['validationStatus'] || 'WARN' != $apireq['validationStatus'] || 'BAD' != $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' != $apireq['validationStatus'] ) ) {
255
  // ERROR: no GOOD, WARN or BAD results
@@ -722,7 +722,7 @@ class autoptimizeCriticalCSSCron {
722
  } else {
723
  // If rule doesn't exist, create an AUTO rule
724
  // AUTO rules were only for types, but will now also work for paths.
725
- if ( 'types' == $trule[0] || 'paths' == $trule[0] ) {
726
  // Set rule hash and file and action flag.
727
  $rule['hash'] = $hash;
728
  $rule['file'] = $file;
227
  $apireq['resultStatus'] = 'GOOD';
228
  }
229
 
230
+ if ( 'GOOD' == $apireq['resultStatus'] && ( 'GOOD' == $apireq['validationStatus'] || 'WARN' == $apireq['validationStatus'] ) ) {
231
+ // SUCCESS: GOOD job with GOOD or WARN validation
232
  // Update job properties.
233
  $jprops['file'] = $this->ao_ccss_save_file( $apireq['css'], $trule, false );
234
  $jprops['jqstat'] = $apireq['status'];
237
  $jprops['jftime'] = microtime( true );
238
  $rule_update = true;
239
  autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '>, file saved <' . $jprops['file'] . '>', 3 );
240
+ } elseif ( 'GOOD' == $apireq['resultStatus'] && ( 'BAD' == $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' == $apireq['validationStatus'] ) ) {
241
+ // SUCCESS: GOOD job with BAD or SCREENSHOT_WARN_BLANK validation
242
  // Update job properties.
243
  $jprops['jqstat'] = $apireq['status'];
244
  $jprops['jrstat'] = $apireq['resultStatus'];
249
  $rule_update = true;
250
  autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file saved <' . $jprops['file'] . '> but requires REVIEW', 3 );
251
  } else {
252
+ autoptimizeCriticalCSSCore::ao_ccss_log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file not saved because it required REVIEW.', 3 );
253
  }
254
  } elseif ( 'GOOD' != $apireq['resultStatus'] && ( 'GOOD' != $apireq['validationStatus'] || 'WARN' != $apireq['validationStatus'] || 'BAD' != $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' != $apireq['validationStatus'] ) ) {
255
  // ERROR: no GOOD, WARN or BAD results
722
  } else {
723
  // If rule doesn't exist, create an AUTO rule
724
  // AUTO rules were only for types, but will now also work for paths.
725
+ if ( ( 'types' == $trule[0] || 'paths' == $trule[0] ) && ! empty( $trule[1] ) ) {
726
  // Set rule hash and file and action flag.
727
  $rule['hash'] = $hash;
728
  $rule['file'] = $file;
classes/autoptimizeCriticalCSSEnqueue.php CHANGED
@@ -41,7 +41,21 @@ class autoptimizeCriticalCSSEnqueue {
41
  global $ao_ccss_forcepath;
42
 
43
  // Get request path and page type, and initialize the queue update flag.
44
- $req_path = strtok( $_SERVER['REQUEST_URI'], '?' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  $req_type = $self->ao_ccss_get_type();
46
  $job_qualify = false;
47
  $target_rule = false;
@@ -199,6 +213,10 @@ class autoptimizeCriticalCSSEnqueue {
199
  if ( is_404() ) {
200
  $page_type = 'is_404';
201
  break;
 
 
 
 
202
  } elseif ( strpos( $type, 'custom_post_' ) !== false && ( ! $ao_ccss_forcepath || ! is_page() ) ) {
203
  // Match custom post types and not page or page not forced to path-based.
204
  if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) {
41
  global $ao_ccss_forcepath;
42
 
43
  // Get request path and page type, and initialize the queue update flag.
44
+ $req_orig = $_SERVER['REQUEST_URI'];
45
+ $req_path = strtok( $req_orig, '?' );
46
+
47
+ // Check if we have a lang param. we need to keep as WPML can switch languages based on that
48
+ // and that includes RTL -> LTR so diff. structure, so rules would be RTL vs LTR
49
+ // but this needs changes in the structur of the rule object so off by default for now
50
+ // as now this will simply result in conditional rules being overwritten.
51
+ if ( apply_filters( 'autoptimize_filter_ccss_coreenqueue_honor_lang', false ) && strpos( $req_orig, 'lang=' ) !== false ) {
52
+ $req_params = strtok( '?' );
53
+ parse_str( $req_params, $req_params_arr );
54
+ if ( array_key_exists( 'lang', $req_params_arr ) && !empty( $req_params_arr['lang'] ) ) {
55
+ $req_path .= '?lang=' . $req_params_arr['lang'];
56
+ }
57
+ }
58
+
59
  $req_type = $self->ao_ccss_get_type();
60
  $job_qualify = false;
61
  $target_rule = false;
213
  if ( is_404() ) {
214
  $page_type = 'is_404';
215
  break;
216
+ } elseif ( is_front_page() ) {
217
+ // identify frontpage immediately to avoid it also matching a CPT or template.
218
+ $page_type = 'is_front_page';
219
+ break;
220
  } elseif ( strpos( $type, 'custom_post_' ) !== false && ( ! $ao_ccss_forcepath || ! is_page() ) ) {
221
  // Match custom post types and not page or page not forced to path-based.
222
  if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) {
classes/autoptimizeHTML.php CHANGED
@@ -82,7 +82,7 @@ class autoptimizeHTML extends autoptimizeBase
82
  $options['xhtml'] = true;
83
  }
84
 
85
- $tmp_content = Minify_HTML::minify( $this->content, $options );
86
  if ( ! empty( $tmp_content ) ) {
87
  $this->content = $tmp_content;
88
  unset( $tmp_content );
82
  $options['xhtml'] = true;
83
  }
84
 
85
+ $tmp_content = AO_Minify_HTML::minify( $this->content, $options );
86
  if ( ! empty( $tmp_content ) ) {
87
  $this->content = $tmp_content;
88
  unset( $tmp_content );
classes/autoptimizeImages.php CHANGED
@@ -231,7 +231,7 @@ class autoptimizeImages
231
 
232
  public static function get_service_url_suffix()
233
  {
234
- $suffix = '/af/GWRGFLW109483/' . AUTOPTIMIZE_SITE_DOMAIN;
235
 
236
  return $suffix;
237
  }
@@ -346,9 +346,7 @@ class autoptimizeImages
346
  $result = trim( $in );
347
 
348
  // Some silly plugins wrap background images in html-encoded quotes, so remove those from the img url.
349
- if ( strpos( $result, '&quot;' ) !== false ) {
350
- $result = str_replace( '&quot;', '', $result );
351
- }
352
 
353
  if ( autoptimizeUtils::is_protocol_relative( $result ) ) {
354
  $result = $parsed_site_url['scheme'] . ':' . $result;
@@ -466,7 +464,13 @@ class autoptimizeImages
466
  return $filtered_url;
467
  }
468
 
469
- $orig_url = $this->normalize_img_url( $orig_url );
 
 
 
 
 
 
470
  $imgopt_base_url = $this->get_imgopt_base_url();
471
  $imgopt_size = '';
472
 
@@ -478,7 +482,7 @@ class autoptimizeImages
478
  $imgopt_size .= ',h_' . $height;
479
  }
480
 
481
- $url = $imgopt_base_url . $imgopt_size . '/' . $orig_url;
482
 
483
  return $url;
484
  }
@@ -539,6 +543,8 @@ class autoptimizeImages
539
  // extract img tags.
540
  if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $in, $matches ) ) {
541
  foreach ( $matches[0] as $tag ) {
 
 
542
  $orig_tag = $tag;
543
  $imgopt_w = '';
544
  $imgopt_h = '';
@@ -574,7 +580,7 @@ class autoptimizeImages
574
  foreach ( $urls as $url ) {
575
  $full_src_orig = $url[0];
576
  $url = $url[1];
577
- if ( $this->can_optimize_image( $url, $full_src_orig, $testing ) ) {
578
  $imgopt_url = $this->build_imgopt_url( $url, $imgopt_w, $imgopt_h );
579
  $full_imgopt_src = str_replace( $url, $imgopt_url, $full_src_orig );
580
  $tag = str_replace( $full_src_orig, $full_imgopt_src, $tag );
@@ -611,6 +617,8 @@ class autoptimizeImages
611
  $tag = $this->add_lazyload( $tag, $placeholder );
612
  }
613
 
 
 
614
  // and add tag to array for later replacement.
615
  if ( $tag !== $orig_tag ) {
616
  $to_replace[ $orig_tag ] = $tag;
@@ -770,7 +778,13 @@ class autoptimizeImages
770
  public function add_lazyload( $tag, $placeholder = '' ) {
771
  // adds actual lazyload-attributes to an image node.
772
  $this->lazyload_counter++;
773
- $_lazyload_from_nth = apply_filters( 'autoptimize_filter_imgopt_lazyload_from_nth', $this->options['autoptimize_imgopt_number_field_7'] );
 
 
 
 
 
 
774
  if ( str_ireplace( $this->get_lazyload_exclusions(), '', $tag ) === $tag && $this->lazyload_counter >= $_lazyload_from_nth ) {
775
  $tag = $this->maybe_fix_missing_quotes( $tag );
776
 
@@ -965,7 +979,7 @@ class autoptimizeImages
965
  public function process_bgimage( $in ) {
966
  if ( strpos( $in, 'background-image:' ) !== false && apply_filters( 'autoptimize_filter_imgopt_lazyload_backgroundimages', true ) ) {
967
  $out = preg_replace_callback(
968
- '/(<(?:article|aside|body|div|footer|header|p|section|table)[^>]*)\sstyle=(?:"|\')[^<>]*?background-image:\s?url\((?:"|\')?([^"\')]*)(?:"|\')?\)[^>]*/',
969
  array( $this, 'lazyload_bgimg_callback' ),
970
  $in
971
  );
@@ -980,15 +994,22 @@ class autoptimizeImages
980
  $placeholder = apply_filters( 'autoptimize_filter_imgopt_lazyload_placeholder', $this->get_default_lazyload_placeholder( 500, 300 ) );
981
  $lazyload_class = apply_filters( 'autoptimize_filter_imgopt_lazyload_class', 'lazyload' );
982
  // replace background-image URL with SVG placeholder.
983
- $out = str_replace( $matches[2], $placeholder, $matches[0] );
 
 
984
  // add data-bg attribute with real background-image URL for lazyload to pick up.
985
- $out = str_replace( $matches[1], $matches[1] . ' data-bg="' . trim( str_replace( array( "\r\n", '&quot;' ), '', $matches[2] ) ) . '"', $out );
986
- // add lazyload class to tag.
987
  $out = $this->inject_classes_in_tag( $out, "$lazyload_class " );
988
  return $out;
989
  }
990
  return $matches[0];
991
  }
 
 
 
 
 
992
 
993
  public function maybe_fix_missing_quotes( $tag_in ) {
994
  // W3TC's Minify_HTML class removes quotes around attribute value, this re-adds them for the class and width/height attributes so we can lazyload properly.
@@ -1033,7 +1054,7 @@ class autoptimizeImages
1033
  {
1034
  // Check querystring for "refreshCacheChecker" and call cachechecker if so.
1035
  if ( array_key_exists( 'refreshImgProvStats', $_GET ) && 1 == $_GET['refreshImgProvStats'] ) {
1036
- $this->query_img_provider_stats();
1037
  }
1038
 
1039
  $options = $this->fetch_options();
@@ -1102,18 +1123,18 @@ class autoptimizeImages
1102
  echo apply_filters( 'autoptimize_filter_imgopt_settings_status', '<p><strong><span style="color:' . $_notice_color . ';">' . __( 'Shortpixel status: ', 'autoptimize' ) . '</span></strong>' . $_notice['notice'] . '</p>' );
1103
  } else {
1104
  // translators: link points to shortpixel.
1105
- $upsell_msg_1 = '<p>' . sprintf( __( 'Get more Google love and improve your website\'s loading speed by having your publicly available images optimized on the fly (also in the "next-gen" WebP and AVIF image format) by %1$sShortPixel%2$s and then cached and served fast from Shortpixel\'s global CDN.', 'autoptimize' ), '<a href="https://shortpixel.com/aospai' . $sp_url_suffix . '" target="_blank">', '</a>' );
1106
  if ( 'launch' === $options['availabilities']['extra_imgopt']['status'] ) {
1107
  $upsell_msg_2 = __( 'For a limited time only, this service is offered free for all Autoptimize users, <b>don\'t miss the chance to test it</b> and see how much it could improve your site\'s speed.', 'autoptimize' );
1108
  } else {
1109
  // translators: link points to shortpixel.
1110
- $upsell_msg_2 = sprintf( __( '%1$sSign-up now%2$s to receive extra traffic or image optimization credits for free. You\'ll also receive +50&percnt; more CDN traffic or image optimization credits regardless for any future plan that you\'ll choose to purchase.', 'autoptimize' ), '<a href="https://shortpixel.com/aospai' . $sp_url_suffix . '" target="_blank">', '</a>' );
1111
  }
1112
  echo apply_filters( 'autoptimize_imgopt_imgopt_settings_copy', $upsell_msg_1 . ' ' . $upsell_msg_2 . '</p>' );
1113
  }
1114
  // translators: link points to shortpixel FAQ.
1115
- $faqcopy = sprintf( __( '<strong>Questions</strong>? Have a look at the %1$sShortPixel FAQ%2$s!', 'autoptimize' ), '<strong><a href="https://help.shortpixel.com/category/405-autoptimize" target="_blank">', '</strong></a>' );
1116
- $faqcopy = $faqcopy . ' ' . __( 'Only works for sites/ images that are publicly available.', 'autoptimize' );
1117
  // translators: links points to shortpixel TOS & Privacy Policy.
1118
  $toscopy = sprintf( __( 'Usage of this feature is subject to Shortpixel\'s %1$sTerms of Use%2$s and %3$sPrivacy policy%4$s.', 'autoptimize' ), '<a href="https://shortpixel.com/tos' . $sp_url_suffix . '" target="_blank">', '</a>', '<a href="https://shortpixel.com/pp' . $sp_url_suffix . '" target="_blank">', '</a>' );
1119
  echo apply_filters( 'autoptimize_imgopt_imgopt_settings_tos', '<p>' . $faqcopy . ' ' . $toscopy . '</p>' );
@@ -1221,7 +1242,7 @@ class autoptimizeImages
1221
  $_imgopt_notice = '';
1222
  $_stat = autoptimizeOptionWrapper::get_option( 'autoptimize_imgopt_provider_stat', '' );
1223
  $_site_host = AUTOPTIMIZE_SITE_DOMAIN;
1224
- $_imgopt_upsell = 'https://shortpixel.com/aospai/af/GWRGFLW109483/' . $_site_host;
1225
  $_imgopt_assoc = 'https://shortpixel.helpscoutdocs.com/article/94-how-to-associate-a-domain-to-my-account';
1226
  $_imgopt_unreach = 'https://shortpixel.helpscoutdocs.com/article/148-why-are-my-images-redirected-from-cdn-shortpixel-ai';
1227
 
@@ -1233,12 +1254,12 @@ class autoptimizeImages
1233
  // translators: "add more credits" will appear in a "a href".
1234
  $_imgopt_notice = sprintf( __( 'Your ShortPixel image optimization and CDN quota was used, %1$sadd more credits%2$s to keep fast serving optimized images on your site', 'autoptimize' ), '<a href="' . $_imgopt_upsell . '" target="_blank">', '</a>' );
1235
  // translators: "associate your domain" will appear in a "a href".
1236
- $_imgopt_notice = $_imgopt_notice . ' ' . sprintf( __( 'If you have enough credits/ CDN quota remaining, then you may need to %1$sassociate your domain%2$s to your Shortpixel account.', 'autoptimize' ), '<a rel="noopener noreferrer" href="' . $_imgopt_assoc . '" target="_blank">', '</a>' );
1237
  } elseif ( -3 == $_stat['Status'] ) {
1238
  // translators: "check the documentation here" will appear in a "a href".
1239
  $_imgopt_notice = sprintf( __( 'It seems ShortPixel image optimization is not able to fetch images from your site, %1$scheck the documentation here%2$s for more information', 'autoptimize' ), '<a href="' . $_imgopt_unreach . '" target="_blank">', '</a>' );
1240
  } else {
1241
- $_imgopt_upsell = 'https://shortpixel.com/g/af/GWRGFLW109483';
1242
  // translators: "log in to check your account" will appear in a "a href".
1243
  $_imgopt_notice = sprintf( __( 'Your ShortPixel image optimization and CDN quota are in good shape, %1$slog in to check your account%2$s.', 'autoptimize' ), '<a href="' . $_imgopt_upsell . '" target="_blank">', '</a>' );
1244
  }
@@ -1256,7 +1277,7 @@ class autoptimizeImages
1256
  }
1257
  $_imgopt_notice .= ' (' . $_imgopt_stats_last_run . ', ';
1258
  // translators: "here to refresh" links to the Autoptimize Extra page and forces a refresh of the img opt stats.
1259
- $_imgopt_notice .= sprintf( __( 'click %1$shere to refresh%2$s', 'autoptimize' ), '<a href="' . $_imgopt_stats_refresh_url . '">', '</a>).' );
1260
  }
1261
 
1262
  // and make the full notice filterable.
@@ -1280,15 +1301,19 @@ class autoptimizeImages
1280
  /**
1281
  * Get img provider stats (used to display notice).
1282
  */
1283
- public function query_img_provider_stats() {
1284
  if ( ! empty( $this->options['autoptimize_imgopt_checkbox_field_1'] ) ) {
1285
  $url = '';
1286
- $endpoint = $this->get_imgopt_host() . 'read-domain/';
 
1287
  $domain = AUTOPTIMIZE_SITE_DOMAIN;
1288
 
1289
  // make sure parse_url result makes sense, keeping $url empty if not.
1290
  if ( $domain && ! empty( $domain ) ) {
1291
  $url = $endpoint . $domain;
 
 
 
1292
  }
1293
 
1294
  $url = apply_filters(
231
 
232
  public static function get_service_url_suffix()
233
  {
234
+ $suffix = '/af/SPZURYE109483/' . AUTOPTIMIZE_SITE_DOMAIN;
235
 
236
  return $suffix;
237
  }
346
  $result = trim( $in );
347
 
348
  // Some silly plugins wrap background images in html-encoded quotes, so remove those from the img url.
349
+ $result = $this->fix_silly_bgimg_quotes( $result );
 
 
350
 
351
  if ( autoptimizeUtils::is_protocol_relative( $result ) ) {
352
  $result = $parsed_site_url['scheme'] . ':' . $result;
464
  return $filtered_url;
465
  }
466
 
467
+ $normalized_url = $this->normalize_img_url( $orig_url );
468
+
469
+ // if the URL is ascii we check if we have a real URL with filter_var (which only works on ascii url's) and if not a real URL we return the original one.
470
+ if ( apply_filters( 'autoptimize_filter_imgopt_check_normalized_url', true ) && ! preg_match( '/[^\x20-\x7e]/', $normalized_url ) && false === filter_var( $normalized_url, FILTER_VALIDATE_URL ) ) {
471
+ return $orig_url;
472
+ }
473
+
474
  $imgopt_base_url = $this->get_imgopt_base_url();
475
  $imgopt_size = '';
476
 
482
  $imgopt_size .= ',h_' . $height;
483
  }
484
 
485
+ $url = $imgopt_base_url . $imgopt_size . '/' . $normalized_url;
486
 
487
  return $url;
488
  }
543
  // extract img tags.
544
  if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $in, $matches ) ) {
545
  foreach ( $matches[0] as $tag ) {
546
+ $tag = apply_filters( 'autoptimize_filter_imgopt_tag_preopt' , $tag );
547
+
548
  $orig_tag = $tag;
549
  $imgopt_w = '';
550
  $imgopt_h = '';
580
  foreach ( $urls as $url ) {
581
  $full_src_orig = $url[0];
582
  $url = $url[1];
583
+ if ( $this->can_optimize_image( $url, $tag, $testing ) ) {
584
  $imgopt_url = $this->build_imgopt_url( $url, $imgopt_w, $imgopt_h );
585
  $full_imgopt_src = str_replace( $url, $imgopt_url, $full_src_orig );
586
  $tag = str_replace( $full_src_orig, $full_imgopt_src, $tag );
617
  $tag = $this->add_lazyload( $tag, $placeholder );
618
  }
619
 
620
+ $tag = apply_filters( 'autoptimize_filter_imgopt_tag_postopt' , $tag );
621
+
622
  // and add tag to array for later replacement.
623
  if ( $tag !== $orig_tag ) {
624
  $to_replace[ $orig_tag ] = $tag;
778
  public function add_lazyload( $tag, $placeholder = '' ) {
779
  // adds actual lazyload-attributes to an image node.
780
  $this->lazyload_counter++;
781
+
782
+ $_lazyload_from_nth = '';
783
+ if ( array_key_exists( 'autoptimize_imgopt_number_field_7', $this->options ) ) {
784
+ $_lazyload_from_nth = $this->options['autoptimize_imgopt_number_field_7'];
785
+ }
786
+ $_lazyload_from_nth = apply_filters( 'autoptimize_filter_imgopt_lazyload_from_nth', $_lazyload_from_nth );
787
+
788
  if ( str_ireplace( $this->get_lazyload_exclusions(), '', $tag ) === $tag && $this->lazyload_counter >= $_lazyload_from_nth ) {
789
  $tag = $this->maybe_fix_missing_quotes( $tag );
790
 
979
  public function process_bgimage( $in ) {
980
  if ( strpos( $in, 'background-image:' ) !== false && apply_filters( 'autoptimize_filter_imgopt_lazyload_backgroundimages', true ) ) {
981
  $out = preg_replace_callback(
982
+ '/(<(?:article|aside|body|div|footer|header|p|section|span|table)[^>]*)\sstyle=(?:"|\')[^<>]*?background-image:\s?url\((?:"|\')?([^"\')]*)(?:"|\')?\)[^>]*/',
983
  array( $this, 'lazyload_bgimg_callback' ),
984
  $in
985
  );
994
  $placeholder = apply_filters( 'autoptimize_filter_imgopt_lazyload_placeholder', $this->get_default_lazyload_placeholder( 500, 300 ) );
995
  $lazyload_class = apply_filters( 'autoptimize_filter_imgopt_lazyload_class', 'lazyload' );
996
  // replace background-image URL with SVG placeholder.
997
+ $out = str_replace( 'url(' . $matches[2], 'url(' . $placeholder, $matches[0] );
998
+ // sanitize bgimg src for quote sillyness.
999
+ $bgimg_src = $this->fix_silly_bgimg_quotes( $matches[2] );
1000
  // add data-bg attribute with real background-image URL for lazyload to pick up.
1001
+ $out = str_replace( $matches[1], $matches[1] . ' data-bg="' . $bgimg_src . '"', $out );
1002
+ // and finally add lazyload class to tag.
1003
  $out = $this->inject_classes_in_tag( $out, "$lazyload_class " );
1004
  return $out;
1005
  }
1006
  return $matches[0];
1007
  }
1008
+
1009
+ public function fix_silly_bgimg_quotes( $tag_in ) {
1010
+ // some themes/ pagebuilders wrap backgroundimages in HTML-encoded quotes (or linebreaks) which breaks imgopt/ lazyloading, this removes them.
1011
+ return trim( str_replace( array( "\r\n", '&quot;', '&#034;', '&apos;', '&#039;' ), '', $tag_in ) );
1012
+ }
1013
 
1014
  public function maybe_fix_missing_quotes( $tag_in ) {
1015
  // W3TC's Minify_HTML class removes quotes around attribute value, this re-adds them for the class and width/height attributes so we can lazyload properly.
1054
  {
1055
  // Check querystring for "refreshCacheChecker" and call cachechecker if so.
1056
  if ( array_key_exists( 'refreshImgProvStats', $_GET ) && 1 == $_GET['refreshImgProvStats'] ) {
1057
+ $this->query_img_provider_stats( true );
1058
  }
1059
 
1060
  $options = $this->fetch_options();
1123
  echo apply_filters( 'autoptimize_filter_imgopt_settings_status', '<p><strong><span style="color:' . $_notice_color . ';">' . __( 'Shortpixel status: ', 'autoptimize' ) . '</span></strong>' . $_notice['notice'] . '</p>' );
1124
  } else {
1125
  // translators: link points to shortpixel.
1126
+ $upsell_msg_1 = '<p>' . sprintf( __( 'Get more Google love by speeding up your website. Start serving on-the-fly optimized images (also in the "next-gen" <strong>WebP</strong> and <strong>AVIF</strong> image formats) by %1$sShortPixel%2$s. The optimized images are cached and served from %3$sShortPixel\'s global CDN%2$s.', 'autoptimize' ), '<a href="https://shortpixel.com/aospai' . $sp_url_suffix . '" target="_blank">', '</a>', '<a href="https://help.shortpixel.com/article/62-where-does-the-cdn-has-pops" target="_blank">' );
1127
  if ( 'launch' === $options['availabilities']['extra_imgopt']['status'] ) {
1128
  $upsell_msg_2 = __( 'For a limited time only, this service is offered free for all Autoptimize users, <b>don\'t miss the chance to test it</b> and see how much it could improve your site\'s speed.', 'autoptimize' );
1129
  } else {
1130
  // translators: link points to shortpixel.
1131
+ $upsell_msg_2 = sprintf( __( '%1$sSign-up now%2$s to receive x2 more CDN traffic or image optimization credits for free! This offer also applies to any future plan that you\'ll choose to purchase.', 'autoptimize' ), '<a href="https://shortpixel.com/aospai' . $sp_url_suffix . '" target="_blank">', '</a>' );
1132
  }
1133
  echo apply_filters( 'autoptimize_imgopt_imgopt_settings_copy', $upsell_msg_1 . ' ' . $upsell_msg_2 . '</p>' );
1134
  }
1135
  // translators: link points to shortpixel FAQ.
1136
+ $faqcopy = sprintf( __( '<strong>Questions</strong>? Have a look at the %1$sAutoptimize + ShortPixel FAQ%2$s!', 'autoptimize' ), '<strong><a href="https://help.shortpixel.com/category/405-autoptimize" target="_blank">', '</strong></a>' );
1137
+ $faqcopy = $faqcopy . ' ' . __( 'Only works for websites and images that are publicly available.', 'autoptimize' );
1138
  // translators: links points to shortpixel TOS & Privacy Policy.
1139
  $toscopy = sprintf( __( 'Usage of this feature is subject to Shortpixel\'s %1$sTerms of Use%2$s and %3$sPrivacy policy%4$s.', 'autoptimize' ), '<a href="https://shortpixel.com/tos' . $sp_url_suffix . '" target="_blank">', '</a>', '<a href="https://shortpixel.com/pp' . $sp_url_suffix . '" target="_blank">', '</a>' );
1140
  echo apply_filters( 'autoptimize_imgopt_imgopt_settings_tos', '<p>' . $faqcopy . ' ' . $toscopy . '</p>' );
1242
  $_imgopt_notice = '';
1243
  $_stat = autoptimizeOptionWrapper::get_option( 'autoptimize_imgopt_provider_stat', '' );
1244
  $_site_host = AUTOPTIMIZE_SITE_DOMAIN;
1245
+ $_imgopt_upsell = 'https://shortpixel.com/aospai/af/SPZURYE109483/' . $_site_host;
1246
  $_imgopt_assoc = 'https://shortpixel.helpscoutdocs.com/article/94-how-to-associate-a-domain-to-my-account';
1247
  $_imgopt_unreach = 'https://shortpixel.helpscoutdocs.com/article/148-why-are-my-images-redirected-from-cdn-shortpixel-ai';
1248
 
1254
  // translators: "add more credits" will appear in a "a href".
1255
  $_imgopt_notice = sprintf( __( 'Your ShortPixel image optimization and CDN quota was used, %1$sadd more credits%2$s to keep fast serving optimized images on your site', 'autoptimize' ), '<a href="' . $_imgopt_upsell . '" target="_blank">', '</a>' );
1256
  // translators: "associate your domain" will appear in a "a href".
1257
+ $_imgopt_notice = $_imgopt_notice . ' ' . sprintf( __( 'If you have enough CDN quota remaining, then you may need to %1$sassociate your domain%2$s to your Shortpixel account.', 'autoptimize' ), '<a rel="noopener noreferrer" href="' . $_imgopt_assoc . '" target="_blank">', '</a>' );
1258
  } elseif ( -3 == $_stat['Status'] ) {
1259
  // translators: "check the documentation here" will appear in a "a href".
1260
  $_imgopt_notice = sprintf( __( 'It seems ShortPixel image optimization is not able to fetch images from your site, %1$scheck the documentation here%2$s for more information', 'autoptimize' ), '<a href="' . $_imgopt_unreach . '" target="_blank">', '</a>' );
1261
  } else {
1262
+ $_imgopt_upsell = 'https://shortpixel.com/g/af/SPZURYE109483';
1263
  // translators: "log in to check your account" will appear in a "a href".
1264
  $_imgopt_notice = sprintf( __( 'Your ShortPixel image optimization and CDN quota are in good shape, %1$slog in to check your account%2$s.', 'autoptimize' ), '<a href="' . $_imgopt_upsell . '" target="_blank">', '</a>' );
1265
  }
1277
  }
1278
  $_imgopt_notice .= ' (' . $_imgopt_stats_last_run . ', ';
1279
  // translators: "here to refresh" links to the Autoptimize Extra page and forces a refresh of the img opt stats.
1280
+ $_imgopt_notice .= sprintf( __( 'you can click %1$shere to refresh your quota status%2$s', 'autoptimize' ), '<a href="' . $_imgopt_stats_refresh_url . '">', '</a>).' );
1281
  }
1282
 
1283
  // and make the full notice filterable.
1301
  /**
1302
  * Get img provider stats (used to display notice).
1303
  */
1304
+ public function query_img_provider_stats( $_refresh = false ) {
1305
  if ( ! empty( $this->options['autoptimize_imgopt_checkbox_field_1'] ) ) {
1306
  $url = '';
1307
+ $stat_dom = 'https://no-cdn.shortpixel.ai/';
1308
+ $endpoint = $stat_dom . 'read-domain/';
1309
  $domain = AUTOPTIMIZE_SITE_DOMAIN;
1310
 
1311
  // make sure parse_url result makes sense, keeping $url empty if not.
1312
  if ( $domain && ! empty( $domain ) ) {
1313
  $url = $endpoint . $domain;
1314
+ if ( true === $_refresh ) {
1315
+ $url = $url . '/refresh';
1316
+ }
1317
  }
1318
 
1319
  $url = apply_filters(
classes/autoptimizeMain.php CHANGED
@@ -684,13 +684,14 @@ class autoptimizeMain
684
  public static function notice_plug_imgopt()
685
  {
686
  // Translators: the URL added points to the Autopmize Extra settings.
687
- $_ao_imgopt_plug_notice = sprintf( __( 'Did you know Autoptimize includes on-the-fly image optimization (with support for WebP) and CDN via ShortPixel? Check out the %1$sAutoptimize Image settings%2$s to activate this option.', 'autoptimize' ), '<a href="options-general.php?page=autoptimize_imgopt">', '</a>' );
688
  $_ao_imgopt_plug_notice = apply_filters( 'autoptimize_filter_main_imgopt_plug_notice', $_ao_imgopt_plug_notice );
689
  $_ao_imgopt_launch_ok = autoptimizeImages::launch_ok_wrapper();
690
  $_ao_imgopt_plug_dismissible = 'ao-img-opt-plug-123';
691
  $_ao_imgopt_active = autoptimizeImages::imgopt_active();
 
692
 
693
- if ( current_user_can( 'manage_options' ) && '' !== $_ao_imgopt_plug_notice && ! $_ao_imgopt_active && $_ao_imgopt_launch_ok && PAnD::is_admin_notice_active( $_ao_imgopt_plug_dismissible ) ) {
694
  echo '<div class="notice notice-info is-dismissible" data-dismissible="' . $_ao_imgopt_plug_dismissible . '"><p>';
695
  echo $_ao_imgopt_plug_notice;
696
  echo '</p></div>';
684
  public static function notice_plug_imgopt()
685
  {
686
  // Translators: the URL added points to the Autopmize Extra settings.
687
+ $_ao_imgopt_plug_notice = sprintf( __( 'Did you know Autoptimize includes on-the-fly image optimization (with support for WebP and AVIF) and CDN via ShortPixel? Check out the %1$sAutoptimize Image settings%2$s to activate this option.', 'autoptimize' ), '<a href="options-general.php?page=autoptimize_imgopt">', '</a>' );
688
  $_ao_imgopt_plug_notice = apply_filters( 'autoptimize_filter_main_imgopt_plug_notice', $_ao_imgopt_plug_notice );
689
  $_ao_imgopt_launch_ok = autoptimizeImages::launch_ok_wrapper();
690
  $_ao_imgopt_plug_dismissible = 'ao-img-opt-plug-123';
691
  $_ao_imgopt_active = autoptimizeImages::imgopt_active();
692
+ $_is_ao_settings_page = ( str_replace( array( 'autoptimize', 'autoptimize_imgopt', 'ao_critcss', 'autoptimize_extra', 'ao_partners' ), '', $_SERVER['REQUEST_URI'] ) !== $_SERVER['REQUEST_URI'] ? true : false );
693
 
694
+ if ( current_user_can( 'manage_options' ) && $_is_ao_settings_page && '' !== $_ao_imgopt_plug_notice && ! $_ao_imgopt_active && $_ao_imgopt_launch_ok && PAnD::is_admin_notice_active( $_ao_imgopt_plug_dismissible ) ) {
695
  echo '<div class="notice notice-info is-dismissible" data-dismissible="' . $_ao_imgopt_plug_dismissible . '"><p>';
696
  echo $_ao_imgopt_plug_notice;
697
  echo '</p></div>';
classes/autoptimizeScripts.php CHANGED
@@ -60,6 +60,8 @@ class autoptimizeScripts extends autoptimizeBase
60
  'data-noptimize',
61
  'logHuman',
62
  'amp-mobile-version-switcher',
 
 
63
  );
64
 
65
  /**
60
  'data-noptimize',
61
  'logHuman',
62
  'amp-mobile-version-switcher',
63
+ 'data-rocketlazyloadscript',
64
+ 'rocket-browser-checker-js-after',
65
  );
66
 
67
  /**
classes/critcss-inc/admin_settings_adv.php CHANGED
@@ -86,7 +86,7 @@ function ao_ccss_render_adv() {
86
  <td>
87
  <input type="checkbox" id="autoptimize_ccss_loggedin" name="autoptimize_ccss_loggedin" value="1" <?php checked( 1 == $ao_ccss_loggedin ); ?>>
88
  <p class="notes">
89
- <?php _e( 'Critical CSS is generated by criticalcss.com from your pages as seen be "anonymous visitor", disable this option if you don\'t want the "visitor" critical CSS to be used for logged on users.', 'autoptimize' ); ?>
90
  </p>
91
  </td>
92
  </tr>
86
  <td>
87
  <input type="checkbox" id="autoptimize_ccss_loggedin" name="autoptimize_ccss_loggedin" value="1" <?php checked( 1 == $ao_ccss_loggedin ); ?>>
88
  <p class="notes">
89
+ <?php _e( 'Critical CSS is generated by criticalcss.com from your pages as seen by an "anonymous visitor". Disable this option if you don\'t want the "visitor" critical CSS to be used for logged in users.', 'autoptimize' ); ?>
90
  </p>
91
  </td>
92
  </tr>
classes/critcss-inc/admin_settings_rules.php CHANGED
@@ -180,7 +180,7 @@ function ao_ccss_render_rules() {
180
  <li><?php _e( 'If you want to make any fine tunning in the critical CSS file of an <span class="badge auto">AUTO</span> rule, click on "Edit" button of that rule, change what you need, submit and save it. The rule you\'ve just edited becomes a <span class="badge manual">MANUAL</span> rule then.', 'autoptimize' ); ?></li>
181
  <li><?php _e( 'You can create <span class="badge manual">MANUAL</span> rules for specific page paths (URL). Longer, more specific paths have higher priority over shorter ones, which in turn have higher priority over <span class="badge auto">AUTO</span> rules. Also, critical CSS files from <span class="badge manual">MANUAL</span> <strong>rules are NEVER updated automatically.</strong>', 'autoptimize' ); ?></li>
182
  <li><?php _e( 'You can also create an <span class="badge auto">AUTO</span> rule for a path by leaving its critical CSS content empty. The critical CSS for that path will be automatically fetched from <a href="https://criticalcss.com/?aff=1" target="_blank">criticalcss.com</a> for you and updated whenever it changes.', 'autoptimize' ); ?></li>
183
- <li><?php _e( "If you see an <span class='badge auto'>AUTO</span> rule with a <span class='badge review'>R</span> besides it (R is after REVIEW), it means that the fetched critical CSS for that rule is not 100% garanteed to work according to <a href='https://criticalcss.com/?aff=1' target='_blank'>criticalcss.com</a> analysis. It's advised that you edit and review that rule to make any required adjustments.", 'autoptimize' ); ?></li>
184
  <li><?php _e( 'At any time you can delete an <span class="badge auto">AUTO</span> or <span class="badge manual">MANUAL</span> rule by cliking on "Remove" button of the desired rule and saving your changes.', 'autoptimize' ); ?></li>
185
  </ol>
186
  </div>
180
  <li><?php _e( 'If you want to make any fine tunning in the critical CSS file of an <span class="badge auto">AUTO</span> rule, click on "Edit" button of that rule, change what you need, submit and save it. The rule you\'ve just edited becomes a <span class="badge manual">MANUAL</span> rule then.', 'autoptimize' ); ?></li>
181
  <li><?php _e( 'You can create <span class="badge manual">MANUAL</span> rules for specific page paths (URL). Longer, more specific paths have higher priority over shorter ones, which in turn have higher priority over <span class="badge auto">AUTO</span> rules. Also, critical CSS files from <span class="badge manual">MANUAL</span> <strong>rules are NEVER updated automatically.</strong>', 'autoptimize' ); ?></li>
182
  <li><?php _e( 'You can also create an <span class="badge auto">AUTO</span> rule for a path by leaving its critical CSS content empty. The critical CSS for that path will be automatically fetched from <a href="https://criticalcss.com/?aff=1" target="_blank">criticalcss.com</a> for you and updated whenever it changes.', 'autoptimize' ); ?></li>
183
+ <li><?php _e( "If you see an <span class='badge auto'>AUTO</span> rule with a <span class='badge review'>R</span> besides it (R is after REVIEW), it means that the fetched critical CSS for that rule is not 100% guaranteed to work according to <a href='https://criticalcss.com/?aff=1' target='_blank'>criticalcss.com</a> analysis. It's advised that you edit and review that rule to make any required adjustments.", 'autoptimize' ); ?></li>
184
  <li><?php _e( 'At any time you can delete an <span class="badge auto">AUTO</span> or <span class="badge manual">MANUAL</span> rule by cliking on "Remove" button of the desired rule and saving your changes.', 'autoptimize' ); ?></li>
185
  </ol>
186
  </div>
classes/external/js/lazysizes.min.js CHANGED
@@ -1,3 +1,3 @@
1
- /*! lazysizes + ls unveilhooks - v5.2.2 (incl. ls-uvh data-link fix) */
2
- !function(e){var t=function(u,D,f){"use strict";var k,H;if(function(){var e;var t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:true,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:true,ricTimeout:0,throttleDelay:125};H=u.lazySizesConfig||u.lazysizesConfig||{};for(e in t){if(!(e in H)){H[e]=t[e]}}}(),!D||!D.getElementsByClassName){return{init:function(){},cfg:H,noSupport:true}}var O=D.documentElement,a=u.HTMLPictureElement,P="addEventListener",$="getAttribute",q=u[P].bind(u),I=u.setTimeout,U=u.requestAnimationFrame||I,l=u.requestIdleCallback,j=/^picture$/i,r=["load","error","lazyincluded","_lazyloaded"],i={},G=Array.prototype.forEach,J=function(e,t){if(!i[t]){i[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")}return i[t].test(e[$]("class")||"")&&i[t]},K=function(e,t){if(!J(e,t)){e.setAttribute("class",(e[$]("class")||"").trim()+" "+t)}},Q=function(e,t){var i;if(i=J(e,t)){e.setAttribute("class",(e[$]("class")||"").replace(i," "))}},V=function(t,i,e){var a=e?P:"removeEventListener";if(e){V(t,i)}r.forEach(function(e){t[a](e,i)})},X=function(e,t,i,a,r){var n=D.createEvent("Event");if(!i){i={}}i.instance=k;n.initEvent(t,!a,!r);n.detail=i;e.dispatchEvent(n);return n},Y=function(e,t){var i;if(!a&&(i=u.picturefill||H.pf)){if(t&&t.src&&!e[$]("srcset")){e.setAttribute("srcset",t.src)}i({reevaluate:true,elements:[e]})}else if(t&&t.src){e.src=t.src}},Z=function(e,t){return(getComputedStyle(e,null)||{})[t]},s=function(e,t,i){i=i||e.offsetWidth;while(i<H.minSize&&t&&!e._lazysizesWidth){i=t.offsetWidth;t=t.parentNode}return i},ee=function(){var i,a;var t=[];var r=[];var n=t;var s=function(){var e=n;n=t.length?r:t;i=true;a=false;while(e.length){e.shift()()}i=false};var e=function(e,t){if(i&&!t){e.apply(this,arguments)}else{n.push(e);if(!a){a=true;(D.hidden?I:U)(s)}}};e._lsFlush=s;return e}(),te=function(i,e){return e?function(){ee(i)}:function(){var e=this;var t=arguments;ee(function(){i.apply(e,t)})}},ie=function(e){var i;var a=0;var r=H.throttleDelay;var n=H.ricTimeout;var t=function(){i=false;a=f.now();e()};var s=l&&n>49?function(){l(t,{timeout:n});if(n!==H.ricTimeout){n=H.ricTimeout}}:te(function(){I(t)},true);return function(e){var t;if(e=e===true){n=33}if(i){return}i=true;t=r-(f.now()-a);if(t<0){t=0}if(e||t<9){s()}else{I(s,t)}}},ae=function(e){var t,i;var a=99;var r=function(){t=null;e()};var n=function(){var e=f.now()-i;if(e<a){I(n,a-e)}else{(l||r)(r)}};return function(){i=f.now();if(!t){t=I(n,a)}}},e=function(){var v,m,c,h,e;var y,z,g,p,C,b,A;var n=/^img$/i;var d=/^iframe$/i;var E="onscroll"in u&&!/(gle|ing)bot/.test(navigator.userAgent);var _=0;var w=0;var N=0;var M=-1;var x=function(e){N--;if(!e||N<0||!e.target){N=0}};var W=function(e){if(A==null){A=Z(D.body,"visibility")=="hidden"}return A||!(Z(e.parentNode,"visibility")=="hidden"&&Z(e,"visibility")=="hidden")};var S=function(e,t){var i;var a=e;var r=W(e);g-=t;b+=t;p-=t;C+=t;while(r&&(a=a.offsetParent)&&a!=D.body&&a!=O){r=(Z(a,"opacity")||1)>0;if(r&&Z(a,"overflow")!="visible"){i=a.getBoundingClientRect();r=C>i.left&&p<i.right&&b>i.top-1&&g<i.bottom+1}}return r};var t=function(){var e,t,i,a,r,n,s,l,o,u,f,c;var d=k.elements;if((h=H.loadMode)&&N<8&&(e=d.length)){t=0;M++;for(;t<e;t++){if(!d[t]||d[t]._lazyRace){continue}if(!E||k.prematureUnveil&&k.prematureUnveil(d[t])){R(d[t]);continue}if(!(l=d[t][$]("data-expand"))||!(n=l*1)){n=w}if(!u){u=!H.expand||H.expand<1?O.clientHeight>500&&O.clientWidth>500?500:370:H.expand;k._defEx=u;f=u*H.expFactor;c=H.hFac;A=null;if(w<f&&N<1&&M>2&&h>2&&!D.hidden){w=f;M=0}else if(h>1&&M>1&&N<6){w=u}else{w=_}}if(o!==n){y=innerWidth+n*c;z=innerHeight+n;s=n*-1;o=n}i=d[t].getBoundingClientRect();if((b=i.bottom)>=s&&(g=i.top)<=z&&(C=i.right)>=s*c&&(p=i.left)<=y&&(b||C||p||g)&&(H.loadHidden||W(d[t]))&&(m&&N<3&&!l&&(h<3||M<4)||S(d[t],n))){R(d[t]);r=true;if(N>9){break}}else if(!r&&m&&!a&&N<4&&M<4&&h>2&&(v[0]||H.preloadAfterLoad)&&(v[0]||!l&&(b||C||p||g||d[t][$](H.sizesAttr)!="auto"))){a=v[0]||d[t]}}if(a&&!r){R(a)}}};var i=ie(t);var B=function(e){var t=e.target;if(t._lazyCache){delete t._lazyCache;return}x(e);K(t,H.loadedClass);Q(t,H.loadingClass);V(t,L);X(t,"lazyloaded")};var a=te(B);var L=function(e){a({target:e.target})};var T=function(t,i){try{t.contentWindow.location.replace(i)}catch(e){t.src=i}};var F=function(e){var t;var i=e[$](H.srcsetAttr);if(t=H.customMedia[e[$]("data-media")||e[$]("media")]){e.setAttribute("media",t)}if(i){e.setAttribute("srcset",i)}};var s=te(function(t,e,i,a,r){var n,s,l,o,u,f;if(!(u=X(t,"lazybeforeunveil",e)).defaultPrevented){if(a){if(i){K(t,H.autosizesClass)}else{t.setAttribute("sizes",a)}}s=t[$](H.srcsetAttr);n=t[$](H.srcAttr);if(r){l=t.parentNode;o=l&&j.test(l.nodeName||"")}f=e.firesLoad||"src"in t&&(s||n||o);u={target:t};K(t,H.loadingClass);if(f){clearTimeout(c);c=I(x,2500);V(t,L,true)}if(o){G.call(l.getElementsByTagName("source"),F)}if(s){t.setAttribute("srcset",s)}else if(n&&!o){if(d.test(t.nodeName)){T(t,n)}else{t.src=n}}if(r&&(s||o)){Y(t,{src:n})}}if(t._lazyRace){delete t._lazyRace}Q(t,H.lazyClass);ee(function(){var e=t.complete&&t.naturalWidth>1;if(!f||e){if(e){K(t,"ls-is-cached")}B(u);t._lazyCache=true;I(function(){if("_lazyCache"in t){delete t._lazyCache}},9)}if(t.loading=="lazy"){N--}},true)});var R=function(e){if(e._lazyRace){return}var t;var i=n.test(e.nodeName);var a=i&&(e[$](H.sizesAttr)||e[$]("sizes"));var r=a=="auto";if((r||!m)&&i&&(e[$]("src")||e.srcset)&&!e.complete&&!J(e,H.errorClass)&&J(e,H.lazyClass)){return}t=X(e,"lazyunveilread").detail;if(r){re.updateElem(e,true,e.offsetWidth)}e._lazyRace=true;N++;s(e,t,r,a,i)};var r=ae(function(){H.loadMode=3;i()});var l=function(){if(H.loadMode==3){H.loadMode=2}r()};var o=function(){if(m){return}if(f.now()-e<999){I(o,999);return}m=true;H.loadMode=3;i();q("scroll",l,true)};return{_:function(){e=f.now();k.elements=D.getElementsByClassName(H.lazyClass);v=D.getElementsByClassName(H.lazyClass+" "+H.preloadClass);q("scroll",i,true);q("resize",i,true);q("pageshow",function(e){if(e.persisted){var t=D.querySelectorAll("."+H.loadingClass);if(t.length&&t.forEach){U(function(){t.forEach(function(e){if(e.complete){R(e)}})})}}});if(u.MutationObserver){new MutationObserver(i).observe(O,{childList:true,subtree:true,attributes:true})}else{O[P]("DOMNodeInserted",i,true);O[P]("DOMAttrModified",i,true);setInterval(i,999)}q("hashchange",i,true);["focus","mouseover","click","load","transitionend","animationend"].forEach(function(e){D[P](e,i,true)});if(/d$|^c/.test(D.readyState)){o()}else{q("load",o);D[P]("DOMContentLoaded",i);I(o,2e4)}if(k.elements.length){t();ee._lsFlush()}else{i()}},checkElems:i,unveil:R,_aLSL:l}}(),re=function(){var i;var n=te(function(e,t,i,a){var r,n,s;e._lazysizesWidth=a;a+="px";e.setAttribute("sizes",a);if(j.test(t.nodeName||"")){r=t.getElementsByTagName("source");for(n=0,s=r.length;n<s;n++){r[n].setAttribute("sizes",a)}}if(!i.detail.dataAttr){Y(e,i.detail)}});var a=function(e,t,i){var a;var r=e.parentNode;if(r){i=s(e,r,i);a=X(e,"lazybeforesizes",{width:i,dataAttr:!!t});if(!a.defaultPrevented){i=a.detail.width;if(i&&i!==e._lazysizesWidth){n(e,r,a,i)}}}};var e=function(){var e;var t=i.length;if(t){e=0;for(;e<t;e++){a(i[e])}}};var t=ae(e);return{_:function(){i=D.getElementsByClassName(H.autosizesClass);q("resize",t)},checkElems:t,updateElem:a}}(),t=function(){if(!t.i&&D.getElementsByClassName){t.i=true;re._();e._()}};return I(function(){H.init&&t()}),k={cfg:H,autoSizer:re,loader:e,init:t,uP:Y,aC:K,rC:Q,hC:J,fire:X,gW:s,rAF:ee}}(e,e.document,Date);e.lazySizes=t,"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:{});
3
- !function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):"function"==typeof define&&define.amd?define(["lazysizes"],t):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(e,n,i){"use strict";var l,o,d={};function u(e,t){var a,r;d[e]||(a=n.createElement(t?"link":"script"),r=n.getElementsByTagName("script")[0],t?(a.rel="stylesheet",a.href=e):a.src=e,d[e]=!0,d[a.src||a.href]=!0,r.parentNode.insertBefore(a,r))}n.addEventListener&&(l=function(e,t){var a=n.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,r;if(e.detail.instance==i&&!e.defaultPrevented){var n=e.target;if("none"==n.preload&&(n.preload=n.getAttribute("data-preload")||"auto"),null!=n.getAttribute("data-autoplay"))if(n.getAttribute("data-expand")&&!n.autoplay)try{n.play()}catch(e){}else requestAnimationFrame(function(){n.setAttribute("data-expand","-10"),i.aC(n,i.cfg.lazyClass)});(t=n.getAttribute("data-link"))&&"img"!=n.tagName.toLowerCase()&&u(t,!0),(t=n.getAttribute("data-script"))&&u(t),(t=n.getAttribute("data-require"))&&(i.cfg.requireJs?i.cfg.requireJs([t]):u(t)),(a=n.getAttribute("data-bg"))&&(e.detail.firesLoad=!0,l(a,function(){n.style.backgroundImage="url("+(o.test(a)?JSON.stringify(a):a)+")",e.detail.firesLoad=!1,i.fire(n,"_lazyloaded",{},!0,!0)})),(r=n.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,l(r,function(){n.poster=r,e.detail.firesLoad=!1,i.fire(n,"_lazyloaded",{},!0,!0)}))}},!(o=/\(|\)|\s|'/)))});
1
+ /*! lazysizes + ls unveilhooks - v5.3.1 (incl. ls-uvh data-link fix) */
2
+ !function(e){var t=function(u,D,f){"use strict";var k,H;if(function(){var e;var t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",fastLoadedClass:"ls-is-cached",iframeLoadMode:0,srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:true,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:true,ricTimeout:0,throttleDelay:125};H=u.lazySizesConfig||u.lazysizesConfig||{};for(e in t){if(!(e in H)){H[e]=t[e]}}}(),!D||!D.getElementsByClassName){return{init:function(){},cfg:H,noSupport:true}}var O=D.documentElement,i=u.HTMLPictureElement,P="addEventListener",$="getAttribute",q=u[P].bind(u),I=u.setTimeout,U=u.requestAnimationFrame||I,o=u.requestIdleCallback,j=/^picture$/i,r=["load","error","lazyincluded","_lazyloaded"],a={},G=Array.prototype.forEach,J=function(e,t){if(!a[t]){a[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")}return a[t].test(e[$]("class")||"")&&a[t]},K=function(e,t){if(!J(e,t)){e.setAttribute("class",(e[$]("class")||"").trim()+" "+t)}},Q=function(e,t){var a;if(a=J(e,t)){e.setAttribute("class",(e[$]("class")||"").replace(a," "))}},V=function(t,a,e){var i=e?P:"removeEventListener";if(e){V(t,a)}r.forEach(function(e){t[i](e,a)})},X=function(e,t,a,i,r){var n=D.createEvent("Event");if(!a){a={}}a.instance=k;n.initEvent(t,!i,!r);n.detail=a;e.dispatchEvent(n);return n},Y=function(e,t){var a;if(!i&&(a=u.picturefill||H.pf)){if(t&&t.src&&!e[$]("srcset")){e.setAttribute("srcset",t.src)}a({reevaluate:true,elements:[e]})}else if(t&&t.src){e.src=t.src}},Z=function(e,t){return(getComputedStyle(e,null)||{})[t]},s=function(e,t,a){a=a||e.offsetWidth;while(a<H.minSize&&t&&!e._lazysizesWidth){a=t.offsetWidth;t=t.parentNode}return a},ee=function(){var a,i;var t=[];var r=[];var n=t;var s=function(){var e=n;n=t.length?r:t;a=true;i=false;while(e.length){e.shift()()}a=false};var e=function(e,t){if(a&&!t){e.apply(this,arguments)}else{n.push(e);if(!i){i=true;(D.hidden?I:U)(s)}}};e._lsFlush=s;return e}(),te=function(a,e){return e?function(){ee(a)}:function(){var e=this;var t=arguments;ee(function(){a.apply(e,t)})}},ae=function(e){var a;var i=0;var r=H.throttleDelay;var n=H.ricTimeout;var t=function(){a=false;i=f.now();e()};var s=o&&n>49?function(){o(t,{timeout:n});if(n!==H.ricTimeout){n=H.ricTimeout}}:te(function(){I(t)},true);return function(e){var t;if(e=e===true){n=33}if(a){return}a=true;t=r-(f.now()-i);if(t<0){t=0}if(e||t<9){s()}else{I(s,t)}}},ie=function(e){var t,a;var i=99;var r=function(){t=null;e()};var n=function(){var e=f.now()-a;if(e<i){I(n,i-e)}else{(o||r)(r)}};return function(){a=f.now();if(!t){t=I(n,i)}}},e=function(){var v,m,c,h,e;var y,z,g,p,C,b,A;var n=/^img$/i;var d=/^iframe$/i;var E="onscroll"in u&&!/(gle|ing)bot/.test(navigator.userAgent);var _=0;var w=0;var M=0;var N=-1;var L=function(e){M--;if(!e||M<0||!e.target){M=0}};var x=function(e){if(A==null){A=Z(D.body,"visibility")=="hidden"}return A||!(Z(e.parentNode,"visibility")=="hidden"&&Z(e,"visibility")=="hidden")};var W=function(e,t){var a;var i=e;var r=x(e);g-=t;b+=t;p-=t;C+=t;while(r&&(i=i.offsetParent)&&i!=D.body&&i!=O){r=(Z(i,"opacity")||1)>0;if(r&&Z(i,"overflow")!="visible"){a=i.getBoundingClientRect();r=C>a.left&&p<a.right&&b>a.top-1&&g<a.bottom+1}}return r};var t=function(){var e,t,a,i,r,n,s,o,l,u,f,c;var d=k.elements;if((h=H.loadMode)&&M<8&&(e=d.length)){t=0;N++;for(;t<e;t++){if(!d[t]||d[t]._lazyRace){continue}if(!E||k.prematureUnveil&&k.prematureUnveil(d[t])){R(d[t]);continue}if(!(o=d[t][$]("data-expand"))||!(n=o*1)){n=w}if(!u){u=!H.expand||H.expand<1?O.clientHeight>500&&O.clientWidth>500?500:370:H.expand;k._defEx=u;f=u*H.expFactor;c=H.hFac;A=null;if(w<f&&M<1&&N>2&&h>2&&!D.hidden){w=f;N=0}else if(h>1&&N>1&&M<6){w=u}else{w=_}}if(l!==n){y=innerWidth+n*c;z=innerHeight+n;s=n*-1;l=n}a=d[t].getBoundingClientRect();if((b=a.bottom)>=s&&(g=a.top)<=z&&(C=a.right)>=s*c&&(p=a.left)<=y&&(b||C||p||g)&&(H.loadHidden||x(d[t]))&&(m&&M<3&&!o&&(h<3||N<4)||W(d[t],n))){R(d[t]);r=true;if(M>9){break}}else if(!r&&m&&!i&&M<4&&N<4&&h>2&&(v[0]||H.preloadAfterLoad)&&(v[0]||!o&&(b||C||p||g||d[t][$](H.sizesAttr)!="auto"))){i=v[0]||d[t]}}if(i&&!r){R(i)}}};var a=ae(t);var S=function(e){var t=e.target;if(t._lazyCache){delete t._lazyCache;return}L(e);K(t,H.loadedClass);Q(t,H.loadingClass);V(t,B);X(t,"lazyloaded")};var i=te(S);var B=function(e){i({target:e.target})};var T=function(e,t){var a=e.getAttribute("data-load-mode")||H.iframeLoadMode;if(a==0){e.contentWindow.location.replace(t)}else if(a==1){e.src=t}};var F=function(e){var t;var a=e[$](H.srcsetAttr);if(t=H.customMedia[e[$]("data-media")||e[$]("media")]){e.setAttribute("media",t)}if(a){e.setAttribute("srcset",a)}};var s=te(function(t,e,a,i,r){var n,s,o,l,u,f;if(!(u=X(t,"lazybeforeunveil",e)).defaultPrevented){if(i){if(a){K(t,H.autosizesClass)}else{t.setAttribute("sizes",i)}}s=t[$](H.srcsetAttr);n=t[$](H.srcAttr);if(r){o=t.parentNode;l=o&&j.test(o.nodeName||"")}f=e.firesLoad||"src"in t&&(s||n||l);u={target:t};K(t,H.loadingClass);if(f){clearTimeout(c);c=I(L,2500);V(t,B,true)}if(l){G.call(o.getElementsByTagName("source"),F)}if(s){t.setAttribute("srcset",s)}else if(n&&!l){if(d.test(t.nodeName)){T(t,n)}else{t.src=n}}if(r&&(s||l)){Y(t,{src:n})}}if(t._lazyRace){delete t._lazyRace}Q(t,H.lazyClass);ee(function(){var e=t.complete&&t.naturalWidth>1;if(!f||e){if(e){K(t,H.fastLoadedClass)}S(u);t._lazyCache=true;I(function(){if("_lazyCache"in t){delete t._lazyCache}},9)}if(t.loading=="lazy"){M--}},true)});var R=function(e){if(e._lazyRace){return}var t;var a=n.test(e.nodeName);var i=a&&(e[$](H.sizesAttr)||e[$]("sizes"));var r=i=="auto";if((r||!m)&&a&&(e[$]("src")||e.srcset)&&!e.complete&&!J(e,H.errorClass)&&J(e,H.lazyClass)){return}t=X(e,"lazyunveilread").detail;if(r){re.updateElem(e,true,e.offsetWidth)}e._lazyRace=true;M++;s(e,t,r,i,a)};var r=ie(function(){H.loadMode=3;a()});var o=function(){if(H.loadMode==3){H.loadMode=2}r()};var l=function(){if(m){return}if(f.now()-e<999){I(l,999);return}m=true;H.loadMode=3;a();q("scroll",o,true)};return{_:function(){e=f.now();k.elements=D.getElementsByClassName(H.lazyClass);v=D.getElementsByClassName(H.lazyClass+" "+H.preloadClass);q("scroll",a,true);q("resize",a,true);q("pageshow",function(e){if(e.persisted){var t=D.querySelectorAll("."+H.loadingClass);if(t.length&&t.forEach){U(function(){t.forEach(function(e){if(e.complete){R(e)}})})}}});if(u.MutationObserver){new MutationObserver(a).observe(O,{childList:true,subtree:true,attributes:true})}else{O[P]("DOMNodeInserted",a,true);O[P]("DOMAttrModified",a,true);setInterval(a,999)}q("hashchange",a,true);["focus","mouseover","click","load","transitionend","animationend"].forEach(function(e){D[P](e,a,true)});if(/d$|^c/.test(D.readyState)){l()}else{q("load",l);D[P]("DOMContentLoaded",a);I(l,2e4)}if(k.elements.length){t();ee._lsFlush()}else{a()}},checkElems:a,unveil:R,_aLSL:o}}(),re=function(){var a;var n=te(function(e,t,a,i){var r,n,s;e._lazysizesWidth=i;i+="px";e.setAttribute("sizes",i);if(j.test(t.nodeName||"")){r=t.getElementsByTagName("source");for(n=0,s=r.length;n<s;n++){r[n].setAttribute("sizes",i)}}if(!a.detail.dataAttr){Y(e,a.detail)}});var i=function(e,t,a){var i;var r=e.parentNode;if(r){a=s(e,r,a);i=X(e,"lazybeforesizes",{width:a,dataAttr:!!t});if(!i.defaultPrevented){a=i.detail.width;if(a&&a!==e._lazysizesWidth){n(e,r,i,a)}}}};var e=function(){var e;var t=a.length;if(t){e=0;for(;e<t;e++){i(a[e])}}};var t=ie(e);return{_:function(){a=D.getElementsByClassName(H.autosizesClass);q("resize",t)},checkElems:t,updateElem:i}}(),t=function(){if(!t.i&&D.getElementsByClassName){t.i=true;re._();e._()}};return I(function(){H.init&&t()}),k={cfg:H,autoSizer:re,loader:e,init:t,uP:Y,aC:K,rC:Q,hC:J,fire:X,gW:s,rAF:ee}}(e,e.document,Date);e.lazySizes=t,"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:{});
3
+ !function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):"function"==typeof define&&define.amd?define(["lazysizes"],t):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(e,i,o){"use strict";var l,d,u={};function s(e,t,a){var n,r;u[e]||(n=i.createElement(t?"link":"script"),r=i.getElementsByTagName("script")[0],t?(n.rel="stylesheet",n.href=e):(n.onload=function(){n.onerror=null,n.onload=null,a()},n.onerror=n.onload,n.src=e),u[e]=!0,u[n.src||n.href]=!0,r.parentNode.insertBefore(n,r))}i.addEventListener&&(l=function(e,t){var a=i.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,n;if(e.detail.instance==o&&!e.defaultPrevented){var r=e.target;if("none"==r.preload&&(r.preload=r.getAttribute("data-preload")||"auto"),null!=r.getAttribute("data-autoplay"))if(r.getAttribute("data-expand")&&!r.autoplay)try{r.play()}catch(e){}else requestAnimationFrame(function(){r.setAttribute("data-expand","-10"),o.aC(r,o.cfg.lazyClass)});(t=r.getAttribute("data-link"))&&"img"!=r.tagName.toLowerCase()&&s(t,!0),(t=r.getAttribute("data-script"))&&(e.detail.firesLoad=!0,s(t,null,function(){e.detail.firesLoad=!1,o.fire(r,"_lazyloaded",{},!0,!0)})),(t=r.getAttribute("data-require"))&&(o.cfg.requireJs?o.cfg.requireJs([t]):s(t)),(a=r.getAttribute("data-bg"))&&(e.detail.firesLoad=!0,l(a,function(){r.style.backgroundImage="url("+(d.test(a)?JSON.stringify(a):a)+")",e.detail.firesLoad=!1,o.fire(r,"_lazyloaded",{},!0,!0)})),(n=r.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,l(n,function(){r.poster=n,e.detail.firesLoad=!1,o.fire(r,"_lazyloaded",{},!0,!0)}))}},!(d=/\(|\)|\s|'/)))});
classes/external/php/{minify-html.php → ao-minify-html.php} RENAMED
@@ -16,7 +16,7 @@
16
  * @package Minify
17
  * @author Stephen Clay <steve@mrclay.org>
18
  */
19
- class Minify_HTML {
20
 
21
  /** @var string */
22
  private $_html;
@@ -43,7 +43,7 @@ class Minify_HTML {
43
  * @return string
44
  */
45
  public static function minify($html, $options = array()) {
46
- $min = new Minify_HTML($html, $options);
47
  return $min->process();
48
  }
49
 
16
  * @package Minify
17
  * @author Stephen Clay <steve@mrclay.org>
18
  */
19
+ class AO_Minify_HTML {
20
 
21
  /** @var string */
22
  private $_html;
43
  * @return string
44
  */
45
  public static function minify($html, $options = array()) {
46
+ $min = new AO_Minify_HTML($html, $options);
47
  return $min->process();
48
  }
49
 
readme.txt CHANGED
@@ -5,7 +5,7 @@ Donate link: http://blog.futtta.be/2013/10/21/do-not-donate-to-me/
5
  Requires at least: 4.9
6
  Tested up to: 5.7
7
  Requires PHP: 5.6
8
- Stable tag: 2.8.1
9
 
10
  Autoptimize speeds up your website by optimizing JS, CSS, images (incl. lazy-load), HTML and Google Fonts, asyncing JS, removing emoji cruft and more.
11
 
@@ -319,6 +319,14 @@ Just [fork Autoptimize on Github](https://github.com/futtta/autoptimize) and cod
319
 
320
  == Changelog ==
321
 
 
 
 
 
 
 
 
 
322
  = 2.8.1 =
323
  * Images: new option not to lazyload first X images
324
  * fix for "array to string" conversion errors in image optimization logic of .ico files
5
  Requires at least: 4.9
6
  Tested up to: 5.7
7
  Requires PHP: 5.6
8
+ Stable tag: 2.8.2
9
 
10
  Autoptimize speeds up your website by optimizing JS, CSS, images (incl. lazy-load), HTML and Google Fonts, asyncing JS, removing emoji cruft and more.
11
 
319
 
320
  == Changelog ==
321
 
322
+ = 2.8.2 =
323
+ * Images: only show "did you know shortpixel" notice on Autoptimize settings pages (no more littering all over the backend)
324
+ * Images: update lazysizes from upstream
325
+ * Images: misc. improvements such as fix for PHP "undefined index" notice, updated copy, ...
326
+ * HTML: rename HTML minify class from minify_HTML to AO_minify_HTML to avoid conflicts with e.g. W3TC
327
+ * Critical CSS: misc. improvements such as detect is_front_page before any other conditional, fix for conditional rules without an actual condition, improved debug logging, ...
328
+ * JS/ CSS: fix for AO not optimizing multisite child sites when CDN set
329
+
330
  = 2.8.1 =
331
  * Images: new option not to lazyload first X images
332
  * fix for "array to string" conversion errors in image optimization logic of .ico files