Version Description
- Image optimization: also optimize icon links
- Image optimization: fix webp-detection for Safari (contributed by @pinkasey)
- Image lazyload: remove CSS that hides the placeholder image/ sets transistion between placeholder and final image
- Critical CSS: new advanced option to unload CCSS on onLoad
- Critical CSS improvement: cache templates in a transient to avoid overhead of having to search filesystem time and time again (contributed by @pratham2003)
- Critical CSS improvement: better but still experimental jQuery deferring logic
- Critical CSS fix: prevent MANUAL template-based rules being overwritten
- CSS Inline & defer: move away from old loadCSS-based approach to Filamentgroup's new, simpler method
- 404 fallback enabled by default for new installations
- changed all occurences of blacklist/ whitelist to blocklist/ allowlist. The filters
autoptimize_filter_js_whitelist
andautoptimize_filter_css_whitelist
still work in 2.7.4 but usage is deprecated and should be replaced withautoptimize_filter_js_allowlist
andautoptimize_filter_css_allowlist
. - updated readme to explicitly confirm this is GPL + praise open source projects used in Autoptimize as praise was long overdue!
- tested and confirmed working on WordPress 5.5 beta 2
Download this release
Release Info
Developer | futtta |
Plugin | Autoptimize |
Version | 2.7.4 |
Comparing to | |
See all releases |
Code changes from version 2.7.3 to 2.7.4
- autoptimize.php +4 -3
- classes/autoptimizeConfig.php +8 -17
- classes/autoptimizeCriticalCSSBase.php +16 -8
- classes/autoptimizeCriticalCSSCore.php +45 -14
- classes/autoptimizeCriticalCSSCron.php +7 -2
- classes/autoptimizeCriticalCSSEnqueue.php +8 -4
- classes/autoptimizeCriticalCSSSettings.php +2 -0
- classes/autoptimizeImages.php +25 -2
- classes/autoptimizeMain.php +1 -0
- classes/autoptimizeScripts.php +16 -12
- classes/autoptimizeStyles.php +35 -31
- classes/critcss-inc/admin_settings_adv.php +12 -0
- readme.txt +33 -3
autoptimize.php
CHANGED
@@ -3,12 +3,13 @@
|
|
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.7.
|
7 |
* Author: Frank Goossens (futtta)
|
8 |
* Author URI: https://autoptimize.com/
|
9 |
* Text Domain: autoptimize
|
|
|
10 |
* Released under the GNU General Public License (GPL)
|
11 |
-
*
|
12 |
*/
|
13 |
|
14 |
/**
|
@@ -20,7 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
20 |
exit;
|
21 |
}
|
22 |
|
23 |
-
define( 'AUTOPTIMIZE_PLUGIN_VERSION', '2.7.
|
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.7.4
|
7 |
* Author: Frank Goossens (futtta)
|
8 |
* Author URI: https://autoptimize.com/
|
9 |
* Text Domain: autoptimize
|
10 |
+
* License: GPLv2
|
11 |
* Released under the GNU General Public License (GPL)
|
12 |
+
* https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
13 |
*/
|
14 |
|
15 |
/**
|
21 |
exit;
|
22 |
}
|
23 |
|
24 |
+
define( 'AUTOPTIMIZE_PLUGIN_VERSION', '2.7.4' );
|
25 |
|
26 |
// plugin_dir_path() returns the trailing slash!
|
27 |
define( 'AUTOPTIMIZE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
classes/autoptimizeConfig.php
CHANGED
@@ -407,9 +407,9 @@ echo __( 'A comma-separated list of CSS you want to exclude from being optimized
|
|
407 |
<?php _e( 'When aggregating JS or CSS, excluded files that are not minified (based on filename) are by default minified by Autoptimize despite being excluded. Uncheck this option if anything breaks despite excluding.', 'autoptimize' ); ?></label></td>
|
408 |
</tr>
|
409 |
<tr valign="top">
|
410 |
-
<th scope="row"><?php _e( '
|
411 |
-
<td><label class="cb_label"><input type="checkbox" name="autoptimize_cache_fallback" <?php echo autoptimizeOptionWrapper::get_option( 'autoptimize_cache_fallback', '' ) ? 'checked="checked" ' : ''; ?>/>
|
412 |
-
<?php _e( 'Sometimes Autoptimized JS/ CSS is referenced in cached HTML but is already removed, resulting in broken sites.
|
413 |
</tr>
|
414 |
<tr valign="top">
|
415 |
<th scope="row"><?php _e( 'Also optimize for logged in editors/ administrators?', 'autoptimize' ); ?></th>
|
@@ -743,7 +743,7 @@ echo __( 'A comma-separated list of CSS you want to exclude from being optimized
|
|
743 |
'autoptimize_optimize_logged' => 1,
|
744 |
'autoptimize_optimize_checkout' => 0,
|
745 |
'autoptimize_minify_excluded' => 1,
|
746 |
-
'autoptimize_cache_fallback' =>
|
747 |
);
|
748 |
|
749 |
return $config;
|
@@ -785,25 +785,16 @@ echo __( 'A comma-separated list of CSS you want to exclude from being optimized
|
|
785 |
return $defaults;
|
786 |
}
|
787 |
|
788 |
-
/**
|
789 |
-
* Returns preload polyfill JS.
|
790 |
-
*
|
791 |
-
* @return string
|
792 |
-
*/
|
793 |
-
public static function get_ao_css_preload_polyfill()
|
794 |
-
{
|
795 |
-
$preload_poly = apply_filters( 'autoptimize_css_preload_polyfill', '<script data-cfasync=\'false\'>!function(t){"use strict";t.loadCSS||(t.loadCSS=function(){});var e=loadCSS.relpreload={};if(e.support=function(){var e;try{e=t.document.createElement("link").relList.supports("preload")}catch(t){e=!1}return function(){return e}}(),e.bindMediaToggle=function(t){function e(){t.media=a}var a=t.media||"all";t.addEventListener?t.addEventListener("load",e):t.attachEvent&&t.attachEvent("onload",e),setTimeout(function(){t.rel="stylesheet",t.media="only x"}),setTimeout(e,3e3)},e.poly=function(){if(!e.support())for(var a=t.document.getElementsByTagName("link"),n=0;n<a.length;n++){var o=a[n];"preload"!==o.rel||"style"!==o.getAttribute("as")||o.getAttribute("data-loadcss")||(o.setAttribute("data-loadcss",!0),e.bindMediaToggle(o))}},!e.support()){e.poly();var a=t.setInterval(e.poly,500);t.addEventListener?t.addEventListener("load",function(){e.poly(),t.clearInterval(a)}):t.attachEvent&&t.attachEvent("onload",function(){e.poly(),t.clearInterval(a)})}"undefined"!=typeof exports?exports.loadCSS=loadCSS:t.loadCSS=loadCSS}("undefined"!=typeof global?global:this);</script>' );
|
796 |
-
return $preload_poly;
|
797 |
-
}
|
798 |
-
|
799 |
/**
|
800 |
* Returns preload JS onload handler.
|
801 |
*
|
|
|
|
|
802 |
* @return string
|
803 |
*/
|
804 |
-
public static function get_ao_css_preload_onload()
|
805 |
{
|
806 |
-
$preload_onload = apply_filters( 'autoptimize_filter_css_preload_onload', "this.onload=null;this.
|
807 |
return $preload_onload;
|
808 |
}
|
809 |
|
407 |
<?php _e( 'When aggregating JS or CSS, excluded files that are not minified (based on filename) are by default minified by Autoptimize despite being excluded. Uncheck this option if anything breaks despite excluding.', 'autoptimize' ); ?></label></td>
|
408 |
</tr>
|
409 |
<tr valign="top">
|
410 |
+
<th scope="row"><?php _e( 'Enable 404 fallbacks?', 'autoptimize' ); ?></th>
|
411 |
+
<td><label class="cb_label"><input type="checkbox" name="autoptimize_cache_fallback" <?php echo autoptimizeOptionWrapper::get_option( 'autoptimize_cache_fallback', '1' ) ? 'checked="checked" ' : ''; ?>/>
|
412 |
+
<?php _e( 'Sometimes Autoptimized JS/ CSS is referenced in cached HTML but is already removed, resulting in broken sites. With this option on, Autoptimize will try to redirect those not-found files to "fallback"-versions, keeping the page/ site somewhat intact. In some cases this will require extra web-server level configuration to ensure <code>wp-content/autoptimize_404_handler.php</code> is set to handle 404\'s in <code>wp-content/cache/autoptimize</code>.', 'autoptimize' ); ?></label></td>
|
413 |
</tr>
|
414 |
<tr valign="top">
|
415 |
<th scope="row"><?php _e( 'Also optimize for logged in editors/ administrators?', 'autoptimize' ); ?></th>
|
743 |
'autoptimize_optimize_logged' => 1,
|
744 |
'autoptimize_optimize_checkout' => 0,
|
745 |
'autoptimize_minify_excluded' => 1,
|
746 |
+
'autoptimize_cache_fallback' => 1,
|
747 |
);
|
748 |
|
749 |
return $config;
|
785 |
return $defaults;
|
786 |
}
|
787 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
788 |
/**
|
789 |
* Returns preload JS onload handler.
|
790 |
*
|
791 |
+
* @param string $media media attribute value the JS to use.
|
792 |
+
*
|
793 |
* @return string
|
794 |
*/
|
795 |
+
public static function get_ao_css_preload_onload( $media = 'all' )
|
796 |
{
|
797 |
+
$preload_onload = apply_filters( 'autoptimize_filter_css_preload_onload', "this.onload=null;this.media='" . $media . "';" );
|
798 |
return $preload_onload;
|
799 |
}
|
800 |
|
classes/autoptimizeCriticalCSSBase.php
CHANGED
@@ -20,9 +20,6 @@ class autoptimizeCriticalCSSBase {
|
|
20 |
{
|
21 |
// define constant, but only once.
|
22 |
if ( ! defined( 'AO_CCSS_DIR' ) ) {
|
23 |
-
// Define plugin version.
|
24 |
-
define( 'AO_CCSS_VER', 'AO_' . AUTOPTIMIZE_PLUGIN_VERSION );
|
25 |
-
|
26 |
// Define a constant with the directory to store critical CSS in.
|
27 |
if ( is_multisite() ) {
|
28 |
$blog_id = get_current_blog_id();
|
@@ -30,11 +27,10 @@ class autoptimizeCriticalCSSBase {
|
|
30 |
} else {
|
31 |
define( 'AO_CCSS_DIR', WP_CONTENT_DIR . '/uploads/ao_ccss/' );
|
32 |
}
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
define( '
|
37 |
-
define( 'AO_CCSS_DEBUG', AO_CCSS_DIR . 'queue.json' );
|
38 |
|
39 |
// Define constants for criticalcss.com base path and API endpoints.
|
40 |
// fixme: AO_CCSS_URL should be read from the autoptimize availability json stored as option.
|
@@ -43,6 +39,17 @@ class autoptimizeCriticalCSSBase {
|
|
43 |
define( 'AO_CCSS_SLEEP', 10 );
|
44 |
}
|
45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
$this->filepath = __FILE__;
|
47 |
|
48 |
$this->setup();
|
@@ -108,6 +115,7 @@ class autoptimizeCriticalCSSBase {
|
|
108 |
$autoptimize_ccss_options['ao_ccss_servicestatus'] = get_option( 'autoptimize_service_availablity' );
|
109 |
$autoptimize_ccss_options['ao_ccss_deferjquery'] = get_option( 'autoptimize_ccss_deferjquery', false );
|
110 |
$autoptimize_ccss_options['ao_ccss_domain'] = get_option( 'autoptimize_ccss_domain' );
|
|
|
111 |
|
112 |
if ( strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'http' ) === false && strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'uggc' ) === 0 ) {
|
113 |
$autoptimize_ccss_options['ao_ccss_domain'] = str_rot13( $autoptimize_ccss_options['ao_ccss_domain'] );
|
20 |
{
|
21 |
// define constant, but only once.
|
22 |
if ( ! defined( 'AO_CCSS_DIR' ) ) {
|
|
|
|
|
|
|
23 |
// Define a constant with the directory to store critical CSS in.
|
24 |
if ( is_multisite() ) {
|
25 |
$blog_id = get_current_blog_id();
|
27 |
} else {
|
28 |
define( 'AO_CCSS_DIR', WP_CONTENT_DIR . '/uploads/ao_ccss/' );
|
29 |
}
|
30 |
+
}
|
31 |
+
if ( ! defined( 'AO_CCSS_VER' ) ) {
|
32 |
+
// Define plugin version.
|
33 |
+
define( 'AO_CCSS_VER', 'AO_' . AUTOPTIMIZE_PLUGIN_VERSION );
|
|
|
34 |
|
35 |
// Define constants for criticalcss.com base path and API endpoints.
|
36 |
// fixme: AO_CCSS_URL should be read from the autoptimize availability json stored as option.
|
39 |
define( 'AO_CCSS_SLEEP', 10 );
|
40 |
}
|
41 |
|
42 |
+
// Define support files locations, in case they are not already defined.
|
43 |
+
if ( ! defined( 'AO_CCSS_LOCK' ) ) {
|
44 |
+
define( 'AO_CCSS_LOCK', AO_CCSS_DIR . 'queue.lock' );
|
45 |
+
}
|
46 |
+
if ( ! defined( 'AO_CCSS_LOG' ) ) {
|
47 |
+
define( 'AO_CCSS_LOG', AO_CCSS_DIR . 'queuelog.html' );
|
48 |
+
}
|
49 |
+
if ( ! defined( 'AO_CCSS_DEBUG' ) ) {
|
50 |
+
define( 'AO_CCSS_DEBUG', AO_CCSS_DIR . 'queue.json' );
|
51 |
+
}
|
52 |
+
|
53 |
$this->filepath = __FILE__;
|
54 |
|
55 |
$this->setup();
|
115 |
$autoptimize_ccss_options['ao_ccss_servicestatus'] = get_option( 'autoptimize_service_availablity' );
|
116 |
$autoptimize_ccss_options['ao_ccss_deferjquery'] = get_option( 'autoptimize_ccss_deferjquery', false );
|
117 |
$autoptimize_ccss_options['ao_ccss_domain'] = get_option( 'autoptimize_ccss_domain' );
|
118 |
+
$autoptimize_ccss_options['ao_ccss_unloadccss'] = get_option( 'autoptimize_ccss_unloadccss', false );
|
119 |
|
120 |
if ( strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'http' ) === false && strpos( $autoptimize_ccss_options['ao_ccss_domain'], 'uggc' ) === 0 ) {
|
121 |
$autoptimize_ccss_options['ao_ccss_domain'] = str_rot13( $autoptimize_ccss_options['ao_ccss_domain'] );
|
classes/autoptimizeCriticalCSSCore.php
CHANGED
@@ -25,6 +25,7 @@ class autoptimizeCriticalCSSCore {
|
|
25 |
global $ao_css_defer;
|
26 |
global $ao_ccss_deferjquery;
|
27 |
global $ao_ccss_key;
|
|
|
28 |
|
29 |
// add all filters to do CCSS if key present.
|
30 |
if ( $ao_css_defer && isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) ) {
|
@@ -40,6 +41,11 @@ class autoptimizeCriticalCSSCore {
|
|
40 |
add_filter( 'autoptimize_html_after_minify', array( $this, 'ao_ccss_defer_jquery' ), 11, 1 );
|
41 |
}
|
42 |
|
|
|
|
|
|
|
|
|
|
|
43 |
// Order paths by length, as longest ones have greater priority in the rules.
|
44 |
if ( ! empty( $ao_ccss_rules['paths'] ) ) {
|
45 |
$keys = array_map( 'strlen', array_keys( $ao_ccss_rules['paths'] ) );
|
@@ -53,6 +59,9 @@ class autoptimizeCriticalCSSCore {
|
|
53 |
|
54 |
// Extend conditional tags on plugin initalization.
|
55 |
add_action( apply_filters( 'autoptimize_filter_ccss_extend_types_hook', 'init' ), array( $this, 'ao_ccss_extend_types' ) );
|
|
|
|
|
|
|
56 |
}
|
57 |
}
|
58 |
|
@@ -161,15 +170,19 @@ class autoptimizeCriticalCSSCore {
|
|
161 |
}
|
162 |
|
163 |
public function ao_ccss_defer_jquery( $in ) {
|
164 |
-
|
|
|
165 |
if ( ( ! is_user_logged_in() || $ao_ccss_loggedin ) && preg_match_all( '#<script.*>(.*)</script>#Usmi', $in, $matches, PREG_SET_ORDER ) ) {
|
166 |
foreach ( $matches as $match ) {
|
167 |
-
if ( (
|
168 |
-
//
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
|
|
|
|
|
|
173 |
$new_match = str_replace( '<script ', '<script defer ', $match[0] );
|
174 |
$in = str_replace( $match[0], $new_match, $in );
|
175 |
}
|
@@ -178,6 +191,13 @@ class autoptimizeCriticalCSSCore {
|
|
178 |
return $in;
|
179 |
}
|
180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
public function ao_ccss_extend_types() {
|
182 |
// Extend contidional tags
|
183 |
// Attach the conditional tags array.
|
@@ -203,7 +223,12 @@ class autoptimizeCriticalCSSCore {
|
|
203 |
}
|
204 |
|
205 |
// Templates.
|
206 |
-
|
|
|
|
|
|
|
|
|
|
|
207 |
foreach ( $templates as $tplfile => $tplname ) {
|
208 |
array_unshift( $ao_ccss_types, 'template_' . $tplfile );
|
209 |
}
|
@@ -529,17 +554,17 @@ class autoptimizeCriticalCSSCore {
|
|
529 |
// Perform basic exploit avoidance and CSS validation.
|
530 |
if ( ! empty( $ccss ) ) {
|
531 |
// Try to avoid code injection.
|
532 |
-
$
|
533 |
-
foreach ( $
|
534 |
-
if ( strpos( $ccss, $
|
535 |
-
autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS received contained
|
536 |
return false;
|
537 |
}
|
538 |
}
|
539 |
|
540 |
// Check for most basics CSS structures.
|
541 |
-
$
|
542 |
-
foreach ( $
|
543 |
if ( false === strpos( $ccss, $needed ) && 'none' !== $ccss ) {
|
544 |
autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS received did not seem to contain real CSS.', 2 );
|
545 |
return false;
|
@@ -589,4 +614,10 @@ class autoptimizeCriticalCSSCore {
|
|
589 |
error_log( $message, 3, AO_CCSS_LOG );
|
590 |
}
|
591 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
592 |
}
|
25 |
global $ao_css_defer;
|
26 |
global $ao_ccss_deferjquery;
|
27 |
global $ao_ccss_key;
|
28 |
+
global $ao_ccss_unloadccss;
|
29 |
|
30 |
// add all filters to do CCSS if key present.
|
31 |
if ( $ao_css_defer && isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) ) {
|
41 |
add_filter( 'autoptimize_html_after_minify', array( $this, 'ao_ccss_defer_jquery' ), 11, 1 );
|
42 |
}
|
43 |
|
44 |
+
// conditionally add filter to unload the CCSS.
|
45 |
+
if ( $ao_ccss_unloadccss ) {
|
46 |
+
add_filter( 'autoptimize_html_after_minify', array( $this, 'ao_ccss_unloadccss' ), 12, 1 );
|
47 |
+
}
|
48 |
+
|
49 |
// Order paths by length, as longest ones have greater priority in the rules.
|
50 |
if ( ! empty( $ao_ccss_rules['paths'] ) ) {
|
51 |
$keys = array_map( 'strlen', array_keys( $ao_ccss_rules['paths'] ) );
|
59 |
|
60 |
// Extend conditional tags on plugin initalization.
|
61 |
add_action( apply_filters( 'autoptimize_filter_ccss_extend_types_hook', 'init' ), array( $this, 'ao_ccss_extend_types' ) );
|
62 |
+
|
63 |
+
// When autoptimize cache is cleared, also clear transient cache for page templates.
|
64 |
+
add_action( 'autoptimize_action_cachepurged', array( 'autoptimizeCriticalCSSCore', 'ao_ccss_clear_page_tpl_cache' ), 10, 0 );
|
65 |
}
|
66 |
}
|
67 |
|
170 |
}
|
171 |
|
172 |
public function ao_ccss_defer_jquery( $in ) {
|
173 |
+
global $ao_ccss_loggedin;
|
174 |
+
// defer all linked and inline JS.
|
175 |
if ( ( ! is_user_logged_in() || $ao_ccss_loggedin ) && preg_match_all( '#<script.*>(.*)</script>#Usmi', $in, $matches, PREG_SET_ORDER ) ) {
|
176 |
foreach ( $matches as $match ) {
|
177 |
+
if ( str_replace( apply_filters( 'autoptimize_filter_ccss_core_defer_exclude', array( 'data-noptimize="1"', 'data-cfasync="false"', 'data-pagespeed-no-defer' ) ), '', $match[0] ) !== $match[0] ) {
|
178 |
+
// do not touch JS with noptimize/ cfasync/ pagespeed-no-defer flags.
|
179 |
+
continue;
|
180 |
+
} elseif ( '' !== $match[1] && ( ! preg_match( '/<script.* type\s?=.*>/', $match[0] ) || preg_match( '/type\s*=\s*[\'"]?(?:text|application)\/(?:javascript|ecmascript)[\'"]?/i', $match[0] ) ) ) {
|
181 |
+
// base64-encode and defer all inline JS.
|
182 |
+
$base64_js = '<script defer src="data:text/javascript;base64,' . base64_encode( $match[1] ) . '"></script>';
|
183 |
+
$in = str_replace( $match[0], $base64_js, $in );
|
184 |
+
} elseif ( str_replace( array( ' defer', ' async' ), '', $match[0] ) === $match[0] ) {
|
185 |
+
// and defer linked JS unless already deferred or asynced.
|
186 |
$new_match = str_replace( '<script ', '<script defer ', $match[0] );
|
187 |
$in = str_replace( $match[0], $new_match, $in );
|
188 |
}
|
191 |
return $in;
|
192 |
}
|
193 |
|
194 |
+
public function ao_ccss_unloadccss( $html_in ) {
|
195 |
+
// set media attrib of inline CCSS to none at onLoad to avoid it impacting full CSS (rarely needed).
|
196 |
+
$_unloadccss_js = apply_filters( 'autoptimize_filter_ccss_core_unloadccss_js', '<script>window.addEventListener("load", function(event) {document.getElementById("aoatfcss").media="none";})</script>' );
|
197 |
+
|
198 |
+
return str_replace( '</body>', $_unloadccss_js . '</body>', $html_in );
|
199 |
+
}
|
200 |
+
|
201 |
public function ao_ccss_extend_types() {
|
202 |
// Extend contidional tags
|
203 |
// Attach the conditional tags array.
|
223 |
}
|
224 |
|
225 |
// Templates.
|
226 |
+
// Transient cache to avoid frequent disk reads.
|
227 |
+
$templates = get_transient( 'autoptimize_ccss_page_templates' );
|
228 |
+
if ( ! $templates ) {
|
229 |
+
$templates = wp_get_theme()->get_page_templates();
|
230 |
+
set_transient( 'autoptimize_ccss_page_templates', $templates, HOUR_IN_SECONDS );
|
231 |
+
}
|
232 |
foreach ( $templates as $tplfile => $tplname ) {
|
233 |
array_unshift( $ao_ccss_types, 'template_' . $tplfile );
|
234 |
}
|
554 |
// Perform basic exploit avoidance and CSS validation.
|
555 |
if ( ! empty( $ccss ) ) {
|
556 |
// Try to avoid code injection.
|
557 |
+
$blocklist = array( '#!/', 'function(', '<script', '<?php' );
|
558 |
+
foreach ( $blocklist as $blocklisted ) {
|
559 |
+
if ( strpos( $ccss, $blocklisted ) !== false ) {
|
560 |
+
autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS received contained blocklisted content.', 2 );
|
561 |
return false;
|
562 |
}
|
563 |
}
|
564 |
|
565 |
// Check for most basics CSS structures.
|
566 |
+
$needlist = array( '{', '}', ':' );
|
567 |
+
foreach ( $needlist as $needed ) {
|
568 |
if ( false === strpos( $ccss, $needed ) && 'none' !== $ccss ) {
|
569 |
autoptimizeCriticalCSSCore::ao_ccss_log( 'Critical CSS received did not seem to contain real CSS.', 2 );
|
570 |
return false;
|
614 |
error_log( $message, 3, AO_CCSS_LOG );
|
615 |
}
|
616 |
}
|
617 |
+
|
618 |
+
public static function ao_ccss_clear_page_tpl_cache() {
|
619 |
+
// Clears transient cache for page templates.
|
620 |
+
delete_transient( 'autoptimize_ccss_page_templates' );
|
621 |
+
}
|
622 |
+
|
623 |
}
|
classes/autoptimizeCriticalCSSCron.php
CHANGED
@@ -141,7 +141,11 @@ class autoptimizeCriticalCSSCron {
|
|
141 |
// Update job properties.
|
142 |
$jprops['jid'] = $apireq['job']['id'];
|
143 |
$jprops['jqstat'] = $apireq['job']['status'];
|
144 |
-
$
|
|
|
|
|
|
|
|
|
145 |
$jprops['jvstat'] = 'NONE';
|
146 |
$jprops['jftime'] = microtime( true );
|
147 |
autoptimizeCriticalCSSCore::ao_ccss_log( 'Concurrent requests when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 );
|
@@ -269,9 +273,10 @@ class autoptimizeCriticalCSSCron {
|
|
269 |
// ERROR: failed job
|
270 |
// Update job properties.
|
271 |
$jprops['jqstat'] = $apireq['job']['status'];
|
272 |
-
if ( $apireq['error'] ) {
|
273 |
$jprops['jrstat'] = $apireq['job']['error'];
|
274 |
} else {
|
|
|
275 |
}
|
276 |
$jprops['jvstat'] = 'NONE';
|
277 |
$jprops['jftime'] = microtime( true );
|
141 |
// Update job properties.
|
142 |
$jprops['jid'] = $apireq['job']['id'];
|
143 |
$jprops['jqstat'] = $apireq['job']['status'];
|
144 |
+
if ( $apireq['job']['error'] ) {
|
145 |
+
$jprops['jrstat'] = $apireq['job']['error'];
|
146 |
+
} else {
|
147 |
+
$jprops['jrstat'] = 'Baby did a bad bad thing';
|
148 |
+
}
|
149 |
$jprops['jvstat'] = 'NONE';
|
150 |
$jprops['jftime'] = microtime( true );
|
151 |
autoptimizeCriticalCSSCore::ao_ccss_log( 'Concurrent requests when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 );
|
273 |
// ERROR: failed job
|
274 |
// Update job properties.
|
275 |
$jprops['jqstat'] = $apireq['job']['status'];
|
276 |
+
if ( $apireq['job']['error'] ) {
|
277 |
$jprops['jrstat'] = $apireq['job']['error'];
|
278 |
} else {
|
279 |
+
$jprops['jrstat'] = 'Baby did a bad bad thing';
|
280 |
}
|
281 |
$jprops['jvstat'] = 'NONE';
|
282 |
$jprops['jftime'] = microtime( true );
|
classes/autoptimizeCriticalCSSEnqueue.php
CHANGED
@@ -27,7 +27,7 @@ class autoptimizeCriticalCSSEnqueue {
|
|
27 |
$enqueue = true;
|
28 |
|
29 |
// ... which are not the ones below.
|
30 |
-
if ( is_user_logged_in() || is_feed() || is_404() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || $self->ao_ccss_ua() || 'nokey' == $key['status'] || 'invalid' == $key['status'] ) {
|
31 |
$enqueue = false;
|
32 |
autoptimizeCriticalCSSCore::ao_ccss_log( "Job queuing is not available for WordPress's logged in users, feeds, error pages, ajax calls, to criticalcss.com itself or when a valid API key is not found", 3 );
|
33 |
}
|
@@ -91,8 +91,8 @@ class autoptimizeCriticalCSSEnqueue {
|
|
91 |
}
|
92 |
}
|
93 |
|
94 |
-
if ( $job_qualify && false == $rule_properties['hash'] && false != $rule_properties['file'] ) {
|
95 |
-
// If job qualifies but rule hash is false and file isn't false
|
96 |
$job_qualify = false;
|
97 |
autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission DISQUALIFIED by MANUAL rule <' . $target_rule . '> with hash <' . $rule_properties['hash'] . '> and file <' . $rule_properties['file'] . '>', 3 );
|
98 |
} elseif ( ! $job_qualify && empty( $rule_properties ) ) {
|
@@ -205,7 +205,11 @@ class autoptimizeCriticalCSSEnqueue {
|
|
205 |
break;
|
206 |
}
|
207 |
} elseif ( strpos( $type, 'template_' ) !== false ) {
|
208 |
-
//
|
|
|
|
|
|
|
|
|
209 |
} else {
|
210 |
// Match all other existing types
|
211 |
// but remove prefix to be able to check if the function exists & returns true.
|
27 |
$enqueue = true;
|
28 |
|
29 |
// ... which are not the ones below.
|
30 |
+
if ( is_user_logged_in() || is_feed() || is_404() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || $self->ao_ccss_ua() || 'nokey' == $key['status'] || 'invalid' == $key['status'] || false === apply_filters( 'autoptimize_filter_ccss_enqueue_should_enqueue', true ) ) {
|
31 |
$enqueue = false;
|
32 |
autoptimizeCriticalCSSCore::ao_ccss_log( "Job queuing is not available for WordPress's logged in users, feeds, error pages, ajax calls, to criticalcss.com itself or when a valid API key is not found", 3 );
|
33 |
}
|
91 |
}
|
92 |
}
|
93 |
|
94 |
+
if ( $job_qualify && ( ( false == $rule_properties['hash'] && false != $rule_properties['file'] ) || strpos( $req_type, 'template_' ) !== false ) ) {
|
95 |
+
// If job qualifies but rule hash is false and file isn't false (MANUAL rule) or if template, job does not qualify despite what previous evaluations says.
|
96 |
$job_qualify = false;
|
97 |
autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission DISQUALIFIED by MANUAL rule <' . $target_rule . '> with hash <' . $rule_properties['hash'] . '> and file <' . $rule_properties['file'] . '>', 3 );
|
98 |
} elseif ( ! $job_qualify && empty( $rule_properties ) ) {
|
205 |
break;
|
206 |
}
|
207 |
} elseif ( strpos( $type, 'template_' ) !== false ) {
|
208 |
+
// Match templates.
|
209 |
+
if ( is_page_template( substr( $type, 9 ) ) ) {
|
210 |
+
$page_type = $type;
|
211 |
+
break;
|
212 |
+
}
|
213 |
} else {
|
214 |
// Match all other existing types
|
215 |
// but remove prefix to be able to check if the function exists & returns true.
|
classes/autoptimizeCriticalCSSSettings.php
CHANGED
@@ -67,6 +67,7 @@ class autoptimizeCriticalCSSSettings {
|
|
67 |
register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_forcepath' );
|
68 |
register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_deferjquery' );
|
69 |
register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_domain' );
|
|
|
70 |
|
71 |
// And add submenu-page.
|
72 |
add_submenu_page( null, 'Critical CSS', 'Critical CSS', 'manage_options', 'ao_critcss', array( $this, 'ao_criticalcsssettings_page' ) );
|
@@ -106,6 +107,7 @@ class autoptimizeCriticalCSSSettings {
|
|
106 |
${$_option} = $_value;
|
107 |
}
|
108 |
?>
|
|
|
109 |
<div class="wrap">
|
110 |
<div id="autoptimize_main">
|
111 |
<div id="ao_title_and_button">
|
67 |
register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_forcepath' );
|
68 |
register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_deferjquery' );
|
69 |
register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_domain' );
|
70 |
+
register_setting( 'ao_ccss_options_group', 'autoptimize_ccss_unloadccss' );
|
71 |
|
72 |
// And add submenu-page.
|
73 |
add_submenu_page( null, 'Critical CSS', 'Critical CSS', 'manage_options', 'ao_critcss', array( $this, 'ao_criticalcsssettings_page' ) );
|
107 |
${$_option} = $_value;
|
108 |
}
|
109 |
?>
|
110 |
+
<script>document.title = "Autoptimize: <?php _e( 'Critical CSS', 'autoptimize' ); ?> " + document.title;</script>
|
111 |
<div class="wrap">
|
112 |
<div id="autoptimize_main">
|
113 |
<div id="ao_title_and_button">
|
classes/autoptimizeImages.php
CHANGED
@@ -489,6 +489,19 @@ class autoptimizeImages
|
|
489 |
}
|
490 |
}
|
491 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
492 |
public function filter_optimize_images( $in )
|
493 |
{
|
494 |
/*
|
@@ -609,6 +622,15 @@ class autoptimizeImages
|
|
609 |
);
|
610 |
}
|
611 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
612 |
// lazyload: restore noscript tags + lazyload picture source tags and bgimage.
|
613 |
if ( $this->should_lazyload() ) {
|
614 |
$out = autoptimizeBase::restore_marked_content(
|
@@ -788,6 +810,7 @@ class autoptimizeImages
|
|
788 |
$lazysizes_js = plugins_url( 'external/js/lazysizes.min.js?ao_version=' . AUTOPTIMIZE_PLUGIN_VERSION, __FILE__ );
|
789 |
$cdn_url = $this->get_cdn_url();
|
790 |
if ( ! empty( $cdn_url ) ) {
|
|
|
791 |
$lazysizes_js = str_replace( AUTOPTIMIZE_WP_SITE_URL, $cdn_url, $lazysizes_js );
|
792 |
}
|
793 |
|
@@ -797,14 +820,14 @@ class autoptimizeImages
|
|
797 |
}
|
798 |
|
799 |
// Adds lazyload CSS & JS to footer, using echo because wp_enqueue_script seems not to support pushing attributes (async).
|
800 |
-
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_cssoutput', '<
|
801 |
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_jsconfig', '<script' . $type_js . $noptimize_flag . '>window.lazySizesConfig=window.lazySizesConfig||{};window.lazySizesConfig.loadMode=1;</script>' );
|
802 |
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_js', '<script async' . $type_js . $noptimize_flag . ' src=\'' . $lazysizes_js . '\'></script>' );
|
803 |
|
804 |
// And add webp detection and loading JS.
|
805 |
if ( $this->should_webp() ) {
|
806 |
$_webp_detect = "function c_webp(A){var n=new Image;n.onload=function(){var e=0<n.width&&0<n.height;A(e)},n.onerror=function(){A(!1)},n.src='data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA=='}function s_webp(e){window.supportsWebP=e}c_webp(s_webp);";
|
807 |
-
$_webp_load = "document.addEventListener('lazybeforeunveil',function({target:
|
808 |
echo apply_filters( 'autoptimize_filter_imgopt_webp_js', '<script' . $type_js . $noptimize_flag . '>' . $_webp_detect . $_webp_load . '</script>' );
|
809 |
}
|
810 |
}
|
489 |
}
|
490 |
}
|
491 |
|
492 |
+
public function replace_icon_callback( $matches )
|
493 |
+
{
|
494 |
+
if ( array_key_exists( '2', $matches ) ) {
|
495 |
+
$sizes = explode( 'x', $matches[2] );
|
496 |
+
$width = $sizes[0];
|
497 |
+
$height = $sizes[1];
|
498 |
+
} else {
|
499 |
+
$width = 180;
|
500 |
+
$height = 180;
|
501 |
+
}
|
502 |
+
return $this->replace_img_callback( $matches, $width, $height );
|
503 |
+
}
|
504 |
+
|
505 |
public function filter_optimize_images( $in )
|
506 |
{
|
507 |
/*
|
622 |
);
|
623 |
}
|
624 |
|
625 |
+
// act on icon links.
|
626 |
+
if ( ( strpos( $out, '<link rel="icon"' ) !== false || ( strpos( $out, "<link rel='icon'" ) !== false ) ) && apply_filters( 'autoptimize_filter_imgopt_linkicon', true ) ) {
|
627 |
+
$out = preg_replace_callback(
|
628 |
+
'/<link\srel=(?:"|\')(?:apple-touch-)?icon(?:"|\').*\shref=(?:"|\')(.*)(?:"|\')(?:\ssizes=(?:"|\')(\d*x\d*)(?:"|\'))?\s\/>/Um',
|
629 |
+
array( $this, 'replace_icon_callback' ),
|
630 |
+
$out
|
631 |
+
);
|
632 |
+
}
|
633 |
+
|
634 |
// lazyload: restore noscript tags + lazyload picture source tags and bgimage.
|
635 |
if ( $this->should_lazyload() ) {
|
636 |
$out = autoptimizeBase::restore_marked_content(
|
810 |
$lazysizes_js = plugins_url( 'external/js/lazysizes.min.js?ao_version=' . AUTOPTIMIZE_PLUGIN_VERSION, __FILE__ );
|
811 |
$cdn_url = $this->get_cdn_url();
|
812 |
if ( ! empty( $cdn_url ) ) {
|
813 |
+
$cdn_url = rtrim( $cdn_url, '/' );
|
814 |
$lazysizes_js = str_replace( AUTOPTIMIZE_WP_SITE_URL, $cdn_url, $lazysizes_js );
|
815 |
}
|
816 |
|
820 |
}
|
821 |
|
822 |
// Adds lazyload CSS & JS to footer, using echo because wp_enqueue_script seems not to support pushing attributes (async).
|
823 |
+
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_cssoutput', '<noscript><style>.lazyload{display:none;}</style></noscript>' );
|
824 |
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_jsconfig', '<script' . $type_js . $noptimize_flag . '>window.lazySizesConfig=window.lazySizesConfig||{};window.lazySizesConfig.loadMode=1;</script>' );
|
825 |
echo apply_filters( 'autoptimize_filter_imgopt_lazyload_js', '<script async' . $type_js . $noptimize_flag . ' src=\'' . $lazysizes_js . '\'></script>' );
|
826 |
|
827 |
// And add webp detection and loading JS.
|
828 |
if ( $this->should_webp() ) {
|
829 |
$_webp_detect = "function c_webp(A){var n=new Image;n.onload=function(){var e=0<n.width&&0<n.height;A(e)},n.onerror=function(){A(!1)},n.src='data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA=='}function s_webp(e){window.supportsWebP=e}c_webp(s_webp);";
|
830 |
+
$_webp_load = "document.addEventListener('lazybeforeunveil',function({target:b}){window.supportsWebP&&['data-src','data-srcset'].forEach(function(c){attr=b.getAttribute(c),null!==attr&&-1==attr.indexOf('/client/to_webp')&&b.setAttribute(c,attr.replace(/\/client\//,'/client/to_webp,'))})});";
|
831 |
echo apply_filters( 'autoptimize_filter_imgopt_webp_js', '<script' . $type_js . $noptimize_flag . '>' . $_webp_detect . $_webp_load . '</script>' );
|
832 |
}
|
833 |
}
|
classes/autoptimizeMain.php
CHANGED
@@ -585,6 +585,7 @@ class autoptimizeMain
|
|
585 |
'autoptimize_ccss_forcepath',
|
586 |
'autoptimize_ccss_deferjquery',
|
587 |
'autoptimize_ccss_domain',
|
|
|
588 |
);
|
589 |
|
590 |
if ( ! is_multisite() ) {
|
585 |
'autoptimize_ccss_forcepath',
|
586 |
'autoptimize_ccss_deferjquery',
|
587 |
'autoptimize_ccss_domain',
|
588 |
+
'autoptimize_ccss_unloadccss',
|
589 |
);
|
590 |
|
591 |
if ( ! is_multisite() ) {
|
classes/autoptimizeScripts.php
CHANGED
@@ -165,11 +165,11 @@ class autoptimizeScripts extends autoptimizeBase
|
|
165 |
private $md5hash = '';
|
166 |
|
167 |
/**
|
168 |
-
* Setting (filter);
|
169 |
*
|
170 |
* @var string
|
171 |
*/
|
172 |
-
private $
|
173 |
|
174 |
/**
|
175 |
* Setting (filter); holds JS that should be removed.
|
@@ -206,9 +206,10 @@ class autoptimizeScripts extends autoptimizeBase
|
|
206 |
}
|
207 |
|
208 |
// only optimize known good JS?
|
209 |
-
$
|
210 |
-
|
211 |
-
|
|
|
212 |
}
|
213 |
|
214 |
// is there JS we should simply remove?
|
@@ -301,7 +302,7 @@ class autoptimizeScripts extends autoptimizeBase
|
|
301 |
// Get script files.
|
302 |
if ( preg_match_all( '#<script.*</script>#Usmi', $this->content, $matches ) ) {
|
303 |
foreach ( $matches[0] as $tag ) {
|
304 |
-
// only consider script aggregation for types
|
305 |
$should_aggregate = $this->should_aggregate( $tag );
|
306 |
if ( ! $should_aggregate ) {
|
307 |
$tag = '';
|
@@ -602,7 +603,7 @@ class autoptimizeScripts extends autoptimizeBase
|
|
602 |
}
|
603 |
|
604 |
/**
|
605 |
-
* Checks against the
|
606 |
*
|
607 |
* @param string $tag JS tag.
|
608 |
*/
|
@@ -612,13 +613,13 @@ class autoptimizeScripts extends autoptimizeBase
|
|
612 |
return false;
|
613 |
}
|
614 |
|
615 |
-
if ( ! empty( $this->
|
616 |
-
foreach ( $this->
|
617 |
if ( false !== strpos( $tag, $match ) ) {
|
618 |
return true;
|
619 |
}
|
620 |
}
|
621 |
-
// No match with
|
622 |
return false;
|
623 |
} else {
|
624 |
foreach ( $this->domove as $match ) {
|
@@ -645,9 +646,9 @@ class autoptimizeScripts extends autoptimizeBase
|
|
645 |
}
|
646 |
|
647 |
/**
|
648 |
-
* Checks agains the
|
649 |
*
|
650 |
-
* @param string $tag tag to check for
|
651 |
*/
|
652 |
private function ismovable( $tag )
|
653 |
{
|
@@ -757,6 +758,9 @@ class autoptimizeScripts extends autoptimizeBase
|
|
757 |
return false;
|
758 |
}
|
759 |
|
|
|
|
|
|
|
760 |
// Store in cache.
|
761 |
$cache->cache( $contents, 'text/javascript' );
|
762 |
}
|
165 |
private $md5hash = '';
|
166 |
|
167 |
/**
|
168 |
+
* Setting (filter); allowlist of to be aggregated JS.
|
169 |
*
|
170 |
* @var string
|
171 |
*/
|
172 |
+
private $allowlist = '';
|
173 |
|
174 |
/**
|
175 |
* Setting (filter); holds JS that should be removed.
|
206 |
}
|
207 |
|
208 |
// only optimize known good JS?
|
209 |
+
$allowlist_js = apply_filters( 'autoptimize_filter_js_allowlist', '', $this->content );
|
210 |
+
$allowlist_js = apply_filters( 'autoptimize_filter_js_whitelist', $allowlist_js, $this->content ); // fixme: to be removed in next version.
|
211 |
+
if ( ! empty( $allowlist_js ) ) {
|
212 |
+
$this->allowlist = array_filter( array_map( 'trim', explode( ',', $allowlist_js ) ) );
|
213 |
}
|
214 |
|
215 |
// is there JS we should simply remove?
|
302 |
// Get script files.
|
303 |
if ( preg_match_all( '#<script.*</script>#Usmi', $this->content, $matches ) ) {
|
304 |
foreach ( $matches[0] as $tag ) {
|
305 |
+
// only consider script aggregation for types allowlisted in should_aggregate-function.
|
306 |
$should_aggregate = $this->should_aggregate( $tag );
|
307 |
if ( ! $should_aggregate ) {
|
308 |
$tag = '';
|
603 |
}
|
604 |
|
605 |
/**
|
606 |
+
* Checks against the allow- and blocklists.
|
607 |
*
|
608 |
* @param string $tag JS tag.
|
609 |
*/
|
613 |
return false;
|
614 |
}
|
615 |
|
616 |
+
if ( ! empty( $this->allowlist ) ) {
|
617 |
+
foreach ( $this->allowlist as $match ) {
|
618 |
if ( false !== strpos( $tag, $match ) ) {
|
619 |
return true;
|
620 |
}
|
621 |
}
|
622 |
+
// No match with allowlist.
|
623 |
return false;
|
624 |
} else {
|
625 |
foreach ( $this->domove as $match ) {
|
646 |
}
|
647 |
|
648 |
/**
|
649 |
+
* Checks agains the blocklist.
|
650 |
*
|
651 |
+
* @param string $tag tag to check for blocklist (exclusions).
|
652 |
*/
|
653 |
private function ismovable( $tag )
|
654 |
{
|
758 |
return false;
|
759 |
}
|
760 |
|
761 |
+
// Filter contents of excluded minified CSS.
|
762 |
+
$contents = apply_filters( 'autoptimize_filter_js_single_after_minify', $contents );
|
763 |
+
|
764 |
// Store in cache.
|
765 |
$cache->cache( $contents, 'text/javascript' );
|
766 |
}
|
classes/autoptimizeStyles.php
CHANGED
@@ -94,11 +94,11 @@ class autoptimizeStyles extends autoptimizeBase
|
|
94 |
private $defer_inline = '';
|
95 |
|
96 |
/**
|
97 |
-
* Setting for
|
98 |
*
|
99 |
* @var string
|
100 |
*/
|
101 |
-
private $
|
102 |
|
103 |
/**
|
104 |
* Setting (only filter) for size under which CSS should be inlined instead of linked.
|
@@ -168,9 +168,10 @@ class autoptimizeStyles extends autoptimizeBase
|
|
168 |
return false;
|
169 |
}
|
170 |
|
171 |
-
$
|
172 |
-
|
173 |
-
|
|
|
174 |
}
|
175 |
|
176 |
$removable_css = apply_filters( 'autoptimize_filter_css_removables', '' );
|
@@ -383,23 +384,27 @@ class autoptimizeStyles extends autoptimizeBase
|
|
383 |
{
|
384 |
// Defer single CSS if "inline & defer" is ON and there is inline CSS.
|
385 |
if ( ! empty( $tag ) && false === strpos( $tag, ' onload=' ) && $this->defer && ! empty( $this->defer_inline ) && apply_filters( 'autoptimize_filter_css_defer_excluded', true, $tag ) ) {
|
386 |
-
//
|
387 |
-
$
|
388 |
-
'
|
389 |
-
|
390 |
-
|
391 |
-
|
|
|
|
|
392 |
|
393 |
// Adapt original <link> element for CSS to be preloaded and add <noscript>-version for fallback.
|
394 |
$new_tag = '<noscript>' . autoptimizeUtils::remove_id_from_node( $tag ) . '</noscript>' . str_replace(
|
395 |
-
|
396 |
-
|
397 |
-
'rel="stylesheet"',
|
398 |
-
),
|
399 |
-
"rel='preload' as='style' onload=\"" . $_preload_onload . '"',
|
400 |
$tag
|
401 |
);
|
402 |
|
|
|
|
|
|
|
|
|
|
|
403 |
return $new_tag;
|
404 |
}
|
405 |
|
@@ -978,7 +983,7 @@ class autoptimizeStyles extends autoptimizeBase
|
|
978 |
|
979 |
if ( $this->inline ) {
|
980 |
foreach ( $this->csscode as $media => $code ) {
|
981 |
-
$this->inject_in_html( '<style ' . $type_css . 'media="' . $media . '">' . $code . '</style>', $replace_tag );
|
982 |
}
|
983 |
} else {
|
984 |
if ( $this->defer ) {
|
@@ -1018,28 +1023,24 @@ class autoptimizeStyles extends autoptimizeBase
|
|
1018 |
if ( $this->defer ) {
|
1019 |
$preload_onload = autoptimizeConfig::get_ao_css_preload_onload();
|
1020 |
|
1021 |
-
$preload_css_block
|
|
|
|
|
|
|
1022 |
$noscript_css_block .= '<link ' . $type_css . 'media="' . $media . '" href="' . $url . '" rel="stylesheet" />';
|
1023 |
} else {
|
1024 |
if ( strlen( $this->csscode[ $media ] ) > $this->cssinlinesize ) {
|
1025 |
-
$this->inject_in_html( '<link ' . $type_css . 'media="' . $media . '" href="' . $url . '" rel="stylesheet" />', $replace_tag );
|
1026 |
} elseif ( strlen( $this->csscode[ $media ] ) > 0 ) {
|
1027 |
-
$this->inject_in_html( '<style ' . $type_css . 'media="' . $media . '">' . $this->csscode[ $media ] . '</style>', $replace_tag );
|
1028 |
}
|
1029 |
}
|
1030 |
}
|
1031 |
|
1032 |
if ( $this->defer ) {
|
1033 |
-
$preload_polyfill = autoptimizeConfig::get_ao_css_preload_polyfill();
|
1034 |
$noscript_css_block .= '</noscript>';
|
1035 |
// Inject inline critical CSS, the preloaded full CSS and the noscript-CSS.
|
1036 |
-
$this->inject_in_html( $inlined_ccss_block . $preload_css_block . $noscript_css_block, $replace_tag );
|
1037 |
-
|
1038 |
-
// Adds preload polyfill at end of body tag.
|
1039 |
-
$this->inject_in_html(
|
1040 |
-
apply_filters( 'autoptimize_css_preload_polyfill', $preload_polyfill ),
|
1041 |
-
apply_filters( 'autoptimize_css_preload_polyfill_injectat', array( '</body>', 'before' ) )
|
1042 |
-
);
|
1043 |
}
|
1044 |
}
|
1045 |
|
@@ -1142,13 +1143,13 @@ class autoptimizeStyles extends autoptimizeBase
|
|
1142 |
return false;
|
1143 |
}
|
1144 |
|
1145 |
-
if ( ! empty( $this->
|
1146 |
-
foreach ( $this->
|
1147 |
if ( false !== strpos( $tag, $match ) ) {
|
1148 |
return true;
|
1149 |
}
|
1150 |
}
|
1151 |
-
// no match with
|
1152 |
return false;
|
1153 |
} else {
|
1154 |
if ( is_array( $this->dontmove ) && ! empty( $this->dontmove ) ) {
|
@@ -1228,6 +1229,9 @@ class autoptimizeStyles extends autoptimizeBase
|
|
1228 |
return false;
|
1229 |
}
|
1230 |
|
|
|
|
|
|
|
1231 |
// Store in cache.
|
1232 |
$cache->cache( $contents, 'text/css' );
|
1233 |
}
|
94 |
private $defer_inline = '';
|
95 |
|
96 |
/**
|
97 |
+
* Setting for allowlist of what should be aggregated.
|
98 |
*
|
99 |
* @var string
|
100 |
*/
|
101 |
+
private $allowlist = '';
|
102 |
|
103 |
/**
|
104 |
* Setting (only filter) for size under which CSS should be inlined instead of linked.
|
168 |
return false;
|
169 |
}
|
170 |
|
171 |
+
$allowlist_css = apply_filters( 'autoptimize_filter_css_allowlist', '', $this->content );
|
172 |
+
$allowlist_css = apply_filters( 'autoptimize_filter_css_whitelist', $allowlist_css, $this->content ); // fixme: to be removed in next version.
|
173 |
+
if ( ! empty( $allowlist_css ) ) {
|
174 |
+
$this->allowlist = array_filter( array_map( 'trim', explode( ',', $allowlist_css ) ) );
|
175 |
}
|
176 |
|
177 |
$removable_css = apply_filters( 'autoptimize_filter_css_removables', '' );
|
384 |
{
|
385 |
// Defer single CSS if "inline & defer" is ON and there is inline CSS.
|
386 |
if ( ! empty( $tag ) && false === strpos( $tag, ' onload=' ) && $this->defer && ! empty( $this->defer_inline ) && apply_filters( 'autoptimize_filter_css_defer_excluded', true, $tag ) ) {
|
387 |
+
// get media attribute and based on that create onload JS attribute value.
|
388 |
+
if ( false !== strpos( $tag, 'media=' ) ) {
|
389 |
+
preg_match( '#media=(?:"|\')([^>]*)(?:"|\')#Ui', $tag, $_medias );
|
390 |
+
$_media = $_medias[1];
|
391 |
+
} else {
|
392 |
+
$_media = 'all';
|
393 |
+
}
|
394 |
+
$_preload_onload = autoptimizeConfig::get_ao_css_preload_onload( $_media );
|
395 |
|
396 |
// Adapt original <link> element for CSS to be preloaded and add <noscript>-version for fallback.
|
397 |
$new_tag = '<noscript>' . autoptimizeUtils::remove_id_from_node( $tag ) . '</noscript>' . str_replace(
|
398 |
+
$_medias[0],
|
399 |
+
"media='print' onload=\"" . $_preload_onload . '"',
|
|
|
|
|
|
|
400 |
$tag
|
401 |
);
|
402 |
|
403 |
+
// Optionally (but default false) preload the (excluded) CSS-file.
|
404 |
+
if ( apply_filters( 'autoptimize_fitler_css_preload_and_print', false ) && 'none' !== $url ) {
|
405 |
+
$new_tag = '<link rel="preload" as="stylesheet" href="' . $url . '"/>' . $new_tag;
|
406 |
+
}
|
407 |
+
|
408 |
return $new_tag;
|
409 |
}
|
410 |
|
983 |
|
984 |
if ( $this->inline ) {
|
985 |
foreach ( $this->csscode as $media => $code ) {
|
986 |
+
$this->inject_in_html( apply_filters( 'autoptimize_filter_css_bodyreplacementpayload', '<style ' . $type_css . 'media="' . $media . '">' . $code . '</style>' ), $replace_tag );
|
987 |
}
|
988 |
} else {
|
989 |
if ( $this->defer ) {
|
1023 |
if ( $this->defer ) {
|
1024 |
$preload_onload = autoptimizeConfig::get_ao_css_preload_onload();
|
1025 |
|
1026 |
+
$preload_css_block .= '<link rel="stylesheet" media="print" href="' . $url . '" onload="' . $preload_onload . '" />';
|
1027 |
+
if ( apply_filters( 'autoptimize_fitler_css_preload_and_print', false ) ) {
|
1028 |
+
$preload_css_block = '<link rel="preload" as="stylesheet" href="' . $url . '"/>' . $preload_css_block;
|
1029 |
+
}
|
1030 |
$noscript_css_block .= '<link ' . $type_css . 'media="' . $media . '" href="' . $url . '" rel="stylesheet" />';
|
1031 |
} else {
|
1032 |
if ( strlen( $this->csscode[ $media ] ) > $this->cssinlinesize ) {
|
1033 |
+
$this->inject_in_html( apply_filters( 'autoptimize_filter_css_bodyreplacementpayload', '<link ' . $type_css . 'media="' . $media . '" href="' . $url . '" rel="stylesheet" />' ), $replace_tag );
|
1034 |
} elseif ( strlen( $this->csscode[ $media ] ) > 0 ) {
|
1035 |
+
$this->inject_in_html( apply_filters( 'autoptimize_filter_css_bodyreplacementpayload', '<style ' . $type_css . 'media="' . $media . '">' . $this->csscode[ $media ] . '</style>' ), $replace_tag );
|
1036 |
}
|
1037 |
}
|
1038 |
}
|
1039 |
|
1040 |
if ( $this->defer ) {
|
|
|
1041 |
$noscript_css_block .= '</noscript>';
|
1042 |
// Inject inline critical CSS, the preloaded full CSS and the noscript-CSS.
|
1043 |
+
$this->inject_in_html( apply_filters( 'autoptimize_filter_css_bodyreplacementpayload', $inlined_ccss_block . $preload_css_block . $noscript_css_block ), $replace_tag );
|
|
|
|
|
|
|
|
|
|
|
|
|
1044 |
}
|
1045 |
}
|
1046 |
|
1143 |
return false;
|
1144 |
}
|
1145 |
|
1146 |
+
if ( ! empty( $this->allowlist ) ) {
|
1147 |
+
foreach ( $this->allowlist as $match ) {
|
1148 |
if ( false !== strpos( $tag, $match ) ) {
|
1149 |
return true;
|
1150 |
}
|
1151 |
}
|
1152 |
+
// no match with allowlist.
|
1153 |
return false;
|
1154 |
} else {
|
1155 |
if ( is_array( $this->dontmove ) && ! empty( $this->dontmove ) ) {
|
1229 |
return false;
|
1230 |
}
|
1231 |
|
1232 |
+
// Filter contents of excluded minified CSS.
|
1233 |
+
$contents = apply_filters( 'autoptimize_filter_css_single_after_minify', $contents );
|
1234 |
+
|
1235 |
// Store in cache.
|
1236 |
$cache->cache( $contents, 'text/css' );
|
1237 |
}
|
classes/critcss-inc/admin_settings_adv.php
CHANGED
@@ -16,6 +16,7 @@ function ao_ccss_render_adv() {
|
|
16 |
global $ao_ccss_forcepath;
|
17 |
global $ao_ccss_deferjquery;
|
18 |
global $ao_ccss_domain;
|
|
|
19 |
|
20 |
// In case domain is not set yet (done in cron.php).
|
21 |
if ( empty( $ao_ccss_domain ) ) {
|
@@ -111,6 +112,17 @@ function ao_ccss_render_adv() {
|
|
111 |
</p>
|
112 |
</td>
|
113 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
<tr>
|
115 |
<th scope="row">
|
116 |
<?php _e( 'Bound domain', 'autoptimize' ); ?>
|
16 |
global $ao_ccss_forcepath;
|
17 |
global $ao_ccss_deferjquery;
|
18 |
global $ao_ccss_domain;
|
19 |
+
global $ao_ccss_unloadccss;
|
20 |
|
21 |
// In case domain is not set yet (done in cron.php).
|
22 |
if ( empty( $ao_ccss_domain ) ) {
|
112 |
</p>
|
113 |
</td>
|
114 |
</tr>
|
115 |
+
<tr>
|
116 |
+
<th scope="row">
|
117 |
+
<?php _e( 'Unload critical CSS after page load?', 'autoptimize' ); ?>
|
118 |
+
</th>
|
119 |
+
<td>
|
120 |
+
<input type="checkbox" id="autoptimize_ccss_unloadccss" name="autoptimize_ccss_unloadccss" value="1" <?php checked( 1 == $ao_ccss_unloadccss ); ?>>
|
121 |
+
<p class="notes">
|
122 |
+
<?php _e( 'In rare cases the critical CSS needs to be removed once the full CSS loads, this option makes it so!', 'autoptimize' ); ?>
|
123 |
+
</p>
|
124 |
+
</td>
|
125 |
+
</tr>
|
126 |
<tr>
|
127 |
<th scope="row">
|
128 |
<?php _e( 'Bound domain', 'autoptimize' ); ?>
|
readme.txt
CHANGED
@@ -3,9 +3,9 @@ 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.9
|
6 |
-
Tested up to: 5.
|
7 |
Requires PHP: 5.6
|
8 |
-
Stable tag: 2.7.
|
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 |
|
@@ -270,7 +270,7 @@ When both Autoptimize 2.7 and the separate Critical CSS power-up are installed a
|
|
270 |
|
271 |
Autoptimize caches aggregated & optimized CSS/ JS and links to those cached files are stored in the HTML, which will be stored in a page cache (which can be a plugin, can be at host level, can be at 3rd party, in the Google cache, in a browser). If there is HTML in a page cache that links to Autoptimized CSS/ JS that has been removed in the mean time (when the cache was cleared) then the page from cache will not look/ work as expected as the CSS or JS were not found (a 404 error).
|
272 |
|
273 |
-
This
|
274 |
|
275 |
When the option is enabled, Autoptimize adds an `ErrorDocument 404` to the .htaccess (as used by Apache) and will also hook into WordPress core `template_redirect` to capture 404's handled by Wordpress. When using NGINX something like below should work (I'm not an NGINX specialist, but it does work for me);
|
276 |
|
@@ -279,6 +279,22 @@ location ~* /wp-content/cache/autoptimize/.*\.(js|css)$ {
|
|
279 |
try_files $uri $uri/ /wp-content/autoptimize_404_handler.php;
|
280 |
}`
|
281 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
= Where can I get help? =
|
283 |
|
284 |
You can get help on the [wordpress.org support forum](http://wordpress.org/support/plugin/autoptimize). If you are 100% sure this your problem cannot be solved using Autoptimize configuration and that you in fact discovered a bug in the code, you can [create an issue on GitHub](https://github.com/futtta/autoptimize/issues). If you're looking for premium support, check out our [Autoptimize Pro Support and Web Performance Optimization services](http://autoptimize.com/).
|
@@ -295,6 +311,20 @@ Just [fork Autoptimize on Github](https://github.com/futtta/autoptimize) and cod
|
|
295 |
|
296 |
== Changelog ==
|
297 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
298 |
= 2.7.3 =
|
299 |
* Critical CSS: cache settings in the PHP process instead of re-fetching them
|
300 |
* Critical CSS: shorter intervals between calls to criticalcss.com (shortening the asynchronous job queue processing time)
|
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.9
|
6 |
+
Tested up to: 5.5
|
7 |
Requires PHP: 5.6
|
8 |
+
Stable tag: 2.7.4
|
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 |
|
270 |
|
271 |
Autoptimize caches aggregated & optimized CSS/ JS and links to those cached files are stored in the HTML, which will be stored in a page cache (which can be a plugin, can be at host level, can be at 3rd party, in the Google cache, in a browser). If there is HTML in a page cache that links to Autoptimized CSS/ JS that has been removed in the mean time (when the cache was cleared) then the page from cache will not look/ work as expected as the CSS or JS were not found (a 404 error).
|
272 |
|
273 |
+
This setting aims to prevent things from breaking by serving "fallback" CSS or JS. The fallback-files are copies of the first Autoptimized CSS & JS files created after the cache was emptied and as such will based on the homepage. This means that the CSS/ JS migth not apply 100% on other pages, but at least the impact of missing CSS/ JS will be lessened (often significantly).
|
274 |
|
275 |
When the option is enabled, Autoptimize adds an `ErrorDocument 404` to the .htaccess (as used by Apache) and will also hook into WordPress core `template_redirect` to capture 404's handled by Wordpress. When using NGINX something like below should work (I'm not an NGINX specialist, but it does work for me);
|
276 |
|
279 |
try_files $uri $uri/ /wp-content/autoptimize_404_handler.php;
|
280 |
}`
|
281 |
|
282 |
+
= What open source software/ projects are used in Autoptimize? =
|
283 |
+
|
284 |
+
The following great open source projects are used in Autoptimize in some form or another:
|
285 |
+
|
286 |
+
* [Mr Clay's Minify](https://github.com/mrclay/minify/) for JS & HTML minification
|
287 |
+
* [YUI CSS compressor PHP Port](https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port) for CSS minification
|
288 |
+
* [Lazysizes](https://github.com/aFarkas/lazysizes) for lazyload
|
289 |
+
* [Persist Admin Notices Dismissal](https://github.com/w3guy/persist-admin-notices-dismissal) for notices in the administration screens
|
290 |
+
* [Plugin Update Checker](https://github.com/YahnisElsts/plugin-update-checker/) for automated updates from Github for the beta version
|
291 |
+
* [LoadCSS](https://github.com/filamentgroup/loadCSS) for deferring full CSS
|
292 |
+
* [jQuery cookie](https://github.com/carhartl/jquery-cookie) to store the "futtta about" category selection in a cookie
|
293 |
+
* [jQuery tablesorter](https://github.com/christianbach/tablesorter) for the critical CSS rules/ jobs display
|
294 |
+
* [jQuery unslider](https://github.com/idiot/unslider/) for the mini-slider in the top right corner on the main settings page (repo gone)
|
295 |
+
* [JavaScript-md5](https://github.com/blueimp/JavaScript-MD5) for critical CSS rules editing
|
296 |
+
* [Speed Booster Pack](https://wordpress.org/plugins/speed-booster-pack/) for advanced JS deferring
|
297 |
+
|
298 |
= Where can I get help? =
|
299 |
|
300 |
You can get help on the [wordpress.org support forum](http://wordpress.org/support/plugin/autoptimize). If you are 100% sure this your problem cannot be solved using Autoptimize configuration and that you in fact discovered a bug in the code, you can [create an issue on GitHub](https://github.com/futtta/autoptimize/issues). If you're looking for premium support, check out our [Autoptimize Pro Support and Web Performance Optimization services](http://autoptimize.com/).
|
311 |
|
312 |
== Changelog ==
|
313 |
|
314 |
+
= 2.7.4 =
|
315 |
+
* Image optimization: also optimize icon links
|
316 |
+
* Image optimization: fix webp-detection for Safari (contributed by @pinkasey)
|
317 |
+
* Image lazyload: remove CSS that hides the placeholder image/ sets transistion between placeholder and final image
|
318 |
+
* Critical CSS: new advanced option to unload CCSS on onLoad
|
319 |
+
* Critical CSS improvement: cache templates in a transient to avoid overhead of having to search filesystem time and time again (contributed by @pratham2003)
|
320 |
+
* Critical CSS improvement: better but still experimental jQuery deferring logic
|
321 |
+
* Critical CSS fix: prevent MANUAL template-based rules being overwritten
|
322 |
+
* CSS Inline & defer: move away from old loadCSS-based approach to [Filamentgroup's new, simpler method](https://www.filamentgroup.com/lab/load-css-simpler/)
|
323 |
+
* 404 fallback enabled by default for new installations
|
324 |
+
* changed all occurences of blacklist/ whitelist to blocklist/ allowlist. The filters `autoptimize_filter_js_whitelist` and `autoptimize_filter_css_whitelist` still work in 2.7.4 but usage is deprecated and should be replaced with `autoptimize_filter_js_allowlist` and `autoptimize_filter_css_allowlist`.
|
325 |
+
* updated readme to explicitly confirm this is GPL + praise open source projects used in Autoptimize as praise was long overdue!
|
326 |
+
* tested and confirmed working on WordPress 5.5 beta 2
|
327 |
+
|
328 |
= 2.7.3 =
|
329 |
* Critical CSS: cache settings in the PHP process instead of re-fetching them
|
330 |
* Critical CSS: shorter intervals between calls to criticalcss.com (shortening the asynchronous job queue processing time)
|