Version Description
- bugfix for CSS minifier throwing a HTTP 500 error when a
}
is missing. - bugfix for slowness when iconv was used for multibyte string replacements (ditched iconv).
- bugfix for occasional issues with broken/ missing
Download this release
Release Info
Developer | futtta |
Plugin | Autoptimize |
Version | 2.4.1 |
Comparing to | |
See all releases |
Code changes from version 2.4.0 to 2.4.1
- autoptimize.php +1 -1
- classes/autoptimizeBase.php +2 -3
- classes/autoptimizeExtra.php +32 -14
- classes/autoptimizeMain.php +34 -0
- classes/autoptimizeStyles.php +1 -1
- classes/autoptimizeUtils.php +2 -87
- classes/external/php/yui-php-cssmin-bundled/Minifier.php +40 -0
- readme.txt +22 -2
autoptimize.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Autoptimize
|
4 |
Plugin URI: https://autoptimize.com/
|
5 |
Description: Optimize your website's performance: JS, CSS, HTML, images, Google Fonts and more!
|
6 |
-
Version: 2.4.
|
7 |
Author: Frank Goossens (futtta)
|
8 |
Author URI: https://autoptimize.com/
|
9 |
Text Domain: autoptimize
|
3 |
Plugin Name: Autoptimize
|
4 |
Plugin URI: https://autoptimize.com/
|
5 |
Description: Optimize your website's performance: JS, CSS, HTML, images, Google Fonts and more!
|
6 |
+
Version: 2.4.1
|
7 |
Author: Frank Goossens (futtta)
|
8 |
Author URI: https://autoptimize.com/
|
9 |
Text Domain: autoptimize
|
classes/autoptimizeBase.php
CHANGED
@@ -417,9 +417,9 @@ abstract class autoptimizeBase
|
|
417 |
$filehash = null;
|
418 |
|
419 |
// Grab the parts we need.
|
420 |
-
$parts = explode( $matches[1]
|
421 |
if ( ! empty( $parts ) ) {
|
422 |
-
$filepath = isset( $parts[0] ) ? $parts[0] : null;
|
423 |
$filehash = isset( $parts[1] ) ? $parts[1] : null;
|
424 |
}
|
425 |
|
@@ -485,7 +485,6 @@ abstract class autoptimizeBase
|
|
485 |
protected function inject_minified( $in )
|
486 |
{
|
487 |
$out = $in;
|
488 |
-
|
489 |
if ( false !== strpos( $in, '%%INJECTLATER%%' ) ) {
|
490 |
$out = preg_replace_callback(
|
491 |
'#\/\*\!%%INJECTLATER' . AUTOPTIMIZE_HASH . '%%(.*?)%%INJECTLATER%%\*\/#is',
|
417 |
$filehash = null;
|
418 |
|
419 |
// Grab the parts we need.
|
420 |
+
$parts = explode( '|', $matches[1] );
|
421 |
if ( ! empty( $parts ) ) {
|
422 |
+
$filepath = isset( $parts[0] ) ? base64_decode($parts[0]) : null;
|
423 |
$filehash = isset( $parts[1] ) ? $parts[1] : null;
|
424 |
}
|
425 |
|
485 |
protected function inject_minified( $in )
|
486 |
{
|
487 |
$out = $in;
|
|
|
488 |
if ( false !== strpos( $in, '%%INJECTLATER%%' ) ) {
|
489 |
$out = preg_replace_callback(
|
490 |
'#\/\*\!%%INJECTLATER' . AUTOPTIMIZE_HASH . '%%(.*?)%%INJECTLATER%%\*\/#is',
|
classes/autoptimizeExtra.php
CHANGED
@@ -250,7 +250,7 @@ class autoptimizeExtra
|
|
250 |
}
|
251 |
|
252 |
if ( ! empty( $subset_string ) ) {
|
253 |
-
$fonts_string = $fonts_string . '
|
254 |
}
|
255 |
|
256 |
$fonts_string = str_replace( '|', '%7C', ltrim( $fonts_string, '|' ) );
|
@@ -367,6 +367,8 @@ class autoptimizeExtra
|
|
367 |
if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $in, $matches ) ) {
|
368 |
foreach ( $matches[0] as $tag ) {
|
369 |
$orig_tag = $tag;
|
|
|
|
|
370 |
|
371 |
// first do (data-)srcsets.
|
372 |
if ( preg_match_all( '#srcset=("|\')(.*)("|\')#Usmi', $tag, $allsrcsets, PREG_SET_ORDER ) ) {
|
@@ -388,7 +390,9 @@ class autoptimizeExtra
|
|
388 |
}
|
389 |
|
390 |
// proceed with img src.
|
391 |
-
// first get width and height and add to $imgopt_size.
|
|
|
|
|
392 |
if ( preg_match( '#width=("|\')(.*)("|\')#Usmi', $tag, $width ) ) {
|
393 |
$imgopt_w = $width[2];
|
394 |
}
|
@@ -646,6 +650,13 @@ class autoptimizeExtra
|
|
646 |
return $launch_status;
|
647 |
}
|
648 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
649 |
public function get_imgopt_host()
|
650 |
{
|
651 |
static $imgopt_host = null;
|
@@ -692,7 +703,7 @@ class autoptimizeExtra
|
|
692 |
$_imgopt_notice = apply_filters( 'autoptimize_filter_imgopt_notice', $_imgopt_notice );
|
693 |
|
694 |
return array(
|
695 |
-
'status' => $_stat[
|
696 |
'notice' => $_imgopt_notice,
|
697 |
);
|
698 |
}
|
@@ -808,17 +819,20 @@ class autoptimizeExtra
|
|
808 |
}
|
809 |
echo apply_filters( 'autoptimize_filter_imgopt_settings_status', '<p><strong><span style="color:' . $_notice_color . ';">' . __( 'Shortpixel status: ', 'autoptimize' ) . '</span></strong>' . $_notice['notice'] . '</p>' );
|
810 |
} else {
|
811 |
-
|
812 |
-
$
|
813 |
-
$upsell_msg_2 = __( 'and then cached and served fast from a CDN.', 'autoptimize' ) . ' ';
|
814 |
if ( 'launch' === $options['availabilities']['extra_imgopt']['status'] ) {
|
815 |
-
$
|
816 |
} else {
|
817 |
-
$
|
818 |
}
|
819 |
-
echo apply_filters( 'autoptimize_extra_imgopt_settings_copy', $upsell_msg_1 .
|
820 |
}
|
821 |
-
|
|
|
|
|
|
|
|
|
822 |
?>
|
823 |
</td>
|
824 |
</tr>
|
@@ -842,7 +856,12 @@ class autoptimizeExtra
|
|
842 |
?>
|
843 |
</select>
|
844 |
</label>
|
845 |
-
<p
|
|
|
|
|
|
|
|
|
|
|
846 |
</td>
|
847 |
</tr>
|
848 |
<tr>
|
@@ -868,9 +887,8 @@ class autoptimizeExtra
|
|
868 |
<td>
|
869 |
<?php
|
870 |
if ( function_exists( 'is_plugin_active' ) && is_plugin_active( 'async-javascript/async-javascript.php' ) ) {
|
871 |
-
|
872 |
-
$
|
873 |
-
echo sprintf( ' <a href="' . $asj_config_url . '">%s</a>', __( 'configuration of async javascript is best done there.', 'autoptimize' ) );
|
874 |
} else {
|
875 |
?>
|
876 |
<input type='text' style='width:80%' name='autoptimize_extra_settings[autoptimize_extra_text_field_3]' value='<?php echo esc_attr( $options['autoptimize_extra_text_field_3'] ); ?>'>
|
250 |
}
|
251 |
|
252 |
if ( ! empty( $subset_string ) ) {
|
253 |
+
$fonts_string = $fonts_string . '&subset=' . $subset_string;
|
254 |
}
|
255 |
|
256 |
$fonts_string = str_replace( '|', '%7C', ltrim( $fonts_string, '|' ) );
|
367 |
if ( preg_match_all( '#<img[^>]*src[^>]*>#Usmi', $in, $matches ) ) {
|
368 |
foreach ( $matches[0] as $tag ) {
|
369 |
$orig_tag = $tag;
|
370 |
+
$imgopt_w = '';
|
371 |
+
$imgopt_h = '';
|
372 |
|
373 |
// first do (data-)srcsets.
|
374 |
if ( preg_match_all( '#srcset=("|\')(.*)("|\')#Usmi', $tag, $allsrcsets, PREG_SET_ORDER ) ) {
|
390 |
}
|
391 |
|
392 |
// proceed with img src.
|
393 |
+
// first reset and then get width and height and add to $imgopt_size.
|
394 |
+
$imgopt_w = '';
|
395 |
+
$imgopt_h = '';
|
396 |
if ( preg_match( '#width=("|\')(.*)("|\')#Usmi', $tag, $width ) ) {
|
397 |
$imgopt_w = $width[2];
|
398 |
}
|
650 |
return $launch_status;
|
651 |
}
|
652 |
|
653 |
+
public static function imgopt_launch_ok_wrapper()
|
654 |
+
{
|
655 |
+
// needed for "plug" notice in autoptimizeMain.php.
|
656 |
+
$self = new self();
|
657 |
+
return $self->imgopt_launch_ok();
|
658 |
+
}
|
659 |
+
|
660 |
public function get_imgopt_host()
|
661 |
{
|
662 |
static $imgopt_host = null;
|
703 |
$_imgopt_notice = apply_filters( 'autoptimize_filter_imgopt_notice', $_imgopt_notice );
|
704 |
|
705 |
return array(
|
706 |
+
'status' => $_stat['Status'],
|
707 |
'notice' => $_imgopt_notice,
|
708 |
);
|
709 |
}
|
819 |
}
|
820 |
echo apply_filters( 'autoptimize_filter_imgopt_settings_status', '<p><strong><span style="color:' . $_notice_color . ';">' . __( 'Shortpixel status: ', 'autoptimize' ) . '</span></strong>' . $_notice['notice'] . '</p>' );
|
821 |
} else {
|
822 |
+
// translators: link points to shortpixel.
|
823 |
+
$upsell_msg_1 = '<p>' . sprintf( __( 'Get more Google love and improve your website\'s loading speed by having the images optimized on the fly by %1$sShortPixel%2$s and then cached and served fast from a CDN.', 'autoptimize' ), '<a href="https://shortpixel.com/aospai' . $sp_url_suffix . '" target="_blank">', '</a>' );
|
|
|
824 |
if ( 'launch' === $options['availabilities']['extra_imgopt']['status'] ) {
|
825 |
+
$upsell_msg_2 = __( 'For a limited time only, this service is offered free-for-all, <b>don\'t miss the chance to test it</b> and see how much it could improve your site\'s speed.', 'autoptimize' );
|
826 |
} else {
|
827 |
+
$upsell_msg_2 = __( 'The service is offered for free for 100 images/month regardless of the traffic used. More image optimizations can be purchased starting with $4.99.', 'autoptimize' );
|
828 |
}
|
829 |
+
echo apply_filters( 'autoptimize_extra_imgopt_settings_copy', $upsell_msg_1 . ' ' . $upsell_msg_2 . '</p>' );
|
830 |
}
|
831 |
+
// translators: link points to shortpixel FAQ.
|
832 |
+
$faqcopy = sprintf( __( '<strong>Questions</strong>? Have a look at the %1$sShortPixel FAQ%2$s!', 'autoptimize' ), '<strong><a href="https://shortpixel.helpscoutdocs.com/category/60-shortpixel-ai-cdn" target="_blank">', '</strong></a>' );
|
833 |
+
// translators: links points to shortpixel TOS & Privacy Policy.
|
834 |
+
$toscopy = sprintf( __( 'Usage of this feature is subject to Shortpixel\'s %1$sTerms of Use%2$s and %3$sPrivacy policy%4$s.', 'autoptimize' ), '<a href="https://shortpixel.com/tos' . $sp_url_suffix . '" target="_blank">', '</a>', '<a href="https://shortpixel.com/pp' . $sp_url_suffix . '" target="_blank">', '</a>' );
|
835 |
+
echo apply_filters( 'autoptimize_extra_imgopt_settings_tos', '<p>' . $faqcopy . ' ' . $toscopy . '</p>' );
|
836 |
?>
|
837 |
</td>
|
838 |
</tr>
|
856 |
?>
|
857 |
</select>
|
858 |
</label>
|
859 |
+
<p>
|
860 |
+
<?php
|
861 |
+
// translators: link points to shortpixel image test page.
|
862 |
+
echo apply_filters( 'autoptimize_extra_imgopt_quality_copy', sprintf( __( 'You can %1$stest compression levels here%2$s.', 'autoptimize' ), '<a href="https://shortpixel.com/oic' . $sp_url_suffix . '" target="_blank">', '</a>' ) );
|
863 |
+
?>
|
864 |
+
</p>
|
865 |
</td>
|
866 |
</tr>
|
867 |
<tr>
|
887 |
<td>
|
888 |
<?php
|
889 |
if ( function_exists( 'is_plugin_active' ) && is_plugin_active( 'async-javascript/async-javascript.php' ) ) {
|
890 |
+
// translators: link points Async Javascript settings page.
|
891 |
+
printf( __( 'You have "Async JavaScript" installed, %1$sconfiguration of async javascript is best done there%2$s.', 'autoptimize' ), '<a href="' . 'options-general.php?page=async-javascript' . '">', '</a>' );
|
|
|
892 |
} else {
|
893 |
?>
|
894 |
<input type='text' style='width:80%' name='autoptimize_extra_settings[autoptimize_extra_text_field_3]' value='<?php echo esc_attr( $options['autoptimize_extra_text_field_3'] ); ?>'>
|
classes/autoptimizeMain.php
CHANGED
@@ -127,6 +127,16 @@ class autoptimizeMain
|
|
127 |
if ( ! defined( 'AUTOPTIMIZE_SITE_DOMAIN' ) ) {
|
128 |
define( 'AUTOPTIMIZE_SITE_DOMAIN', parse_url( AUTOPTIMIZE_WP_SITE_URL, PHP_URL_HOST ) );
|
129 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
do_action( 'autoptimize_setup_done' );
|
131 |
}
|
132 |
|
@@ -173,6 +183,9 @@ class autoptimizeMain
|
|
173 |
if ( apply_filters( 'autoptimize_filter_extra_activate', true ) ) {
|
174 |
$ao_extra = new autoptimizeExtra();
|
175 |
$ao_extra->run();
|
|
|
|
|
|
|
176 |
}
|
177 |
}
|
178 |
|
@@ -525,4 +538,25 @@ class autoptimizeMain
|
|
525 |
echo '</p></div>';
|
526 |
}
|
527 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
528 |
}
|
127 |
if ( ! defined( 'AUTOPTIMIZE_SITE_DOMAIN' ) ) {
|
128 |
define( 'AUTOPTIMIZE_SITE_DOMAIN', parse_url( AUTOPTIMIZE_WP_SITE_URL, PHP_URL_HOST ) );
|
129 |
}
|
130 |
+
|
131 |
+
// Multibyte-capable string replacements are available with a filter.
|
132 |
+
// Also requires 'mbstring' extension.
|
133 |
+
$with_mbstring = apply_filters( 'autoptimize_filter_main_use_mbstring', false );
|
134 |
+
if ( $with_mbstring ) {
|
135 |
+
autoptimizeUtils::mbstring_available( \extensions_loaded( 'mbstring' ) );
|
136 |
+
} else {
|
137 |
+
autoptimizeUtils::mbstring_available( false );
|
138 |
+
}
|
139 |
+
|
140 |
do_action( 'autoptimize_setup_done' );
|
141 |
}
|
142 |
|
183 |
if ( apply_filters( 'autoptimize_filter_extra_activate', true ) ) {
|
184 |
$ao_extra = new autoptimizeExtra();
|
185 |
$ao_extra->run();
|
186 |
+
|
187 |
+
// And show the imgopt notice.
|
188 |
+
add_action( 'admin_notices', 'autoptimizeMain::notice_plug_imgopt' );
|
189 |
}
|
190 |
}
|
191 |
|
538 |
echo '</p></div>';
|
539 |
}
|
540 |
|
541 |
+
public static function notice_plug_imgopt()
|
542 |
+
{
|
543 |
+
// Translators: the URL added points to the Autopmize Extra settings.
|
544 |
+
$_ao_imgopt_plug_notice = sprintf( __( 'Did you know Autoptimize includes on-the-fly image optimization and CDN via ShortPixel? Check out the %1$sAutoptimize Extra settings%2$s to activate this option.', 'autoptimize' ), '<a href="options-general.php?page=autoptimize_extra">', '</a>' );
|
545 |
+
$_ao_imgopt_plug_notice = apply_filters( 'autoptimize_filter_main_imgopt_plug_notice', $_ao_imgopt_plug_notice );
|
546 |
+
$_ao_imgopt_launch_ok = autoptimizeExtra::imgopt_launch_ok_wrapper();
|
547 |
+
$_ao_imgopt_plug_dismissible = 'ao-img-opt-plug-123';
|
548 |
+
|
549 |
+
// check if AO is optimizing images already.
|
550 |
+
$_ao_imgopt_active = false;
|
551 |
+
$_ao_extra_options = get_option( 'autoptimize_extra_settings', '' );
|
552 |
+
if ( is_array( $_ao_extra_options ) && array_key_exists( 'autoptimize_extra_checkbox_field_5', $_ao_extra_options ) && ! empty( $_ao_extra_options['autoptimize_extra_checkbox_field_5'] ) ) {
|
553 |
+
$_ao_imgopt_active = true;
|
554 |
+
}
|
555 |
+
|
556 |
+
if ( '' !== $_ao_imgopt_plug_notice && ! $_ao_imgopt_active && $_ao_imgopt_launch_ok && PAnD::is_admin_notice_active( $_ao_imgopt_plug_dismissible ) ) {
|
557 |
+
echo '<div class="notice notice-info is-dismissible" data-dismissible="' . $_ao_imgopt_plug_dismissible . '"><p>';
|
558 |
+
echo $_ao_imgopt_plug_notice;
|
559 |
+
echo '</p></div>';
|
560 |
+
}
|
561 |
+
}
|
562 |
}
|
classes/autoptimizeStyles.php
CHANGED
@@ -641,7 +641,7 @@ class autoptimizeStyles extends autoptimizeBase
|
|
641 |
$medianame = $med . ', ' . $media;
|
642 |
$this->csscode[$medianame] = $code;
|
643 |
$md5list[$medianame] = $md5list[$med];
|
644 |
-
unset( $this->csscode[$med], $this->csscode[$media], $
|
645 |
}
|
646 |
}
|
647 |
$md5list[$medianame] = $md5sum;
|
641 |
$medianame = $med . ', ' . $media;
|
642 |
$this->csscode[$medianame] = $code;
|
643 |
$md5list[$medianame] = $md5list[$med];
|
644 |
+
unset( $this->csscode[$med], $this->csscode[$media], $md5list[$med] );
|
645 |
}
|
646 |
}
|
647 |
$md5list[$medianame] = $md5sum;
|
classes/autoptimizeUtils.php
CHANGED
@@ -31,28 +31,6 @@ class autoptimizeUtils
|
|
31 |
return $available;
|
32 |
}
|
33 |
|
34 |
-
/**
|
35 |
-
* Returns true when iconv is available.
|
36 |
-
*
|
37 |
-
* @param bool|null $override Allows overriding the decision.
|
38 |
-
*
|
39 |
-
* @return bool
|
40 |
-
*/
|
41 |
-
public static function iconv_available( $override = null )
|
42 |
-
{
|
43 |
-
static $available = null;
|
44 |
-
|
45 |
-
if ( null === $available ) {
|
46 |
-
$available = \extension_loaded( 'iconv' );
|
47 |
-
}
|
48 |
-
|
49 |
-
if ( null !== $override ) {
|
50 |
-
$available = $override;
|
51 |
-
}
|
52 |
-
|
53 |
-
return $available;
|
54 |
-
}
|
55 |
-
|
56 |
/**
|
57 |
* Multibyte-capable strpos() if support is available on the server.
|
58 |
* If not, it falls back to using \strpos().
|
@@ -68,8 +46,6 @@ class autoptimizeUtils
|
|
68 |
{
|
69 |
if ( self::mbstring_available() ) {
|
70 |
return ( null === $encoding ) ? \mb_strpos( $haystack, $needle, $offset ) : \mb_strlen( $haystack, $needle, $offset, $encoding );
|
71 |
-
} elseif ( self::iconv_available() ) {
|
72 |
-
return ( null === $encoding ) ? \iconv_strpos( $haystack, $needle, $offset ) : \iconv_strpos( $haystack, $needle, $offset, $encoding );
|
73 |
} else {
|
74 |
return \strpos( $haystack, $needle, $offset );
|
75 |
}
|
@@ -77,7 +53,7 @@ class autoptimizeUtils
|
|
77 |
|
78 |
/**
|
79 |
* Attempts to return the number of characters in the given $string if
|
80 |
-
* mbstring
|
81 |
* (instead of characters) as fallback.
|
82 |
*
|
83 |
* @param string $string String.
|
@@ -90,8 +66,6 @@ class autoptimizeUtils
|
|
90 |
{
|
91 |
if ( self::mbstring_available() ) {
|
92 |
return ( null === $encoding ) ? \mb_strlen( $string ) : \mb_strlen( $string, $encoding );
|
93 |
-
} elseif ( self::iconv_available() ) {
|
94 |
-
return ( null === $encoding ) ? @iconv_strlen( $string ) : @iconv_strlen( $string, $encoding );
|
95 |
} else {
|
96 |
return \strlen( $string );
|
97 |
}
|
@@ -100,7 +74,7 @@ class autoptimizeUtils
|
|
100 |
/**
|
101 |
* Our wrapper around implementations of \substr_replace()
|
102 |
* that attempts to not break things horribly if at all possible.
|
103 |
-
* Uses mbstring
|
104 |
* substr_replace() (which works just fine in the majority of cases).
|
105 |
*
|
106 |
* @param string $string String.
|
@@ -146,70 +120,11 @@ class autoptimizeUtils
|
|
146 |
}
|
147 |
|
148 |
return "{$leader}{$replacement}{$trailer}";
|
149 |
-
} elseif ( self::iconv_available() ) {
|
150 |
-
$strlen = self::strlen( $string, $encoding );
|
151 |
-
|
152 |
-
if ( $start < 0 ) {
|
153 |
-
$start = \max( 0, $strlen + $start );
|
154 |
-
$start = $strlen + $start;
|
155 |
-
if ( $start < 0 ) {
|
156 |
-
$start = 0;
|
157 |
-
}
|
158 |
-
} elseif ( $start > $strlen ) {
|
159 |
-
$start = $strlen;
|
160 |
-
}
|
161 |
-
|
162 |
-
if ( $length < 0 ) {
|
163 |
-
$length = \max( 0, $strlen - $start + $length );
|
164 |
-
} elseif ( null === $length || ( $length > $strlen ) ) {
|
165 |
-
$length = $strlen;
|
166 |
-
}
|
167 |
-
|
168 |
-
if ( ( $start + $length ) > $strlen ) {
|
169 |
-
$length = $strlen - $start;
|
170 |
-
}
|
171 |
-
|
172 |
-
if ( null === $encoding ) {
|
173 |
-
return self::iconv_substr( $string, 0, $start ) . $replacement . self::iconv_substr( $string, $start + $length, $strlen - $start - $length );
|
174 |
-
}
|
175 |
-
|
176 |
-
return self::iconv_substr( $string, 0, $start, $encoding ) . $replacement . self::iconv_substr( $string, $start + $length, $strlen - $start - $length, $encoding );
|
177 |
}
|
178 |
|
179 |
return ( null === $length ) ? \substr_replace( $string, $replacement, $start ) : \substr_replace( $string, $replacement, $start, $length );
|
180 |
}
|
181 |
|
182 |
-
/**
|
183 |
-
* Wrapper around iconv_substr().
|
184 |
-
*
|
185 |
-
* @param string $s String.
|
186 |
-
* @param int $start Start offset.
|
187 |
-
* @param int|null $length Length.
|
188 |
-
* @param string|null $encoding Encoding.
|
189 |
-
*
|
190 |
-
* @return string
|
191 |
-
*/
|
192 |
-
protected static function iconv_substr( $s, $start, $length = null, $encoding = null )
|
193 |
-
{
|
194 |
-
if ( $start < 0 ) {
|
195 |
-
$start = self::strlen( $s, $encoding ) + $start;
|
196 |
-
if ( $start < 0 ) {
|
197 |
-
$start = 0;
|
198 |
-
}
|
199 |
-
}
|
200 |
-
|
201 |
-
if ( null === $length ) {
|
202 |
-
$length = 2147483647;
|
203 |
-
} elseif ( $length < 0 ) {
|
204 |
-
$length = self::strlen( $s, $encoding ) + ( $length - $start );
|
205 |
-
if ( $length < 0 ) {
|
206 |
-
return '';
|
207 |
-
}
|
208 |
-
}
|
209 |
-
|
210 |
-
return (string) ( null === $encoding ) ? \iconv_substr( $s, $start, $length ) : \iconv_substr( $s, $start, $length, $encoding );
|
211 |
-
}
|
212 |
-
|
213 |
/**
|
214 |
* Decides whether this is a "subdirectory site" or not.
|
215 |
*
|
31 |
return $available;
|
32 |
}
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
/**
|
35 |
* Multibyte-capable strpos() if support is available on the server.
|
36 |
* If not, it falls back to using \strpos().
|
46 |
{
|
47 |
if ( self::mbstring_available() ) {
|
48 |
return ( null === $encoding ) ? \mb_strpos( $haystack, $needle, $offset ) : \mb_strlen( $haystack, $needle, $offset, $encoding );
|
|
|
|
|
49 |
} else {
|
50 |
return \strpos( $haystack, $needle, $offset );
|
51 |
}
|
53 |
|
54 |
/**
|
55 |
* Attempts to return the number of characters in the given $string if
|
56 |
+
* mbstring is available. Returns the number of bytes
|
57 |
* (instead of characters) as fallback.
|
58 |
*
|
59 |
* @param string $string String.
|
66 |
{
|
67 |
if ( self::mbstring_available() ) {
|
68 |
return ( null === $encoding ) ? \mb_strlen( $string ) : \mb_strlen( $string, $encoding );
|
|
|
|
|
69 |
} else {
|
70 |
return \strlen( $string );
|
71 |
}
|
74 |
/**
|
75 |
* Our wrapper around implementations of \substr_replace()
|
76 |
* that attempts to not break things horribly if at all possible.
|
77 |
+
* Uses mbstring if available, before falling back to regular
|
78 |
* substr_replace() (which works just fine in the majority of cases).
|
79 |
*
|
80 |
* @param string $string String.
|
120 |
}
|
121 |
|
122 |
return "{$leader}{$replacement}{$trailer}";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
}
|
124 |
|
125 |
return ( null === $length ) ? \substr_replace( $string, $replacement, $start ) : \substr_replace( $string, $replacement, $start, $length );
|
126 |
}
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
/**
|
129 |
* Decides whether this is a "subdirectory site" or not.
|
130 |
*
|
classes/external/php/yui-php-cssmin-bundled/Minifier.php
CHANGED
@@ -29,11 +29,13 @@ class Minifier
|
|
29 |
const COMMENT_TOKEN_START = '_CSSMIN_CMT_';
|
30 |
const RULE_BODY_TOKEN = '_CSSMIN_RBT_%d_';
|
31 |
const PRESERVED_TOKEN = '_CSSMIN_PTK_%d_';
|
|
|
32 |
|
33 |
// Token lists
|
34 |
private $comments = array();
|
35 |
private $ruleBodies = array();
|
36 |
private $preservedTokens = array();
|
|
|
37 |
|
38 |
// Output options
|
39 |
private $keepImportantComments = true;
|
@@ -62,6 +64,7 @@ class Minifier
|
|
62 |
private $shortenThreeZeroesRegex;
|
63 |
private $shortenFourZeroesRegex;
|
64 |
private $unitsGroupRegex = '(?:ch|cm|em|ex|gd|in|mm|px|pt|pc|q|rem|vh|vmax|vmin|vw|%)';
|
|
|
65 |
|
66 |
/**
|
67 |
* @param bool|int $raisePhpLimits If true, PHP settings will be raised if needed
|
@@ -287,6 +290,17 @@ class Minifier
|
|
287 |
return $tokenId;
|
288 |
}
|
289 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
/**
|
291 |
* Parses & minifies the given input CSS string
|
292 |
* @param string $css
|
@@ -515,6 +529,11 @@ class Minifier
|
|
515 |
|
516 |
while (($blockStartPos = strpos($css, '{', $searchOffset)) !== false) {
|
517 |
$blockEndPos = strpos($css, '}', $blockStartPos);
|
|
|
|
|
|
|
|
|
|
|
518 |
$nextBlockStartPos = strpos($css, '{', $blockStartPos + 1);
|
519 |
$ret .= substr($css, $substrOffset, $blockStartPos - $substrOffset);
|
520 |
|
@@ -600,6 +619,14 @@ class Minifier
|
|
600 |
$body
|
601 |
);
|
602 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
603 |
// Shorten long named colors with a shorter HEX counterpart: white -> #fff.
|
604 |
// Run at least 2 times to cover most cases
|
605 |
$body = preg_replace_callback(
|
@@ -608,6 +635,9 @@ class Minifier
|
|
608 |
$body
|
609 |
);
|
610 |
|
|
|
|
|
|
|
611 |
// Replace positive sign from numbers before the leading space is removed.
|
612 |
// +1.2em to 1.2em, +.8px to .8px, +2% to 2%
|
613 |
$body = preg_replace('/([ :,(])\+(\.?\d+)/S', '$1$2', $body);
|
@@ -695,6 +725,16 @@ class Minifier
|
|
695 |
return $body;
|
696 |
}
|
697 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
698 |
/**
|
699 |
* Compresses At-rules and selectors.
|
700 |
* @param string $css the whole stylesheet with rule bodies tokenized.
|
29 |
const COMMENT_TOKEN_START = '_CSSMIN_CMT_';
|
30 |
const RULE_BODY_TOKEN = '_CSSMIN_RBT_%d_';
|
31 |
const PRESERVED_TOKEN = '_CSSMIN_PTK_%d_';
|
32 |
+
const UNQUOTED_FONT_TOKEN = '_CSSMIN_UFT_%d_';
|
33 |
|
34 |
// Token lists
|
35 |
private $comments = array();
|
36 |
private $ruleBodies = array();
|
37 |
private $preservedTokens = array();
|
38 |
+
private $unquotedFontTokens = array();
|
39 |
|
40 |
// Output options
|
41 |
private $keepImportantComments = true;
|
64 |
private $shortenThreeZeroesRegex;
|
65 |
private $shortenFourZeroesRegex;
|
66 |
private $unitsGroupRegex = '(?:ch|cm|em|ex|gd|in|mm|px|pt|pc|q|rem|vh|vmax|vmin|vw|%)';
|
67 |
+
private $unquotedFontsRegex = '/(font-family:|font:)([^\'"]+?)[^};]*/Si';
|
68 |
|
69 |
/**
|
70 |
* @param bool|int $raisePhpLimits If true, PHP settings will be raised if needed
|
290 |
return $tokenId;
|
291 |
}
|
292 |
|
293 |
+
private function registerUnquotedFontToken($body)
|
294 |
+
{
|
295 |
+
if (empty($body)) {
|
296 |
+
return '';
|
297 |
+
}
|
298 |
+
|
299 |
+
$tokenId = sprintf(self::UNQUOTED_FONT_TOKEN, count($this->unquotedFontTokens));
|
300 |
+
$this->unquotedFontTokens[$tokenId] = $body;
|
301 |
+
return $tokenId;
|
302 |
+
}
|
303 |
+
|
304 |
/**
|
305 |
* Parses & minifies the given input CSS string
|
306 |
* @param string $css
|
529 |
|
530 |
while (($blockStartPos = strpos($css, '{', $searchOffset)) !== false) {
|
531 |
$blockEndPos = strpos($css, '}', $blockStartPos);
|
532 |
+
// When ending curly brace is missing, let's
|
533 |
+
// behave like there was one at the end of the block...
|
534 |
+
if ( false === $blockEndPos ) {
|
535 |
+
$blockEndPos = strlen($css) - 1;
|
536 |
+
}
|
537 |
$nextBlockStartPos = strpos($css, '{', $blockStartPos + 1);
|
538 |
$ret .= substr($css, $substrOffset, $blockStartPos - $substrOffset);
|
539 |
|
619 |
$body
|
620 |
);
|
621 |
|
622 |
+
// Tokenize unquoted font names in order to hide them from
|
623 |
+
// color name replacements.
|
624 |
+
$body = preg_replace_callback(
|
625 |
+
$this->unquotedFontsRegex,
|
626 |
+
array($this, 'preserveUnquotedFontTokens'),
|
627 |
+
$body
|
628 |
+
);
|
629 |
+
|
630 |
// Shorten long named colors with a shorter HEX counterpart: white -> #fff.
|
631 |
// Run at least 2 times to cover most cases
|
632 |
$body = preg_replace_callback(
|
635 |
$body
|
636 |
);
|
637 |
|
638 |
+
// Restore unquoted font tokens now after colors have been changed.
|
639 |
+
$body = $this->restoreUnquotedFontTokens($body);
|
640 |
+
|
641 |
// Replace positive sign from numbers before the leading space is removed.
|
642 |
// +1.2em to 1.2em, +.8px to .8px, +2% to 2%
|
643 |
$body = preg_replace('/([ :,(])\+(\.?\d+)/S', '$1$2', $body);
|
725 |
return $body;
|
726 |
}
|
727 |
|
728 |
+
private function preserveUnquotedFontTokens($matches)
|
729 |
+
{
|
730 |
+
return $this->registerUnquotedFontToken($matches[0]);
|
731 |
+
}
|
732 |
+
|
733 |
+
private function restoreUnquotedFontTokens($body)
|
734 |
+
{
|
735 |
+
return strtr($body, $this->unquotedFontTokens);
|
736 |
+
}
|
737 |
+
|
738 |
/**
|
739 |
* Compresses At-rules and selectors.
|
740 |
* @param string $css the whole stylesheet with rule bodies tokenized.
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Donate link: http://blog.futtta.be/2013/10/21/do-not-donate-to-me/
|
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 4.9
|
7 |
Requires PHP: 5.3
|
8 |
-
Stable tag: 2.4.
|
9 |
|
10 |
Autoptimize speeds up your website by optimizing JS, CSS, HTML, Google Fonts and images, async-ing JS, removing emoji cruft and more.
|
11 |
|
@@ -191,7 +191,7 @@ NextGen Galleries does some nifty stuff to add JavaScript. In order for Autoptim
|
|
191 |
= What is noptimize? =
|
192 |
|
193 |
Starting with version 1.6.6 Autoptimize excludes everything inside noptimize tags, e.g.:
|
194 |
-
`<
|
195 |
|
196 |
You can do this in your page/ post content, in widgets and in your theme files (consider creating [a child theme](http://codex.wordpress.org/Child_Themes) to avoid your work being overwritten by theme updates).
|
197 |
|
@@ -254,6 +254,19 @@ add_filter('autoptimize_filter_main_hookpagecachepurge','__return_false');`
|
|
254 |
|
255 |
Main reason (apart from occasional hickups that seem to be inherent to plugin upgrades) is that AO 2.4 requires you to be running PHP 5.3 or higher. And let's face it; you should actually be running PHP 7.x if you value performance (and security and support), no?
|
256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
= Where can I get help? =
|
258 |
|
259 |
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/).
|
@@ -270,6 +283,13 @@ Just [fork Autoptimize on Github](https://github.com/futtta/autoptimize) and cod
|
|
270 |
|
271 |
== Changelog ==
|
272 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
273 |
= 2.4.0 =
|
274 |
* refactored significantly (no more "classlesses", all is OO), classes are autoloaded, tests added (travis-ci) by zytzagoo who deserves praise for his hard work!
|
275 |
* new: image optimization (see "Extra"-tab) using Shortpixel's smart image optimization proxy
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 4.9
|
7 |
Requires PHP: 5.3
|
8 |
+
Stable tag: 2.4.1
|
9 |
|
10 |
Autoptimize speeds up your website by optimizing JS, CSS, HTML, Google Fonts and images, async-ing JS, removing emoji cruft and more.
|
11 |
|
191 |
= What is noptimize? =
|
192 |
|
193 |
Starting with version 1.6.6 Autoptimize excludes everything inside noptimize tags, e.g.:
|
194 |
+
`<!--noptimize--><script>alert('this will not get autoptimized');</script><!--/noptimize-->`
|
195 |
|
196 |
You can do this in your page/ post content, in widgets and in your theme files (consider creating [a child theme](http://codex.wordpress.org/Child_Themes) to avoid your work being overwritten by theme updates).
|
197 |
|
254 |
|
255 |
Main reason (apart from occasional hickups that seem to be inherent to plugin upgrades) is that AO 2.4 requires you to be running PHP 5.3 or higher. And let's face it; you should actually be running PHP 7.x if you value performance (and security and support), no?
|
256 |
|
257 |
+
= Some of the non-ASCII characters get lost after optimization =
|
258 |
+
|
259 |
+
By default AO uses non multibyte-safe string methods, but if your PHP has the mbstring extension you can enable multibyte-safe string functions with this filter;
|
260 |
+
|
261 |
+
`
|
262 |
+
add_filter('autoptimize_filter_main_use_mbstring', '__return_true');`
|
263 |
+
|
264 |
+
= The Shortpixel image optimizing notice cannot be dismissed? =
|
265 |
+
|
266 |
+
In some rare cases the logic to dismiss the notice does not work due to the transient (WordPress cache) not keeping the dismissed state. If this happens you can use this code snippet to make the notice go away;
|
267 |
+
|
268 |
+
`add_filter( 'autoptimize_filter_main_imgopt_plug_notice', '__return_empty_string' );`
|
269 |
+
|
270 |
= Where can I get help? =
|
271 |
|
272 |
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/).
|
283 |
|
284 |
== Changelog ==
|
285 |
|
286 |
+
= 2.4.1 =
|
287 |
+
* bugfix for CSS minifier throwing a HTTP 500 error when a `}` is missing.
|
288 |
+
* bugfix for slowness when iconv was used for multibyte string replacements (ditched iconv).
|
289 |
+
* bugfix for occasional issues with broken/ missing </html> strings due to mbstring (also for multibyte string replacement) weirdness.
|
290 |
+
* bugfix for wrong sizes in image optimization.
|
291 |
+
* bugfix for Google Font subset getting lost in optimization.
|
292 |
+
|
293 |
= 2.4.0 =
|
294 |
* refactored significantly (no more "classlesses", all is OO), classes are autoloaded, tests added (travis-ci) by zytzagoo who deserves praise for his hard work!
|
295 |
* new: image optimization (see "Extra"-tab) using Shortpixel's smart image optimization proxy
|