Version Description
- Images: Also optimize & lazyload <picture><source>
- Images: Misc. improvements to lazyload
- Images: Updated to LazySizes 5.0.0
- CSS: improvements to the deferring logic for non-aggregated CSS resources.
- Settings-page: Show "JS, CSS & HTML" advanced options by default (many people did not see the button)
Download this release
Release Info
Developer | futtta |
Plugin | Autoptimize |
Version | 2.5.1 |
Comparing to | |
See all releases |
Code changes from version 2.5.0 to 2.5.1
- autoptimize.php +2 -2
- classes/autoptimizeBase.php +3 -0
- classes/autoptimizeConfig.php +5 -6
- classes/autoptimizeExtra.php +4 -2
- classes/autoptimizeHTML.php +3 -0
- classes/autoptimizeImages.php +118 -65
- classes/autoptimizeMain.php +2 -2
- classes/autoptimizeScripts.php +1 -0
- classes/autoptimizeStyles.php +21 -14
- classes/autoptimizeUtils.php +5 -2
- classes/autoptimizeVersionUpdatesHandler.php +10 -6
- classes/external/js/lazysizes.min.js +2 -2
- classes/external/php/minify-html.php +3 -0
- readme.txt +13 -14
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.5.
|
7 |
Author: Frank Goossens (futtta)
|
8 |
Author URI: https://autoptimize.com/
|
9 |
Text Domain: autoptimize
|
@@ -20,7 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
20 |
exit;
|
21 |
}
|
22 |
|
23 |
-
define( 'AUTOPTIMIZE_PLUGIN_VERSION', '2.5.
|
24 |
|
25 |
// plugin_dir_path() returns the trailing slash!
|
26 |
define( 'AUTOPTIMIZE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
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.5.1
|
7 |
Author: Frank Goossens (futtta)
|
8 |
Author URI: https://autoptimize.com/
|
9 |
Text Domain: autoptimize
|
20 |
exit;
|
21 |
}
|
22 |
|
23 |
+
define( 'AUTOPTIMIZE_PLUGIN_VERSION', '2.5.1' );
|
24 |
|
25 |
// plugin_dir_path() returns the trailing slash!
|
26 |
define( 'AUTOPTIMIZE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
classes/autoptimizeBase.php
CHANGED
@@ -23,6 +23,9 @@ abstract class autoptimizeBase
|
|
23 |
*/
|
24 |
public $debug_log = false;
|
25 |
|
|
|
|
|
|
|
26 |
public function __construct( $content )
|
27 |
{
|
28 |
$this->content = $content;
|
23 |
*/
|
24 |
public $debug_log = false;
|
25 |
|
26 |
+
/** @var string */
|
27 |
+
public $cdn_url = '';
|
28 |
+
|
29 |
public function __construct( $content )
|
30 |
{
|
31 |
$this->content = $content;
|
classes/autoptimizeConfig.php
CHANGED
@@ -188,7 +188,7 @@ input[type=url]:invalid {color: red; border-color:red;} .form-table th{font-weig
|
|
188 |
<div id="ao_title_and_button">
|
189 |
<h1 id="ao_title"><?php _e( 'Autoptimize Settings', 'autoptimize' ); ?>
|
190 |
<span id="ao_adv_button">
|
191 |
-
<?php if ( get_option( 'autoptimize_show_adv', '
|
192 |
<a href="javascript:void(0);" id="ao_show_adv" class="button" style="display:none;"><span><?php _e("Show advanced settings","autoptimize") ?></span></a>
|
193 |
<a href="javascript:void(0);" id="ao_hide_adv" class="button"><span><?php _e("Hide advanced settings","autoptimize") ?></span></a>
|
194 |
<style>tr.ao_adv{display:table-row;} li.ao_adv{display:list-item;}</style>
|
@@ -403,7 +403,7 @@ if ( function_exists( 'is_plugin_active' ) && ! is_plugin_active( 'autoptimize-c
|
|
403 |
|
404 |
</ul>
|
405 |
|
406 |
-
<input type="hidden" id="autoptimize_show_adv" name="autoptimize_show_adv" value="<?php echo get_option('autoptimize_show_adv','
|
407 |
|
408 |
<p class="submit">
|
409 |
<input type="submit" class="button-secondary" value="<?php _e('Save Changes','autoptimize') ?>" />
|
@@ -722,7 +722,7 @@ if ( function_exists( 'is_plugin_active' ) && ! is_plugin_active( 'autoptimize-c
|
|
722 |
'autoptimize_css_datauris' => 0,
|
723 |
'autoptimize_cdn_url' => '',
|
724 |
'autoptimize_cache_nogzip' => 1,
|
725 |
-
'autoptimize_show_adv' =>
|
726 |
'autoptimize_optimize_logged' => 1,
|
727 |
'autoptimize_optimize_checkout' => 1,
|
728 |
'autoptimize_minify_excluded' => 1,
|
@@ -884,14 +884,13 @@ if ( function_exists( 'is_plugin_active' ) && ! is_plugin_active( 'autoptimize-c
|
|
884 |
/**
|
885 |
* Returns true if doing ajax.
|
886 |
*
|
887 |
-
* @return
|
888 |
*/
|
889 |
protected static function doing_ajax()
|
890 |
{
|
891 |
if ( function_exists( 'wp_doing_ajax' ) ) {
|
892 |
return wp_doing_ajax();
|
893 |
-
} else {
|
894 |
-
return ( defined( 'DOING_AJAX' ) && DOING_AJAX );
|
895 |
}
|
|
|
896 |
}
|
897 |
}
|
188 |
<div id="ao_title_and_button">
|
189 |
<h1 id="ao_title"><?php _e( 'Autoptimize Settings', 'autoptimize' ); ?>
|
190 |
<span id="ao_adv_button">
|
191 |
+
<?php if ( get_option( 'autoptimize_show_adv', '1' ) == '1' ) { ?>
|
192 |
<a href="javascript:void(0);" id="ao_show_adv" class="button" style="display:none;"><span><?php _e("Show advanced settings","autoptimize") ?></span></a>
|
193 |
<a href="javascript:void(0);" id="ao_hide_adv" class="button"><span><?php _e("Hide advanced settings","autoptimize") ?></span></a>
|
194 |
<style>tr.ao_adv{display:table-row;} li.ao_adv{display:list-item;}</style>
|
403 |
|
404 |
</ul>
|
405 |
|
406 |
+
<input type="hidden" id="autoptimize_show_adv" name="autoptimize_show_adv" value="<?php echo get_option('autoptimize_show_adv','1'); ?>">
|
407 |
|
408 |
<p class="submit">
|
409 |
<input type="submit" class="button-secondary" value="<?php _e('Save Changes','autoptimize') ?>" />
|
722 |
'autoptimize_css_datauris' => 0,
|
723 |
'autoptimize_cdn_url' => '',
|
724 |
'autoptimize_cache_nogzip' => 1,
|
725 |
+
'autoptimize_show_adv' => 1,
|
726 |
'autoptimize_optimize_logged' => 1,
|
727 |
'autoptimize_optimize_checkout' => 1,
|
728 |
'autoptimize_minify_excluded' => 1,
|
884 |
/**
|
885 |
* Returns true if doing ajax.
|
886 |
*
|
887 |
+
* @return bool
|
888 |
*/
|
889 |
protected static function doing_ajax()
|
890 |
{
|
891 |
if ( function_exists( 'wp_doing_ajax' ) ) {
|
892 |
return wp_doing_ajax();
|
|
|
|
|
893 |
}
|
894 |
+
return ( defined( 'DOING_AJAX' ) && DOING_AJAX );
|
895 |
}
|
896 |
}
|
classes/autoptimizeExtra.php
CHANGED
@@ -155,7 +155,9 @@ class autoptimizeExtra
|
|
155 |
|
156 |
public function filter_remove_dns_prefetch( $urls, $relation_type, $url_to_remove )
|
157 |
{
|
158 |
-
|
|
|
|
|
159 |
$cnt = 0;
|
160 |
foreach ( $urls as $url ) {
|
161 |
if ( false !== strpos( $url, $url_to_remove ) ) {
|
@@ -227,7 +229,7 @@ class autoptimizeExtra
|
|
227 |
$fonts_string = $fonts_string . '&subset=' . $subset_string;
|
228 |
}
|
229 |
|
230 |
-
$fonts_string = str_replace( '|', '%7C', ltrim( $fonts_string, '|' ) );
|
231 |
|
232 |
if ( ! empty( $fonts_string ) ) {
|
233 |
if ( '5' === $options['autoptimize_extra_radio_field_4'] ) {
|
155 |
|
156 |
public function filter_remove_dns_prefetch( $urls, $relation_type, $url_to_remove )
|
157 |
{
|
158 |
+
$url_to_remove = (string) $url_to_remove;
|
159 |
+
|
160 |
+
if ( ! empty( $url_to_remove ) && 'dns-prefetch' === $relation_type ) {
|
161 |
$cnt = 0;
|
162 |
foreach ( $urls as $url ) {
|
163 |
if ( false !== strpos( $url, $url_to_remove ) ) {
|
229 |
$fonts_string = $fonts_string . '&subset=' . $subset_string;
|
230 |
}
|
231 |
|
232 |
+
$fonts_string = apply_filters( 'autoptimize_filter_extra_gfont_fontstring', str_replace( '|', '%7C', ltrim( $fonts_string, '|' ) ) );
|
233 |
|
234 |
if ( ! empty( $fonts_string ) ) {
|
235 |
if ( '5' === $options['autoptimize_extra_radio_field_4'] ) {
|
classes/autoptimizeHTML.php
CHANGED
@@ -16,6 +16,9 @@ class autoptimizeHTML extends autoptimizeBase
|
|
16 |
*/
|
17 |
private $keepcomments = false;
|
18 |
|
|
|
|
|
|
|
19 |
/**
|
20 |
* Things to exclude from being minifed.
|
21 |
*
|
16 |
*/
|
17 |
private $keepcomments = false;
|
18 |
|
19 |
+
/** @var bool */
|
20 |
+
private $forcexhtml = false;
|
21 |
+
|
22 |
/**
|
23 |
* Things to exclude from being minifed.
|
24 |
*
|
classes/autoptimizeImages.php
CHANGED
@@ -200,6 +200,7 @@ class autoptimizeImages
|
|
200 |
if ( ! empty( $avail_imgopt ) && array_key_exists( 'hosts', $avail_imgopt ) && is_array( $avail_imgopt['hosts'] ) ) {
|
201 |
$imgopt_host = array_rand( array_flip( $avail_imgopt['hosts'] ) );
|
202 |
}
|
|
|
203 |
}
|
204 |
|
205 |
return $imgopt_host;
|
@@ -326,16 +327,12 @@ class autoptimizeImages
|
|
326 |
// Do the work on cache miss only.
|
327 |
if ( ! isset( $cache[ $in ] ) ) {
|
328 |
// Default to what was given to us.
|
329 |
-
$result = $in;
|
330 |
if ( autoptimizeUtils::is_protocol_relative( $in ) ) {
|
331 |
$result = $parsed_site_url['scheme'] . ':' . $in;
|
332 |
} elseif ( 0 === strpos( $in, '/' ) ) {
|
333 |
// Root-relative...
|
334 |
-
$result
|
335 |
-
// Add the path for subfolder installs.
|
336 |
-
if ( isset( $parsed_site_url['path'] ) ) {
|
337 |
-
$result .= $parsed_site_url['path'];
|
338 |
-
}
|
339 |
$result .= $in;
|
340 |
} elseif ( ! empty( $cdn_domain ) && strpos( $in, $cdn_domain ) !== 0 ) {
|
341 |
$result = str_replace( $cdn_domain, $parsed_site_url['host'], $in );
|
@@ -464,8 +461,9 @@ class autoptimizeImages
|
|
464 |
|
465 |
public function replace_img_callback( $matches, $width = 0, $height = 0 )
|
466 |
{
|
|
|
467 |
if ( $this->can_optimize_image( $matches[1] ) ) {
|
468 |
-
return str_replace( $matches[1], $this->build_imgopt_url( $
|
469 |
} else {
|
470 |
return $matches[0];
|
471 |
}
|
@@ -476,7 +474,6 @@ class autoptimizeImages
|
|
476 |
/*
|
477 |
* potential future functional improvements:
|
478 |
*
|
479 |
-
* picture element.
|
480 |
* filter for critical CSS.
|
481 |
*/
|
482 |
$to_replace = array();
|
@@ -484,9 +481,9 @@ class autoptimizeImages
|
|
484 |
// hide noscript tags to avoid nesting noscript tags (as lazyloaded images add noscript).
|
485 |
if ( $this->should_lazyload() ) {
|
486 |
$in = autoptimizeBase::replace_contents_with_marker_if_exists(
|
487 |
-
'
|
488 |
-
'<
|
489 |
-
'#<
|
490 |
$in
|
491 |
);
|
492 |
}
|
@@ -536,14 +533,8 @@ class autoptimizeImages
|
|
536 |
}
|
537 |
|
538 |
// do lazyload stuff.
|
539 |
-
if ( $this->should_lazyload(
|
540 |
-
|
541 |
-
$tag = str_replace( 'srcset=', 'data-srcset=', $tag );
|
542 |
-
|
543 |
-
// add lazyload class.
|
544 |
-
$tag = $this->inject_classes_in_tag( $tag, 'lazyload ' );
|
545 |
-
|
546 |
-
// set placeholder.
|
547 |
if ( strpos( $url, $this->get_imgopt_host() ) === 0 ) {
|
548 |
// if all img src have been replaced during srcset, we have to extract the
|
549 |
// origin url from the imgopt one to be able to set a lqip placeholder.
|
@@ -551,25 +542,23 @@ class autoptimizeImages
|
|
551 |
} else {
|
552 |
$_url = $url;
|
553 |
}
|
554 |
-
if ( $this->can_optimize_image( $_url ) && apply_filters( 'autoptimize_filter_imgopt_lazyload_dolqip', true ) ) {
|
555 |
-
$placeholder = $this->get_imgopt_host() . 'client/q_lqip,ret_wait,w_' . $imgopt_w . ',h_' . $imgopt_h . '/' . $_url;
|
556 |
-
} else {
|
557 |
-
$placeholder = $this->get_default_lazyload_placeholder( $imgopt_w, $imgopt_h );
|
558 |
-
}
|
559 |
-
$placeholder = ' src=\'' . apply_filters( 'autoptimize_filter_imgopt_lazyload_placeholder', $placeholder );
|
560 |
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
565 |
}
|
566 |
-
|
567 |
-
|
568 |
-
$tag = $noscript_tag . str_replace( ' src=', $min_height . $placeholder . '\' data-src=', $tag );
|
569 |
-
$tag = apply_filters( 'autoptimize_filter_imgopt_lazyloaded_img', $tag );
|
570 |
}
|
571 |
|
572 |
-
// add tag to array for later replacement.
|
573 |
if ( $tag !== $orig_tag ) {
|
574 |
$to_replace[ $orig_tag ] = $tag;
|
575 |
}
|
@@ -597,12 +586,16 @@ class autoptimizeImages
|
|
597 |
);
|
598 |
}
|
599 |
|
600 |
-
//
|
601 |
if ( $this->should_lazyload() ) {
|
602 |
$out = autoptimizeBase::restore_marked_content(
|
603 |
-
'
|
604 |
$out
|
605 |
);
|
|
|
|
|
|
|
|
|
606 |
}
|
607 |
|
608 |
return $out;
|
@@ -648,77 +641,92 @@ class autoptimizeImages
|
|
648 |
/**
|
649 |
* Lazyload functions
|
650 |
*/
|
651 |
-
public function
|
|
|
|
|
|
|
|
|
|
|
|
|
652 |
if ( ! empty( $this->options['autoptimize_imgopt_checkbox_field_3'] ) ) {
|
653 |
$lazyload_return = true;
|
654 |
} else {
|
655 |
$lazyload_return = false;
|
656 |
}
|
|
|
657 |
|
658 |
return $lazyload_return;
|
659 |
}
|
660 |
|
661 |
-
public static function should_lazyload_wrapper() {
|
662 |
-
// needed in autoptimizeMain.php.
|
663 |
-
$self = new self();
|
664 |
-
return $self->should_lazyload();
|
665 |
-
}
|
666 |
-
|
667 |
public function filter_lazyload_images( $in )
|
668 |
{
|
669 |
// only used is image optimization is NOT active but lazyload is.
|
670 |
$to_replace = array();
|
671 |
|
672 |
-
// hide
|
673 |
$out = autoptimizeBase::replace_contents_with_marker_if_exists(
|
674 |
-
'
|
675 |
-
'<
|
676 |
-
'#<
|
677 |
$in
|
678 |
);
|
679 |
|
680 |
// extract img tags and add lazyload attribs.
|
681 |
if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $out, $matches ) ) {
|
682 |
foreach ( $matches[0] as $tag ) {
|
683 |
-
|
|
|
|
|
684 |
}
|
685 |
$out = str_replace( array_keys( $to_replace ), array_values( $to_replace ), $out );
|
686 |
}
|
687 |
|
|
|
|
|
|
|
688 |
// restore noscript tags.
|
689 |
$out = autoptimizeBase::restore_marked_content(
|
690 |
-
'
|
691 |
$out
|
692 |
);
|
693 |
|
694 |
return $out;
|
695 |
}
|
696 |
|
697 |
-
public function add_lazyload( $tag ) {
|
698 |
// adds actual lazyload-attributes to an image node.
|
699 |
if ( str_ireplace( $this->get_lazyload_exclusions(), '', $tag ) === $tag ) {
|
|
|
|
|
700 |
// store original tag for use in noscript version.
|
701 |
$noscript_tag = '<noscript>' . $tag . '</noscript>';
|
702 |
|
703 |
// insert lazyload class.
|
704 |
$tag = $this->inject_classes_in_tag( $tag, 'lazyload ' );
|
705 |
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
715 |
}
|
|
|
|
|
716 |
|
717 |
-
//
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
$tag = str_replace( ' srcset=', ' data-srcset=', $tag );
|
722 |
|
723 |
// add the noscript-tag from earlier.
|
724 |
$tag = $noscript_tag . $tag;
|
@@ -756,7 +764,7 @@ class autoptimizeImages
|
|
756 |
$options = $this->options;
|
757 |
|
758 |
// set default exclusions.
|
759 |
-
$exclude_lazyload_array = array( 'skip-lazy', 'data-no-lazy', 'notlazy', 'data-src', 'data-srcset' );
|
760 |
|
761 |
// add from setting.
|
762 |
if ( array_key_exists( 'autoptimize_imgopt_text_field_5', $options ) ) {
|
@@ -802,6 +810,51 @@ class autoptimizeImages
|
|
802 |
return $webp_return;
|
803 |
}
|
804 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
805 |
/**
|
806 |
* Admin page logic and related functions below.
|
807 |
*/
|
200 |
if ( ! empty( $avail_imgopt ) && array_key_exists( 'hosts', $avail_imgopt ) && is_array( $avail_imgopt['hosts'] ) ) {
|
201 |
$imgopt_host = array_rand( array_flip( $avail_imgopt['hosts'] ) );
|
202 |
}
|
203 |
+
$imgopt_host = apply_filters( 'autoptimize_filter_imgopt_host', $imgopt_host );
|
204 |
}
|
205 |
|
206 |
return $imgopt_host;
|
327 |
// Do the work on cache miss only.
|
328 |
if ( ! isset( $cache[ $in ] ) ) {
|
329 |
// Default to what was given to us.
|
330 |
+
$result = trim( $in );
|
331 |
if ( autoptimizeUtils::is_protocol_relative( $in ) ) {
|
332 |
$result = $parsed_site_url['scheme'] . ':' . $in;
|
333 |
} elseif ( 0 === strpos( $in, '/' ) ) {
|
334 |
// Root-relative...
|
335 |
+
$result = $parsed_site_url['scheme'] . '://' . $parsed_site_url['host'];
|
|
|
|
|
|
|
|
|
336 |
$result .= $in;
|
337 |
} elseif ( ! empty( $cdn_domain ) && strpos( $in, $cdn_domain ) !== 0 ) {
|
338 |
$result = str_replace( $cdn_domain, $parsed_site_url['host'], $in );
|
461 |
|
462 |
public function replace_img_callback( $matches, $width = 0, $height = 0 )
|
463 |
{
|
464 |
+
$_normalized_img_url = $this->normalize_img_url( $matches[1] );
|
465 |
if ( $this->can_optimize_image( $matches[1] ) ) {
|
466 |
+
return str_replace( $matches[1], $this->build_imgopt_url( $_normalized_img_url, $width, $height ), $matches[0] );
|
467 |
} else {
|
468 |
return $matches[0];
|
469 |
}
|
474 |
/*
|
475 |
* potential future functional improvements:
|
476 |
*
|
|
|
477 |
* filter for critical CSS.
|
478 |
*/
|
479 |
$to_replace = array();
|
481 |
// hide noscript tags to avoid nesting noscript tags (as lazyloaded images add noscript).
|
482 |
if ( $this->should_lazyload() ) {
|
483 |
$in = autoptimizeBase::replace_contents_with_marker_if_exists(
|
484 |
+
'SCRIPT',
|
485 |
+
'<script',
|
486 |
+
'#<(?:no)?script.*?<\/(?:no)?script>#is',
|
487 |
$in
|
488 |
);
|
489 |
}
|
533 |
}
|
534 |
|
535 |
// do lazyload stuff.
|
536 |
+
if ( $this->should_lazyload( $in ) ) {
|
537 |
+
// first do lpiq placeholder logic.
|
|
|
|
|
|
|
|
|
|
|
|
|
538 |
if ( strpos( $url, $this->get_imgopt_host() ) === 0 ) {
|
539 |
// if all img src have been replaced during srcset, we have to extract the
|
540 |
// origin url from the imgopt one to be able to set a lqip placeholder.
|
542 |
} else {
|
543 |
$_url = $url;
|
544 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
545 |
|
546 |
+
if ( $this->can_optimize_image( $_url ) && apply_filters( 'autoptimize_filter_imgopt_lazyload_dolqip', true ) ) {
|
547 |
+
$lqip_w = '';
|
548 |
+
$lqip_h = '';
|
549 |
+
if ( isset( $imgopt_w ) && ! empty( $imgopt_w ) ) {
|
550 |
+
$lqip_w = ',w_' . $imgopt_w;
|
551 |
+
}
|
552 |
+
if ( isset( $imgopt_h ) && ! empty( $imgopt_h ) ) {
|
553 |
+
$lqip_h = ',h_' . $imgopt_h;
|
554 |
+
}
|
555 |
+
$placeholder = $this->get_imgopt_host() . 'client/q_lqip,ret_wait' . $lqip_w . $lqip_h . '/' . $_url;
|
556 |
}
|
557 |
+
// then call add_lazyload-function with lpiq placeholder if set.
|
558 |
+
$tag = $this->add_lazyload( $tag, $placeholder );
|
|
|
|
|
559 |
}
|
560 |
|
561 |
+
// and add tag to array for later replacement.
|
562 |
if ( $tag !== $orig_tag ) {
|
563 |
$to_replace[ $orig_tag ] = $tag;
|
564 |
}
|
586 |
);
|
587 |
}
|
588 |
|
589 |
+
// lazyload: restore noscript tags + lazyload picture source tags.
|
590 |
if ( $this->should_lazyload() ) {
|
591 |
$out = autoptimizeBase::restore_marked_content(
|
592 |
+
'SCRIPT',
|
593 |
$out
|
594 |
);
|
595 |
+
|
596 |
+
$out = $this->process_picture_tag( $out, true, true );
|
597 |
+
} else {
|
598 |
+
$out = $this->process_picture_tag( $out, true, false );
|
599 |
}
|
600 |
|
601 |
return $out;
|
641 |
/**
|
642 |
* Lazyload functions
|
643 |
*/
|
644 |
+
public static function should_lazyload_wrapper() {
|
645 |
+
// needed in autoptimizeMain.php.
|
646 |
+
$self = new self();
|
647 |
+
return $self->should_lazyload();
|
648 |
+
}
|
649 |
+
|
650 |
+
public function should_lazyload( $context = '' ) {
|
651 |
if ( ! empty( $this->options['autoptimize_imgopt_checkbox_field_3'] ) ) {
|
652 |
$lazyload_return = true;
|
653 |
} else {
|
654 |
$lazyload_return = false;
|
655 |
}
|
656 |
+
$lazyload_return = apply_filters( 'autoptimize_filter_imgopt_should_lazyload', $lazyload_return, $context );
|
657 |
|
658 |
return $lazyload_return;
|
659 |
}
|
660 |
|
|
|
|
|
|
|
|
|
|
|
|
|
661 |
public function filter_lazyload_images( $in )
|
662 |
{
|
663 |
// only used is image optimization is NOT active but lazyload is.
|
664 |
$to_replace = array();
|
665 |
|
666 |
+
// hide (no)script tags to avoid nesting noscript tags (as lazyloaded images add noscript).
|
667 |
$out = autoptimizeBase::replace_contents_with_marker_if_exists(
|
668 |
+
'SCRIPT',
|
669 |
+
'<script',
|
670 |
+
'#<(?:no)?script.*?<\/(?:no)?script>#is',
|
671 |
$in
|
672 |
);
|
673 |
|
674 |
// extract img tags and add lazyload attribs.
|
675 |
if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $out, $matches ) ) {
|
676 |
foreach ( $matches[0] as $tag ) {
|
677 |
+
if ( $this->should_lazyload( $out ) ) {
|
678 |
+
$to_replace[ $tag ] = $this->add_lazyload( $tag );
|
679 |
+
}
|
680 |
}
|
681 |
$out = str_replace( array_keys( $to_replace ), array_values( $to_replace ), $out );
|
682 |
}
|
683 |
|
684 |
+
// and also lazyload picture tag.
|
685 |
+
$out = $this->process_picture_tag( $out, false, true );
|
686 |
+
|
687 |
// restore noscript tags.
|
688 |
$out = autoptimizeBase::restore_marked_content(
|
689 |
+
'SCRIPT',
|
690 |
$out
|
691 |
);
|
692 |
|
693 |
return $out;
|
694 |
}
|
695 |
|
696 |
+
public function add_lazyload( $tag, $placeholder = '' ) {
|
697 |
// adds actual lazyload-attributes to an image node.
|
698 |
if ( str_ireplace( $this->get_lazyload_exclusions(), '', $tag ) === $tag ) {
|
699 |
+
$tag = $this->maybe_fix_missing_quotes( $tag );
|
700 |
+
|
701 |
// store original tag for use in noscript version.
|
702 |
$noscript_tag = '<noscript>' . $tag . '</noscript>';
|
703 |
|
704 |
// insert lazyload class.
|
705 |
$tag = $this->inject_classes_in_tag( $tag, 'lazyload ' );
|
706 |
|
707 |
+
if ( ! $placeholder || empty( $placeholder ) ) {
|
708 |
+
// get image width & heigth for placeholder fun (and to prevent content reflow).
|
709 |
+
$_get_size = $this->get_size_from_tag( $tag );
|
710 |
+
$width = $_get_size['width'];
|
711 |
+
$height = $_get_size['height'];
|
712 |
+
if ( false === $width ) {
|
713 |
+
$widht = 210; // default width for SVG placeholder.
|
714 |
+
}
|
715 |
+
if ( false === $height ) {
|
716 |
+
$heigth = $width / 3 * 2; // if no height, base it on width using the 3/2 aspect ratio.
|
717 |
+
}
|
718 |
+
|
719 |
+
// insert the actual lazyload stuff.
|
720 |
+
// see https://css-tricks.com/preventing-content-reflow-from-lazy-loaded-images/ for great read on why we're using empty svg's.
|
721 |
+
$placeholder = apply_filters( 'autoptimize_filter_imgopt_lazyload_placeholder', $this->get_default_lazyload_placeholder( $width, $height ) );
|
722 |
}
|
723 |
+
$tag = str_replace( ' src=', ' src=\'' . $placeholder . '\' data-src=', $tag );
|
724 |
+
$tag = str_replace( ' srcset=', ' data-srcset=', $tag );
|
725 |
|
726 |
+
// move sizes to data-sizes unless filter says no.
|
727 |
+
if ( apply_filters( 'autoptimize_filter_imgopt_lazyload_move_sizes', true ) ) {
|
728 |
+
$tag = str_replace( 'sizes=', 'data-sizes=', $tag );
|
729 |
+
}
|
|
|
730 |
|
731 |
// add the noscript-tag from earlier.
|
732 |
$tag = $noscript_tag . $tag;
|
764 |
$options = $this->options;
|
765 |
|
766 |
// set default exclusions.
|
767 |
+
$exclude_lazyload_array = array( 'skip-lazy', 'data-no-lazy', 'notlazy', 'data-src', 'data-srcset', 'data:image/', 'data-lazyload', 'rev-slidebg' );
|
768 |
|
769 |
// add from setting.
|
770 |
if ( array_key_exists( 'autoptimize_imgopt_text_field_5', $options ) ) {
|
810 |
return $webp_return;
|
811 |
}
|
812 |
|
813 |
+
public function process_picture_tag( $in, $imgopt = false, $lazy = false ) {
|
814 |
+
// check if "<picture" is present and if filter allows us to process <picture>.
|
815 |
+
if ( strpos( $in, '<picture' ) === false || apply_filters( 'autoptimize_filter_imgopt_dopicture', true ) === false ) {
|
816 |
+
return $in;
|
817 |
+
}
|
818 |
+
|
819 |
+
$_exclusions = $this->get_lazyload_exclusions();
|
820 |
+
$to_replace_pict = array();
|
821 |
+
|
822 |
+
// extract and process each picture-node.
|
823 |
+
preg_match_all( '#<picture.*</picture>#Usmi', $in, $_pictures, PREG_SET_ORDER );
|
824 |
+
foreach ( $_pictures as $_picture ) {
|
825 |
+
$_picture = $this->maybe_fix_missing_quotes( $_picture );
|
826 |
+
if ( strpos( $_picture[0], '<source ' ) !== false && preg_match_all( '#<source .*srcset=(?:"|\')(?!data)(.*)(?:"|\').*>#Usmi', $_picture[0], $_sources, PREG_SET_ORDER ) !== false ) {
|
827 |
+
foreach ( $_sources as $_source ) {
|
828 |
+
$_picture_replacement = $_source[0];
|
829 |
+
|
830 |
+
// should we optimize the image?
|
831 |
+
if ( $imgopt && $this->can_optimize_image( $_source[1] ) ) {
|
832 |
+
$_picture_replacement = str_replace( $_source[1], $this->build_imgopt_url( $_source[1] ), $_picture_replacement );
|
833 |
+
}
|
834 |
+
// should we lazy-load?
|
835 |
+
if ( $lazy && str_ireplace( $_exclusions, '', $_picture_replacement ) === $_picture_replacement ) {
|
836 |
+
$_picture_replacement = str_replace( ' srcset=', ' data-srcset=', $_picture_replacement );
|
837 |
+
}
|
838 |
+
$to_replace_pict[ $_source[0] ] = $_picture_replacement;
|
839 |
+
}
|
840 |
+
}
|
841 |
+
}
|
842 |
+
|
843 |
+
// and return the fully procesed $in.
|
844 |
+
$out = str_replace( array_keys( $to_replace_pict ), array_values( $to_replace_pict ), $in );
|
845 |
+
|
846 |
+
return $out;
|
847 |
+
}
|
848 |
+
|
849 |
+
public function maybe_fix_missing_quotes( $tag_in ) {
|
850 |
+
// W3TC's Minify_HTML class removes quotes around attribute value, this re-adds them.
|
851 |
+
if ( file_exists( WP_PLUGIN_DIR . '/w3-total-cache/w3-total-cache.php' ) && class_exists( 'Minify_HTML' ) && apply_filters( 'autoptimize_filter_imgopt_fixquotes', true ) ) {
|
852 |
+
return preg_replace( '/=([^("|\')]*)(\s|>)/U', '=\'$1\'$2', $tag_in );
|
853 |
+
} else {
|
854 |
+
return $tag_in;
|
855 |
+
}
|
856 |
+
}
|
857 |
+
|
858 |
/**
|
859 |
* Admin page logic and related functions below.
|
860 |
*/
|
classes/autoptimizeMain.php
CHANGED
@@ -108,7 +108,7 @@ class autoptimizeMain
|
|
108 |
}
|
109 |
}
|
110 |
if ( ! defined( 'AUTOPTIMIZE_WP_CONTENT_URL' ) ) {
|
111 |
-
if ( function_exists( '
|
112 |
define( 'AUTOPTIMIZE_WP_CONTENT_URL', str_replace( get_original_url( AUTOPTIMIZE_WP_SITE_URL ), AUTOPTIMIZE_WP_SITE_URL, content_url() ) );
|
113 |
} else {
|
114 |
define( 'AUTOPTIMIZE_WP_CONTENT_URL', content_url() );
|
@@ -136,7 +136,7 @@ class autoptimizeMain
|
|
136 |
// Also requires 'mbstring' extension.
|
137 |
$with_mbstring = apply_filters( 'autoptimize_filter_main_use_mbstring', false );
|
138 |
if ( $with_mbstring ) {
|
139 |
-
autoptimizeUtils::mbstring_available( \
|
140 |
} else {
|
141 |
autoptimizeUtils::mbstring_available( false );
|
142 |
}
|
108 |
}
|
109 |
}
|
110 |
if ( ! defined( 'AUTOPTIMIZE_WP_CONTENT_URL' ) ) {
|
111 |
+
if ( function_exists( 'get_original_url' ) ) {
|
112 |
define( 'AUTOPTIMIZE_WP_CONTENT_URL', str_replace( get_original_url( AUTOPTIMIZE_WP_SITE_URL ), AUTOPTIMIZE_WP_SITE_URL, content_url() ) );
|
113 |
} else {
|
114 |
define( 'AUTOPTIMIZE_WP_CONTENT_URL', content_url() );
|
136 |
// Also requires 'mbstring' extension.
|
137 |
$with_mbstring = apply_filters( 'autoptimize_filter_main_use_mbstring', false );
|
138 |
if ( $with_mbstring ) {
|
139 |
+
autoptimizeUtils::mbstring_available( \extension_loaded( 'mbstring' ) );
|
140 |
} else {
|
141 |
autoptimizeUtils::mbstring_available( false );
|
142 |
}
|
classes/autoptimizeScripts.php
CHANGED
@@ -26,6 +26,7 @@ class autoptimizeScripts extends autoptimizeBase
|
|
26 |
'addthis.com','/afsonline/show_afs_search.js','disqus.js','networkedblogs.com/getnetworkwidget','infolinks.com/js/',
|
27 |
'jd.gallery.js.php','jd.gallery.transitions.js','swfobject.embedSWF(','linkwithin.com/widget.js','tiny_mce.js','tinyMCEPreInit.go'
|
28 |
);
|
|
|
29 |
|
30 |
private $aggregate = true;
|
31 |
private $trycatch = false;
|
26 |
'addthis.com','/afsonline/show_afs_search.js','disqus.js','networkedblogs.com/getnetworkwidget','infolinks.com/js/',
|
27 |
'jd.gallery.js.php','jd.gallery.transitions.js','swfobject.embedSWF(','linkwithin.com/widget.js','tiny_mce.js','tinyMCEPreInit.go'
|
28 |
);
|
29 |
+
public $cdn_url = '';
|
30 |
|
31 |
private $aggregate = true;
|
32 |
private $trycatch = false;
|
classes/autoptimizeStyles.php
CHANGED
@@ -44,6 +44,8 @@ class autoptimizeStyles extends autoptimizeBase
|
|
44 |
private $cssremovables = array();
|
45 |
private $include_inline = false;
|
46 |
private $inject_min_late = '';
|
|
|
|
|
47 |
private $minify_excluded = true;
|
48 |
|
49 |
// public $cdn_url; // Used all over the place implicitly, so will have to be either public or protected :/ .
|
@@ -183,7 +185,7 @@ class autoptimizeStyles extends autoptimizeBase
|
|
183 |
} else {
|
184 |
// Link is dynamic (.php etc).
|
185 |
$new_tag = $this->optionally_defer_excluded( $tag, 'none' );
|
186 |
-
if ( $new_tag !== $tag ) {
|
187 |
$this->content = str_replace( $tag, $new_tag, $this->content );
|
188 |
}
|
189 |
$tag = '';
|
@@ -207,14 +209,15 @@ class autoptimizeStyles extends autoptimizeBase
|
|
207 |
// Remove the original style tag.
|
208 |
$this->content = str_replace( $tag, '', $this->content );
|
209 |
} else {
|
210 |
-
// Excluded CSS, minify that file:
|
211 |
-
// -> if aggregate is on and exclude minify is on
|
212 |
-
// -> if aggregate is off and the file is not in dontmove.
|
213 |
if ( preg_match( '#<link.*href=("|\')(.*)("|\')#Usmi', $tag, $source ) ) {
|
214 |
$exploded_url = explode( '?', $source[2], 2 );
|
215 |
$url = $exploded_url[0];
|
216 |
$path = $this->getpath( $url );
|
|
|
217 |
|
|
|
|
|
|
|
218 |
if ( $path && ( $this->minify_excluded || apply_filters( 'autoptimize_filter_css_minify_excluded', false, $url ) ) ) {
|
219 |
$consider_minified_array = apply_filters( 'autoptimize_filter_css_consider_minified', false );
|
220 |
if ( ( false === $this->aggregate && str_replace( $this->dontmove, '', $path ) === $path ) || ( true === $this->aggregate && ( false === $consider_minified_array || str_replace( $consider_minified_array, '', $path ) === $path ) ) ) {
|
@@ -222,15 +225,16 @@ class autoptimizeStyles extends autoptimizeBase
|
|
222 |
if ( ! empty( $minified_url ) ) {
|
223 |
// Replace orig URL with cached minified URL.
|
224 |
$new_tag = str_replace( $url, $minified_url, $tag );
|
225 |
-
} else {
|
226 |
-
$new_tag = $tag;
|
227 |
}
|
|
|
|
|
228 |
|
229 |
-
|
|
|
230 |
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
}
|
235 |
}
|
236 |
}
|
@@ -246,12 +250,12 @@ class autoptimizeStyles extends autoptimizeBase
|
|
246 |
* Checks if non-optimized CSS is to be preloaded and if so return
|
247 |
* the tag with preload code.
|
248 |
*
|
249 |
-
* @param string $
|
250 |
* @param string $url (optional).
|
251 |
*
|
252 |
* @return string $new_tag
|
253 |
*/
|
254 |
-
private function optionally_defer_excluded( $
|
255 |
{
|
256 |
// Defer single CSS if "inline & defer" is ON and there is inline CSS.
|
257 |
if ( $this->defer && ! empty( $this->defer_inline ) ) {
|
@@ -262,15 +266,18 @@ class autoptimizeStyles extends autoptimizeBase
|
|
262 |
$url
|
263 |
);
|
264 |
// Adapt original <link> element for CSS to be preloaded and add <noscript>-version for fallback.
|
265 |
-
$new_tag = '<noscript>' . $
|
266 |
array(
|
267 |
"rel='stylesheet'",
|
268 |
'rel="stylesheet"',
|
269 |
),
|
270 |
"rel='preload' as='style' onload=\"" . $_preload_onload . "\"",
|
271 |
-
$
|
272 |
);
|
|
|
|
|
273 |
}
|
|
|
274 |
return $new_tag;
|
275 |
}
|
276 |
|
44 |
private $cssremovables = array();
|
45 |
private $include_inline = false;
|
46 |
private $inject_min_late = '';
|
47 |
+
private $dontmove = array();
|
48 |
+
private $options = array();
|
49 |
private $minify_excluded = true;
|
50 |
|
51 |
// public $cdn_url; // Used all over the place implicitly, so will have to be either public or protected :/ .
|
185 |
} else {
|
186 |
// Link is dynamic (.php etc).
|
187 |
$new_tag = $this->optionally_defer_excluded( $tag, 'none' );
|
188 |
+
if ( $new_tag !== '' && $new_tag !== $tag ) {
|
189 |
$this->content = str_replace( $tag, $new_tag, $this->content );
|
190 |
}
|
191 |
$tag = '';
|
209 |
// Remove the original style tag.
|
210 |
$this->content = str_replace( $tag, '', $this->content );
|
211 |
} else {
|
|
|
|
|
|
|
212 |
if ( preg_match( '#<link.*href=("|\')(.*)("|\')#Usmi', $tag, $source ) ) {
|
213 |
$exploded_url = explode( '?', $source[2], 2 );
|
214 |
$url = $exploded_url[0];
|
215 |
$path = $this->getpath( $url );
|
216 |
+
$new_tag = $tag;
|
217 |
|
218 |
+
// Excluded CSS, minify that file:
|
219 |
+
// -> if aggregate is on and exclude minify is on
|
220 |
+
// -> if aggregate is off and the file is not in dontmove.
|
221 |
if ( $path && ( $this->minify_excluded || apply_filters( 'autoptimize_filter_css_minify_excluded', false, $url ) ) ) {
|
222 |
$consider_minified_array = apply_filters( 'autoptimize_filter_css_consider_minified', false );
|
223 |
if ( ( false === $this->aggregate && str_replace( $this->dontmove, '', $path ) === $path ) || ( true === $this->aggregate && ( false === $consider_minified_array || str_replace( $consider_minified_array, '', $path ) === $path ) ) ) {
|
225 |
if ( ! empty( $minified_url ) ) {
|
226 |
// Replace orig URL with cached minified URL.
|
227 |
$new_tag = str_replace( $url, $minified_url, $tag );
|
|
|
|
|
228 |
}
|
229 |
+
}
|
230 |
+
}
|
231 |
|
232 |
+
// Optionally defer (preload) non-aggregated CSS.
|
233 |
+
$new_tag = $this->optionally_defer_excluded( $new_tag, $url );
|
234 |
|
235 |
+
// And replace!
|
236 |
+
if ( $new_tag !== '' && $new_tag !== $tag ) {
|
237 |
+
$this->content = str_replace( $tag, $new_tag, $this->content );
|
238 |
}
|
239 |
}
|
240 |
}
|
250 |
* Checks if non-optimized CSS is to be preloaded and if so return
|
251 |
* the tag with preload code.
|
252 |
*
|
253 |
+
* @param string $tag (required).
|
254 |
* @param string $url (optional).
|
255 |
*
|
256 |
* @return string $new_tag
|
257 |
*/
|
258 |
+
private function optionally_defer_excluded( $tag, $url = '' )
|
259 |
{
|
260 |
// Defer single CSS if "inline & defer" is ON and there is inline CSS.
|
261 |
if ( $this->defer && ! empty( $this->defer_inline ) ) {
|
266 |
$url
|
267 |
);
|
268 |
// Adapt original <link> element for CSS to be preloaded and add <noscript>-version for fallback.
|
269 |
+
$new_tag = '<noscript>' . $tag . '</noscript>' . str_replace(
|
270 |
array(
|
271 |
"rel='stylesheet'",
|
272 |
'rel="stylesheet"',
|
273 |
),
|
274 |
"rel='preload' as='style' onload=\"" . $_preload_onload . "\"",
|
275 |
+
$tag
|
276 |
);
|
277 |
+
} else {
|
278 |
+
$new_tag = $tag;
|
279 |
}
|
280 |
+
|
281 |
return $new_tag;
|
282 |
}
|
283 |
|
classes/autoptimizeUtils.php
CHANGED
@@ -45,7 +45,7 @@ class autoptimizeUtils
|
|
45 |
public static function strpos( $haystack, $needle, $offset = 0, $encoding = null )
|
46 |
{
|
47 |
if ( self::mbstring_available() ) {
|
48 |
-
return ( null === $encoding ) ? \mb_strpos( $haystack, $needle, $offset ) : \
|
49 |
} else {
|
50 |
return \strpos( $haystack, $needle, $offset );
|
51 |
}
|
@@ -301,9 +301,11 @@ class autoptimizeUtils
|
|
301 |
/**
|
302 |
* Checks to see if 3rd party services are available and stores result in option
|
303 |
*
|
|
|
|
|
304 |
* @param string $return_result should we return resulting service status array (default no).
|
305 |
*
|
306 |
-
* @return
|
307 |
*/
|
308 |
public static function check_service_availability( $return_result = false )
|
309 |
{
|
@@ -319,6 +321,7 @@ class autoptimizeUtils
|
|
319 |
}
|
320 |
}
|
321 |
}
|
|
|
322 |
}
|
323 |
|
324 |
/**
|
45 |
public static function strpos( $haystack, $needle, $offset = 0, $encoding = null )
|
46 |
{
|
47 |
if ( self::mbstring_available() ) {
|
48 |
+
return ( null === $encoding ) ? \mb_strpos( $haystack, $needle, $offset ) : \mb_strpos( $haystack, $needle, $offset, $encoding );
|
49 |
} else {
|
50 |
return \strpos( $haystack, $needle, $offset );
|
51 |
}
|
301 |
/**
|
302 |
* Checks to see if 3rd party services are available and stores result in option
|
303 |
*
|
304 |
+
* TODO This should be two separate methods.
|
305 |
+
*
|
306 |
* @param string $return_result should we return resulting service status array (default no).
|
307 |
*
|
308 |
+
* @return null|array Service status or null.
|
309 |
*/
|
310 |
public static function check_service_availability( $return_result = false )
|
311 |
{
|
321 |
}
|
322 |
}
|
323 |
}
|
324 |
+
return null;
|
325 |
}
|
326 |
|
327 |
/**
|
classes/autoptimizeVersionUpdatesHandler.php
CHANGED
@@ -236,12 +236,16 @@ class autoptimizeVersionUpdatesHandler
|
|
236 |
* Migrate imgopt options from autoptimize_extra_settings to autoptimize_imgopt_settings
|
237 |
*/
|
238 |
private function upgrade_from_2_4() {
|
239 |
-
$extra_settings = get_option( 'autoptimize_extra_settings' );
|
240 |
-
$imgopt_settings = get_option( 'autoptimize_imgopt_settings' );
|
241 |
-
if ( empty( $imgopt_settings ) ) {
|
242 |
-
$imgopt_settings
|
243 |
-
|
244 |
-
|
|
|
|
|
|
|
|
|
245 |
update_option( 'autoptimize_imgopt_settings', $imgopt_settings );
|
246 |
}
|
247 |
}
|
236 |
* Migrate imgopt options from autoptimize_extra_settings to autoptimize_imgopt_settings
|
237 |
*/
|
238 |
private function upgrade_from_2_4() {
|
239 |
+
$extra_settings = get_option( 'autoptimize_extra_settings', '' );
|
240 |
+
$imgopt_settings = get_option( 'autoptimize_imgopt_settings', '' );
|
241 |
+
if ( empty( $imgopt_settings ) && ! empty( $extra_settings ) ) {
|
242 |
+
$imgopt_settings = autoptimizeConfig::get_ao_imgopt_default_options();
|
243 |
+
if ( array_key_exists( 'autoptimize_extra_checkbox_field_5', $extra_settings ) ) {
|
244 |
+
$imgopt_settings['autoptimize_imgopt_checkbox_field_1'] = $extra_settings['autoptimize_extra_checkbox_field_5'];
|
245 |
+
}
|
246 |
+
if ( array_key_exists( 'autoptimize_extra_select_field_6', $extra_settings ) ) {
|
247 |
+
$imgopt_settings['autoptimize_imgopt_select_field_2'] = $extra_settings['autoptimize_extra_select_field_6'];
|
248 |
+
}
|
249 |
update_option( 'autoptimize_imgopt_settings', $imgopt_settings );
|
250 |
}
|
251 |
}
|
classes/external/js/lazysizes.min.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1 |
-
/*! lazysizes -
|
2 |
-
!function(a,b){var c=b(a,a.document);a.lazySizes=c,"object"==typeof module&&module.exports&&(module.exports=c)}(window,function(a,b){"use strict";if(b.getElementsByClassName){var c,d,e=b.documentElement,f=a.Date,g=a.HTMLPictureElement,h="addEventListener",i="getAttribute",j=a[h],k=a.setTimeout,l=a.requestAnimationFrame||k,m=a.requestIdleCallback,n=/^picture$/i,o=["load","error","lazyincluded","_lazyloaded"],p={},q=Array.prototype.forEach,r=function(a,b){return p[b]||(p[b]=new RegExp("(\\s|^)"+b+"(\\s|$)")),p[b].test(a[i]("class")||"")&&p[b]},s=function(a,b){r(a,b)||a.setAttribute("class",(a[i]("class")||"").trim()+" "+b)},t=function(a,b){var c;(c=r(a,b))&&a.setAttribute("class",(a[i]("class")||"").replace(c," "))},u=function(a,b,c){var d=c?h:"removeEventListener";c&&u(a,b),o.forEach(function(c){a[d](c,b)})},v=function(a,d,e,f,g){var h=b.createEvent("Event");return e||(e={}),e.instance=c,h.initEvent(d,!f,!g),h.detail=e,a.dispatchEvent(h),h},w=function(b,c){var e;!g&&(e=a.picturefill||d.pf)?(c&&c.src&&!b[i]("srcset")&&b.setAttribute("srcset",c.src),e({reevaluate:!0,elements:[b]})):c&&c.src&&(b.src=c.src)},x=function(a,b){return(getComputedStyle(a,null)||{})[b]},y=function(a,b,c){for(c=c||a.offsetWidth;c<d.minSize&&b&&!a._lazysizesWidth;)c=b.offsetWidth,b=b.parentNode;return c},z=function(){var a,c,d=[],e=[],f=d,g=function(){var b=f;for(f=d.length?e:d,a=!0,c=!1;b.length;)b.shift()();a=!1},h=function(d,e){a&&!e?d.apply(this,arguments):(f.push(d),c||(c=!0,(b.hidden?k:l)(g)))};return h._lsFlush=g,h}(),A=function(a,b){return b?function(){z(a)}:function(){var b=this,c=arguments;z(function(){a.apply(b,c)})}},B=function(a){var b,c=0,e=d.throttleDelay,g=d.ricTimeout,h=function(){b=!1,c=f.now(),a()},i=m&&g>49?function(){m(h,{timeout:g}),g!==d.ricTimeout&&(g=d.ricTimeout)}:A(function(){k(h)},!0);return function(a){var d;(a=!0===a)&&(g=33),b||(b=!0,d=e-(f.now()-c),d<0&&(d=0),a||d<9?i():k(i,d))}},C=function(a){var b,c,d=99,e=function(){b=null,a()},g=function(){var a=f.now()-c;a<d?k(g,d-a):(m||e)(e)};return function(){c=f.now(),b||(b=k(g,d))}};!function(){var b,c={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:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};d=a.lazySizesConfig||a.lazysizesConfig||{};for(b in c)b in d||(d[b]=c[b]);
|
1 |
+
/*! lazysizes - v5.0.0 */
|
2 |
+
!function(a,b){var c=b(a,a.document);a.lazySizes=c,"object"==typeof module&&module.exports&&(module.exports=c)}(window,function(a,b){"use strict";if(b.getElementsByClassName){var c,d,e=b.documentElement,f=a.Date,g=a.HTMLPictureElement,h="addEventListener",i="getAttribute",j=a[h],k=a.setTimeout,l=a.requestAnimationFrame||k,m=a.requestIdleCallback,n=/^picture$/i,o=["load","error","lazyincluded","_lazyloaded"],p={},q=Array.prototype.forEach,r=function(a,b){return p[b]||(p[b]=new RegExp("(\\s|^)"+b+"(\\s|$)")),p[b].test(a[i]("class")||"")&&p[b]},s=function(a,b){r(a,b)||a.setAttribute("class",(a[i]("class")||"").trim()+" "+b)},t=function(a,b){var c;(c=r(a,b))&&a.setAttribute("class",(a[i]("class")||"").replace(c," "))},u=function(a,b,c){var d=c?h:"removeEventListener";c&&u(a,b),o.forEach(function(c){a[d](c,b)})},v=function(a,d,e,f,g){var h=b.createEvent("Event");return e||(e={}),e.instance=c,h.initEvent(d,!f,!g),h.detail=e,a.dispatchEvent(h),h},w=function(b,c){var e;!g&&(e=a.picturefill||d.pf)?(c&&c.src&&!b[i]("srcset")&&b.setAttribute("srcset",c.src),e({reevaluate:!0,elements:[b]})):c&&c.src&&(b.src=c.src)},x=function(a,b){return(getComputedStyle(a,null)||{})[b]},y=function(a,b,c){for(c=c||a.offsetWidth;c<d.minSize&&b&&!a._lazysizesWidth;)c=b.offsetWidth,b=b.parentNode;return c},z=function(){var a,c,d=[],e=[],f=d,g=function(){var b=f;for(f=d.length?e:d,a=!0,c=!1;b.length;)b.shift()();a=!1},h=function(d,e){a&&!e?d.apply(this,arguments):(f.push(d),c||(c=!0,(b.hidden?k:l)(g)))};return h._lsFlush=g,h}(),A=function(a,b){return b?function(){z(a)}:function(){var b=this,c=arguments;z(function(){a.apply(b,c)})}},B=function(a){var b,c=0,e=d.throttleDelay,g=d.ricTimeout,h=function(){b=!1,c=f.now(),a()},i=m&&g>49?function(){m(h,{timeout:g}),g!==d.ricTimeout&&(g=d.ricTimeout)}:A(function(){k(h)},!0);return function(a){var d;(a=!0===a)&&(g=33),b||(b=!0,d=e-(f.now()-c),d<0&&(d=0),a||d<9?i():k(i,d))}},C=function(a){var b,c,d=99,e=function(){b=null,a()},g=function(){var a=f.now()-c;a<d?k(g,d-a):(m||e)(e)};return function(){c=f.now(),b||(b=k(g,d))}};!function(){var b,c={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:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};d=a.lazySizesConfig||a.lazysizesConfig||{};for(b in c)b in d||(d[b]=c[b]);k(function(){d.init&&F()})}();var D=function(){var g,l,m,o,p,y,D,F,G,H,I,J,K=/^img$/i,L=/^iframe$/i,M="onscroll"in a&&!/(gle|ing)bot/.test(navigator.userAgent),N=0,O=0,P=0,Q=-1,R=function(a){P--,(!a||P<0||!a.target)&&(P=0)},S=function(a){return null==J&&(J="hidden"==x(b.body,"visibility")),J||"hidden"!=x(a.parentNode,"visibility")&&"hidden"!=x(a,"visibility")},T=function(a,c){var d,f=a,g=S(a);for(F-=c,I+=c,G-=c,H+=c;g&&(f=f.offsetParent)&&f!=b.body&&f!=e;)(g=(x(f,"opacity")||1)>0)&&"visible"!=x(f,"overflow")&&(d=f.getBoundingClientRect(),g=H>d.left&&G<d.right&&I>d.top-1&&F<d.bottom+1);return g},U=function(){var a,f,h,j,k,m,n,p,q,r,s,t,u=c.elements;if((o=d.loadMode)&&P<8&&(a=u.length)){for(f=0,Q++;f<a;f++)if(u[f]&&!u[f]._lazyRace)if(!M||c.prematureUnveil&&c.prematureUnveil(u[f]))aa(u[f]);else if((p=u[f][i]("data-expand"))&&(m=1*p)||(m=O),r||(r=!d.expand||d.expand<1?e.clientHeight>500&&e.clientWidth>500?500:370:d.expand,c._defEx=r,s=r*d.expFactor,t=d.hFac,J=null,O<s&&P<1&&Q>2&&o>2&&!b.hidden?(O=s,Q=0):O=o>1&&Q>1&&P<6?r:N),q!==m&&(y=innerWidth+m*t,D=innerHeight+m,n=-1*m,q=m),h=u[f].getBoundingClientRect(),(I=h.bottom)>=n&&(F=h.top)<=D&&(H=h.right)>=n*t&&(G=h.left)<=y&&(I||H||G||F)&&(d.loadHidden||S(u[f]))&&(l&&P<3&&!p&&(o<3||Q<4)||T(u[f],m))){if(aa(u[f]),k=!0,P>9)break}else!k&&l&&!j&&P<4&&Q<4&&o>2&&(g[0]||d.preloadAfterLoad)&&(g[0]||!p&&(I||H||G||F||"auto"!=u[f][i](d.sizesAttr)))&&(j=g[0]||u[f]);j&&!k&&aa(j)}},V=B(U),W=function(a){var b=a.target;if(b._lazyCache)return void delete b._lazyCache;R(a),s(b,d.loadedClass),t(b,d.loadingClass),u(b,Y),v(b,"lazyloaded")},X=A(W),Y=function(a){X({target:a.target})},Z=function(a,b){try{a.contentWindow.location.replace(b)}catch(c){a.src=b}},$=function(a){var b,c=a[i](d.srcsetAttr);(b=d.customMedia[a[i]("data-media")||a[i]("media")])&&a.setAttribute("media",b),c&&a.setAttribute("srcset",c)},_=A(function(a,b,c,e,f){var g,h,j,l,o,p;(o=v(a,"lazybeforeunveil",b)).defaultPrevented||(e&&(c?s(a,d.autosizesClass):a.setAttribute("sizes",e)),h=a[i](d.srcsetAttr),g=a[i](d.srcAttr),f&&(j=a.parentNode,l=j&&n.test(j.nodeName||"")),p=b.firesLoad||"src"in a&&(h||g||l),o={target:a},s(a,d.loadingClass),p&&(clearTimeout(m),m=k(R,2500),u(a,Y,!0)),l&&q.call(j.getElementsByTagName("source"),$),h?a.setAttribute("srcset",h):g&&!l&&(L.test(a.nodeName)?Z(a,g):a.src=g),f&&(h||l)&&w(a,{src:g})),a._lazyRace&&delete a._lazyRace,t(a,d.lazyClass),z(function(){var b=a.complete&&a.naturalWidth>1;p&&!b||(b&&s(a,"ls-is-cached"),W(o),a._lazyCache=!0,k(function(){"_lazyCache"in a&&delete a._lazyCache},9)),"lazy"==a.loading&&P--},!0)}),aa=function(a){if(!a._lazyRace){var b,c=K.test(a.nodeName),e=c&&(a[i](d.sizesAttr)||a[i]("sizes")),f="auto"==e;(!f&&l||!c||!a[i]("src")&&!a.srcset||a.complete||r(a,d.errorClass)||!r(a,d.lazyClass))&&(b=v(a,"lazyunveilread").detail,f&&E.updateElem(a,!0,a.offsetWidth),a._lazyRace=!0,P++,_(a,b,f,e,c))}},ba=C(function(){d.loadMode=3,V()}),ca=function(){3==d.loadMode&&(d.loadMode=2),ba()},da=function(){if(!l){if(f.now()-p<999)return void k(da,999);l=!0,d.loadMode=3,V(),j("scroll",ca,!0)}};return{_:function(){p=f.now(),c.elements=b.getElementsByClassName(d.lazyClass),g=b.getElementsByClassName(d.lazyClass+" "+d.preloadClass),j("scroll",V,!0),j("resize",V,!0),a.MutationObserver?new MutationObserver(V).observe(e,{childList:!0,subtree:!0,attributes:!0}):(e[h]("DOMNodeInserted",V,!0),e[h]("DOMAttrModified",V,!0),setInterval(V,999)),j("hashchange",V,!0),["focus","mouseover","click","load","transitionend","animationend"].forEach(function(a){b[h](a,V,!0)}),/d$|^c/.test(b.readyState)?da():(j("load",da),b[h]("DOMContentLoaded",V),k(da,2e4)),c.elements.length?(U(),z._lsFlush()):V()},checkElems:V,unveil:aa,_aLSL:ca}}(),E=function(){var a,c=A(function(a,b,c,d){var e,f,g;if(a._lazysizesWidth=d,d+="px",a.setAttribute("sizes",d),n.test(b.nodeName||""))for(e=b.getElementsByTagName("source"),f=0,g=e.length;f<g;f++)e[f].setAttribute("sizes",d);c.detail.dataAttr||w(a,c.detail)}),e=function(a,b,d){var e,f=a.parentNode;f&&(d=y(a,f,d),e=v(a,"lazybeforesizes",{width:d,dataAttr:!!b}),e.defaultPrevented||(d=e.detail.width)&&d!==a._lazysizesWidth&&c(a,f,e,d))},f=function(){var b,c=a.length;if(c)for(b=0;b<c;b++)e(a[b])},g=C(f);return{_:function(){a=b.getElementsByClassName(d.autosizesClass),j("resize",g)},checkElems:g,updateElem:e}}(),F=function(){F.i||(F.i=!0,E._(),D._())};return c={cfg:d,autoSizer:E,loader:D,init:F,uP:w,aC:s,rC:t,hC:r,fire:v,gW:y,rAF:z}}});
|
classes/external/php/minify-html.php
CHANGED
@@ -18,6 +18,9 @@
|
|
18 |
*/
|
19 |
class Minify_HTML {
|
20 |
|
|
|
|
|
|
|
21 |
/**
|
22 |
* "Minify" an HTML page
|
23 |
*
|
18 |
*/
|
19 |
class Minify_HTML {
|
20 |
|
21 |
+
/** @var string */
|
22 |
+
private $_html;
|
23 |
+
|
24 |
/**
|
25 |
* "Minify" an HTML page
|
26 |
*
|
readme.txt
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
=== Autoptimize ===
|
2 |
Contributors: futtta, optimizingmatters, zytzagoo, turl
|
3 |
-
Tags: optimize, minify, performance, pagespeed, images, google fonts
|
4 |
Donate link: http://blog.futtta.be/2013/10/21/do-not-donate-to-me/
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.2
|
7 |
Requires PHP: 5.3
|
8 |
-
Stable tag: 2.5.
|
9 |
|
10 |
-
Autoptimize speeds up your website by optimizing JS, CSS, images, HTML
|
11 |
|
12 |
== Description ==
|
13 |
|
14 |
-
Autoptimize makes optimizing your site really easy. It can aggregate, minify and cache scripts and styles, injects CSS in the page head by default but can also inline critical CSS and defer the aggregated full CSS, moves and defers scripts to the footer and minifies HTML. You can optimize and
|
15 |
|
16 |
If you consider performance important, you really should use one of the many caching plugins to do page caching. Some good candidates to complement Autoptimize that way are e.g. [WP Super Cache](http://wordpress.org/plugins/wp-super-cache/), [HyperCache](http://wordpress.org/plugins/hyper-cache/), [Comet Cache](https://wordpress.org/plugins/comet-cache/) or [KeyCDN's Cache Enabler](https://wordpress.org/plugins/cache-enabler).
|
17 |
|
@@ -36,7 +36,7 @@ It concatenates all scripts and styles, minifies and compresses them, adds expir
|
|
36 |
|
37 |
= But I'm on HTTP/2, so I don't need Autoptimize? =
|
38 |
|
39 |
-
HTTP/2 is a great step forward for sure, reducing the impact of multiple requests from the same server significantly by using the same connection to perform several concurrent requests. That being said, [concatenation of CSS/ JS can still make a lot of sense](http://engineering.khanacademy.org/posts/js-packaging-http2.htm), as described in [this css-tricks.com article](https://css-tricks.com/http2-real-world-performance-test-analysis/) and this [blogpost from one of the Ebay engineers](http://calendar.perfplanet.com/2015/packaging-for-performance/). The conclusion; configure, test, reconfigure, retest, tweak and look what works best in your context. Maybe it's just HTTP/2, maybe it's HTTP/2 + aggregation and minification, maybe it's HTTP/2 + minification (which AO can do as well, simply untick the "aggregate JS-files" and/ or "aggregate CSS-files" options).
|
40 |
|
41 |
= Will this work with my blog? =
|
42 |
|
@@ -64,15 +64,7 @@ There's no easy solution for that as "above the fold" depends on where the fold
|
|
64 |
|
65 |
= Or should you inline all CSS? =
|
66 |
|
67 |
-
The short answer: probably not.
|
68 |
-
|
69 |
-
Back in the days CSS optimization was easy; put all CSS in your head, aggregating everything in one CSS-file per media-type and you were good to go. But ever since Google included mobile in PageSpeed Insights and started complaining about render blocking CSS, things got messy (see "deferring CSS" elsewhere in this FAQ). One of the solutions is inlining all your CSS, which as of Autoptimize 1.8.0 is supported.
|
70 |
-
|
71 |
-
Inlining all CSS has one clear advantage (better PageSpeed score) and one big disadvantage; your base HTML-page gets significantly bigger and if the amount of CSS is big, Pagespeed Insights will complain of "roundtrip times". Also when looking at a test that includes multiple requests (let's say 5 pages), performance will be worse, as the CSS-payload is sent over again and again whereas normally the separate CSS-files would not need to be sent any more as they would be in cache.
|
72 |
-
|
73 |
-
So the choice should be based on your answer to some site-specific questions; how much CSS do you have? How many pages per visit do your visitors request? If you have a lot of CSS or a high number of pages/ visit, it's probably not a good idea to inline all CSS.
|
74 |
-
|
75 |
-
You can find more information on this topic [in this blog post](http://blog.futtta.be/2014/02/13/should-you-inline-or-defer-blocking-css/).
|
76 |
|
77 |
= My cache is getting huge, doesn't Autoptimize purge the cache? =
|
78 |
|
@@ -283,6 +275,13 @@ Just [fork Autoptimize on Github](https://github.com/futtta/autoptimize) and cod
|
|
283 |
|
284 |
== Changelog ==
|
285 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
= 2.5.0 =
|
287 |
* moved image optimization to a separate tab and move all code to a separate file.
|
288 |
* added lazyloading (using lazysizes)
|
1 |
=== Autoptimize ===
|
2 |
Contributors: futtta, optimizingmatters, zytzagoo, turl
|
3 |
+
Tags: optimize, minify, performance, pagespeed, images, lazy-load, google fonts
|
4 |
Donate link: http://blog.futtta.be/2013/10/21/do-not-donate-to-me/
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.2
|
7 |
Requires PHP: 5.3
|
8 |
+
Stable tag: 2.5.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 |
|
12 |
== Description ==
|
13 |
|
14 |
+
Autoptimize makes optimizing your site really easy. It can aggregate, minify and cache scripts and styles, injects CSS in the page head by default but can also inline critical CSS and defer the aggregated full CSS, moves and defers scripts to the footer and minifies HTML. You can optimize and lazy-load images, optimize Google Fonts, async non-aggregated JavaScript, remove WordPress core emoji cruft and more. As such it can improve your site's performance even when already on HTTP/2! There is extensive API available to enable you to tailor Autoptimize to each and every site's specific needs.
|
15 |
|
16 |
If you consider performance important, you really should use one of the many caching plugins to do page caching. Some good candidates to complement Autoptimize that way are e.g. [WP Super Cache](http://wordpress.org/plugins/wp-super-cache/), [HyperCache](http://wordpress.org/plugins/hyper-cache/), [Comet Cache](https://wordpress.org/plugins/comet-cache/) or [KeyCDN's Cache Enabler](https://wordpress.org/plugins/cache-enabler).
|
17 |
|
36 |
|
37 |
= But I'm on HTTP/2, so I don't need Autoptimize? =
|
38 |
|
39 |
+
HTTP/2 is a great step forward for sure, reducing the impact of multiple requests from the same server significantly by using the same connection to perform several concurrent requests. That being said, [concatenation of CSS/ JS can still make a lot of sense](http://engineering.khanacademy.org/posts/js-packaging-http2.htm), as described in [this css-tricks.com article](https://css-tricks.com/http2-real-world-performance-test-analysis/) and this [blogpost from one of the Ebay engineers](http://calendar.perfplanet.com/2015/packaging-for-performance/). The conclusion; configure, test, reconfigure, retest, tweak and look what works best in your context. Maybe it's just HTTP/2, maybe it's HTTP/2 + aggregation and minification, maybe it's HTTP/2 + minification (which AO can do as well, simply untick the "aggregate JS-files" and/ or "aggregate CSS-files" options). And Autoptimize can do a lot more then "just" optimizing your JS & CSS off course ;-)
|
40 |
|
41 |
= Will this work with my blog? =
|
42 |
|
64 |
|
65 |
= Or should you inline all CSS? =
|
66 |
|
67 |
+
The short answer: probably not. Although inlining all CSS will make the CSS non-render blocking, it will result in your base HTML-page getting significantly bigger thus requiring more "roundtrip times". Moreover when considering multiple pages being requested in a browsing session the inline CSS is sent over each time, whereas when not inlined it would be served from cache.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
|
69 |
= My cache is getting huge, doesn't Autoptimize purge the cache? =
|
70 |
|
275 |
|
276 |
== Changelog ==
|
277 |
|
278 |
+
= 2.5.1 =
|
279 |
+
* Images: Also optimize & lazyload <picture><source>
|
280 |
+
* Images: Misc. improvements to lazyload
|
281 |
+
* Images: Updated to LazySizes 5.0.0
|
282 |
+
* CSS: improvements to the deferring logic for non-aggregated CSS resources.
|
283 |
+
* Settings-page: Show "JS, CSS & HTML" advanced options by default (many people did not see the button)
|
284 |
+
|
285 |
= 2.5.0 =
|
286 |
* moved image optimization to a separate tab and move all code to a separate file.
|
287 |
* added lazyloading (using lazysizes)
|