Fast Velocity Minify - Version 2.4.3

Version Description

[2018.12.03] = * added font-display, to ensure text remains visible during webfont load for inlined google fonts and font-awesome * added automatic removal of "source mappings" from JS files during merging or minification * added font awesome async and exclusion from PSI options, as well as merging and inlining when the url matches "font-awesome" (ie: cdnjs) * added automatically inline of small CSS code (up to 20KB) for any FVM CSS files in the footer (requests reduction) * added automatically inline of small CSS code (up to 20KB) for any FVM CSS files in the header, which are not of mediatype "all" * improved the cache purge button (no more redirect from frontend to backend) * updated PHP Minify and Path Converter from master * bug fixes related to "Exclude JS files from PSI" option

Download this release

Release Info

Developer Alignak
Plugin Icon 128x128 Fast Velocity Minify
Version 2.4.3
Comparing to
See all releases

Code changes from version 2.4.2 to 2.4.3

fvm.css CHANGED
@@ -14,7 +14,7 @@
14
  .fvm-settings span.note-info { font-size: 14px; margin-left: 8px; color: #666; font-style: italic; }
15
  .fvm-settings p.description { font-size: 14px; color: #666; font-style: italic; font-size: 14px; }
16
  #tab-info h4{font-size: 14px; margin-bottom:-10px; }
17
- h3.hndle { background: #F7F7F7; color: #000;}
18
  .fvm-hide { max-height: 1px; overflow: none; position: absolute; top: -9999px; left: -9999px; visibility: hidden; }
19
  .fvm-warning { font-weight: 600; color: #AA0000; }
20
  .fvm-bold-green { font-weight: 600; color: #1196A3; }
@@ -22,6 +22,8 @@ h3.hndle { background: #F7F7F7; color: #000;}
22
  .fvm-label-pad { line-height: 21px; }
23
  .fvm-rowintro { padding-bottom: 10px; }
24
 
 
 
25
  @media screen and (max-width:520px) {
26
  #fastvelocity-min .processed li .filename{width: 100%;float:none;}
27
  #fastvelocity-min .processed li .actions{text-align: left;margin-top: 4px}
14
  .fvm-settings span.note-info { font-size: 14px; margin-left: 8px; color: #666; font-style: italic; }
15
  .fvm-settings p.description { font-size: 14px; color: #666; font-style: italic; font-size: 14px; }
16
  #tab-info h4{font-size: 14px; margin-bottom:-10px; }
17
+ h3.hndle { background: #F7F7F7; color: #000; cursor: default !important; }
18
  .fvm-hide { max-height: 1px; overflow: none; position: absolute; top: -9999px; left: -9999px; visibility: hidden; }
19
  .fvm-warning { font-weight: 600; color: #AA0000; }
20
  .fvm-bold-green { font-weight: 600; color: #1196A3; }
22
  .fvm-label-pad { line-height: 21px; }
23
  .fvm-rowintro { padding-bottom: 10px; }
24
 
25
+
26
+
27
  @media screen and (max-width:520px) {
28
  #fastvelocity-min .processed li .filename{width: 100%;float:none;}
29
  #fastvelocity-min .processed li .actions{text-align: left;margin-top: 4px}
fvm.js CHANGED
@@ -1,135 +1,59 @@
1
- (function($){
2
-
3
- $(function(){
4
-
5
- // disable some checkboxes when some other is on or off
6
- $('#fastvelocity_min_enable_defer_js').bind('click init', function() {
7
- if( $(this).is(':checked')) {
8
- $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", false);
9
- } else {
10
- $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", true);
11
- }
12
- }).trigger('init');
13
-
14
- // disable some checkboxes when some other is on or off
15
- $('#fastvelocity_min_skip_html_minification').bind('click init', function() {
16
- if( $(this).is(':checked')) {
17
- $("#fastvelocity_min_strip_htmlcomments").prop("disabled", true).prop('checked', false);
18
- } else {
19
- $("#fastvelocity_min_strip_htmlcomments").prop("disabled", false);
20
- }
21
- }).trigger('init');
22
-
23
- // disable some checkboxes when some other is on or off
24
- $('#fastvelocity_min_disable_css_merge').bind('click init', function() {
25
- if( $(this).is(':checked')) {
26
- $("#fastvelocity_min_disable_css_minification, #fastvelocity_min_force_inline_css").prop("disabled", true);
27
- $("#fastvelocity_min_force_inline_css_footer").prop("disabled", true);
28
- $("#fastvelocity_min_skip_cssorder, #fastvelocity_min_remove_print_mediatypes").prop("disabled", true);
29
- } else {
30
- $("#fastvelocity_min_disable_css_minification, #fastvelocity_min_force_inline_css").prop("disabled", false);
31
- $("#fastvelocity_min_force_inline_css_footer").prop("disabled", false);
32
- $("#fastvelocity_min_skip_cssorder, #fastvelocity_min_remove_print_mediatypes").prop("disabled", false);
33
- }
34
- }).trigger('init');
35
-
36
- // disable some checkboxes when some other is on or off
37
- $('#fastvelocity_min_disable_js_merge').bind('click init', function() {
38
- if( $(this).is(':checked')) {
39
- $("#fastvelocity_min_use_yui, #fastvelocity_min_disable_js_minification").prop("disabled", true);
40
- $("#fastvelocity_min_enable_defer_js, #fastvelocity_min_defer_for_pagespeed").prop("disabled", true);
41
- $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", true);
42
- } else {
43
- $("#fastvelocity_min_use_yui, #fastvelocity_min_disable_js_minification").prop("disabled", false);
44
- $("#fastvelocity_min_enable_defer_js, #fastvelocity_min_defer_for_pagespeed").prop("disabled", false);
45
- $("#fastvelocity_min_exclude_defer_jquery, #fastvelocity_min_exclude_defer_login").prop("disabled", false);
46
- }
47
- }).trigger('init');
48
-
49
- // disable some checkboxes when some other is on or off
50
- $('#fastvelocity_min_fvm_removecss').bind('click init', function() {
51
- if( $(this).is(':checked')) {
52
- $("#fastvelocity_min_send_css_to_footer, #fastvelocity_min_critical_path_visibility").prop("disabled", true);
53
- $("#fastvelocity_min_critical_css_tester").prop("disabled", true);
54
- } else {
55
- $("#fastvelocity_min_send_css_to_footer, #fastvelocity_min_critical_path_visibility").prop("disabled", false);
56
- $("#fastvelocity_min_critical_css_tester").prop("disabled", false);
57
- }
58
- }).trigger('init');
59
-
60
- // disable collapse
61
- $('.postbox h3, .postbox .handlediv').unbind('click.postboxes');
62
 
63
- // variables
64
- var $fastvelocity_min_processed = $('#fastvelocity_min_processed'),
65
- $fastvelocity_min_jsprocessed = $('#fastvelocity_min_jsprocessed',$fastvelocity_min_processed),
66
- $fastvelocity_min_jsprocessed_ul = $('ul',$fastvelocity_min_jsprocessed),
67
- $fastvelocity_min_cssprocessed = $('#fastvelocity_min_cssprocessed',$fastvelocity_min_processed),
68
- $fastvelocity_min_cssprocessed_ul = $('ul',$fastvelocity_min_cssprocessed),
69
- $fastvelocity_min_noprocessed = $('#fastvelocity_min_noprocessed'),
70
- timeout = null,
71
- stamp = null;
72
 
73
- $($fastvelocity_min_processed).on('click','.log',function(e){
74
- e.preventDefault();
75
- $(this).parent().nextAll('pre').slideToggle();
76
- });
77
-
78
- function getFiles(extra) {
79
- stamp = new Date().getTime();
80
- var data = {
81
- 'action': 'fastvelocity_min_files',
82
- 'stamp': stamp
83
- };
84
- if(extra) {
85
- for (var attrname in extra) { data[attrname] = extra[attrname]; }
86
  }
87
-
88
 
89
- $.post(ajaxurl, data, function(response) {
90
-
91
- if(response.cachesize.length > 0) {
92
- $("#fvm_cache_size").html(response.cachesize);
 
 
 
 
 
93
  }
94
-
95
- if(stamp == response.stamp) {
96
- if(response.js.length > 0) {
97
- $fastvelocity_min_jsprocessed.show();
98
-
99
- $(response.js).each(function(){
100
- var $li = $fastvelocity_min_jsprocessed_ul.find('li.'+this.hash);
101
- if($li.length > 0) {
102
- if($li.find('pre').html() != this.log) {
103
- $li.find('pre').html(this.log);
104
- }
105
- } else {
106
- $fastvelocity_min_jsprocessed_ul.append('<li class="'+this.hash+'"><span class="filename">'+this.filename+' ('+this.fsize+')</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
107
- }
108
- });
109
-
110
- }
111
- if(response.css.length > 0) {
112
-
113
- $(response.css).each(function(){
114
- var $li = $fastvelocity_min_cssprocessed_ul.find('li.'+this.hash);
115
- if($li.length > 0) {
116
- if($li.find('pre').html() != this.log) {
117
- $li.find('pre').html(this.log);
118
- }
119
- } else {
120
- $fastvelocity_min_cssprocessed_ul.append('<li class="'+this.hash+'"><span class="filename">'+this.filename+' ('+this.fsize+')</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
121
- }
122
- });
123
- }
124
-
125
- // check for new files
126
- timeout = setTimeout(getFiles, 4000);
127
  }
128
  });
129
- }
130
-
131
- getFiles();
132
-
133
- });
 
 
 
 
 
 
 
 
 
 
134
 
135
- })(jQuery);
1
+ jQuery( document ).ready(function() {
2
+
3
+ // disable collapse
4
+ jQuery('.postbox h3, .postbox .handlediv').unbind('click.postboxes');
5
+
6
+ // show logs
7
+ jQuery('#fastvelocity_min_processed').on('click','.log',function(e){
8
+ e.preventDefault();
9
+ jQuery(this).parent().nextAll('pre').slideToggle();
10
+ });
11
+
12
+ function getFiles() {
13
+ stamp = new Date().getTime();
14
+ var data = { 'action': 'fastvelocity_min_files' };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ jQuery.post(ajaxurl, data, function(response) {
 
 
 
 
 
 
 
 
17
 
18
+ if(response.cachesize.length > 0) {
19
+ jQuery("#fvm_cache_size").html(response.cachesize);
 
 
 
 
 
 
 
 
 
 
 
20
  }
 
21
 
22
+ // reset
23
+ var fvmarr = [];
24
+
25
+ // js
26
+ if(response.js.length > 0) {
27
+ jQuery(response.js).each(function(){
28
+ fvmarr.push(this.uid);
29
+ if(jQuery('#'+this.uid).length == 0) {
30
+ jQuery('#fastvelocity_min_jsprocessed ul').append('<li id="'+this.uid+'"><span class="filename">'+this.filename+' ('+this.fsize+')</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
31
  }
32
+ });
33
+ }
34
+
35
+ // css
36
+ if(response.css.length > 0) {
37
+ jQuery(response.css).each(function(){
38
+ fvmarr.push(this.uid);
39
+ if(jQuery('#'+this.uid).length == 0) {
40
+ jQuery('#fastvelocity_min_cssprocessed ul').append('<li id="'+this.uid+'"><span class="filename">'+this.filename+' ('+this.fsize+')</span> <span class="actions"><a href="#" class="log button button-primary">View Log</a></span><pre>'+this.log+'</pre></li><div class="clear"></div>');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
42
  });
43
+ }
44
+
45
+ // remove li, if not set (JS)
46
+ jQuery('#fastvelocity_min_jsprocessed ul li, #fastvelocity_min_cssprocessed ul li').each(function(){
47
+ if(jQuery.inArray(jQuery(this).attr('id'), fvmarr) == -1) {
48
+ jQuery('#' + jQuery(this).attr('id')).remove();
49
+ }
50
+ });
51
+
52
+ // check for new files
53
+ timeout = setTimeout(getFiles, 4000);
54
+ });
55
+ }
56
+
57
+ getFiles();
58
 
59
+ });
fvm.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://fastvelocity.com
5
  Description: Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS and JavaScript files into groups, compressing HTML and other speed optimizations.
6
  Author: Raul Peixoto
7
  Author URI: http://fastvelocity.com
8
- Version: 2.4.2
9
  License: GPL2
10
 
11
  ------------------------------------------------------------------------
@@ -137,6 +137,7 @@ $fvm_remove_css = get_option('fastvelocity_min_fvm_removecss');
137
  $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
138
  $fvm_enabled_css_preload = get_option('fastvelocity_enabled_css_preload');
139
  $fvm_enabled_js_preload = get_option('fastvelocity_enabled_css_preload');
 
140
 
141
  # default options
142
  $used_css_files = array();
@@ -230,6 +231,7 @@ if(is_admin()) {
230
 
231
  # add the CSS async polyfil + LoadAsync JavaScript functions
232
  add_action('wp_footer', 'fvm_add_loadcss', PHP_INT_MAX);
 
233
 
234
  # remove query from static assets and process defering (if enabled)
235
  add_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
@@ -277,7 +279,7 @@ function fastvelocity_admintoolbar() {
277
  $wp_admin_bar->add_node(array(
278
  'id' => 'fvm',
279
  'title' => '<span class="ab-icon"></span><span class="ab-label">' . __("FVM Purge",'fvm') . '</span>',
280
- 'href' => admin_url( '/options-general.php?page=fastvelocity-min&fvm_flush=1' )
281
  ));
282
 
283
  }
@@ -287,10 +289,10 @@ function fastvelocity_admintoolbar() {
287
  # function to list all cache files
288
  function fastvelocity_min_files_callback() {
289
  global $cachedir;
290
-
291
  # default
292
  $size = fastvelocity_get_cachestats();
293
- $return = array('js' => array(), 'css' => array(), 'stamp' => $_POST['stamp'], 'cachesize'=> $size);
294
 
295
  # inspect directory with opendir, since glob might not be available in some systems
296
  clearstatcache();
@@ -298,27 +300,24 @@ function fastvelocity_min_files_callback() {
298
  while (false !== ($file = readdir($handle))) {
299
  $file = $cachedir.'/'.$file;
300
  $ext = pathinfo($file, PATHINFO_EXTENSION);
301
- if (in_array($ext, array('js', 'css'))) {
302
- $log = file_get_contents($file.'.txt');
303
- $mincss = substr($file, 0, -4).'.min.css';
304
- $minjs = substr($file, 0, -3).'.min.js';
305
- $filename = basename($file);
306
- if ($ext == 'css' && file_exists($mincss)) { $filename = basename($mincss); }
307
- if ($ext == 'js' && file_exists($minjs)) { $filename = basename($minjs); }
308
  $fsize = fastvelocity_format_filesize(filesize($file));
309
-
310
- # get location, hash, log
311
- $info = explode('-', $filename);
312
- $hash = $info['1'];
313
- array_push($return[$ext], array('hash' => $hash, 'filename' => $filename, 'log' => $log, 'fsize' => $fsize));
314
- }
315
  }
316
  closedir($handle);
317
  }
318
-
319
- header('Content-Type: application/json');
320
- echo json_encode($return);
321
- wp_die();
322
  }
323
 
324
 
@@ -353,6 +352,7 @@ function fastvelocity_min_register_settings() {
353
  register_setting('fvm-group', 'fastvelocity_min_force_inline_css');
354
  register_setting('fvm-group', 'fastvelocity_min_remove_googlefonts');
355
  register_setting('fvm-group', 'fastvelocity_gfonts_method');
 
356
  register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed');
357
  register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed_optimize');
358
  register_setting('fvm-group', 'fastvelocity_min_exclude_defer_login');
@@ -398,6 +398,62 @@ return $links;
398
  add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
399
 
400
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
 
402
  # manage settings page
403
  function fastvelocity_min_settings() {
@@ -413,19 +469,6 @@ $active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'status';
413
  <div class="wrap">
414
  <h1>Fast Velocity Minify</h1>
415
 
416
- <?php
417
-
418
- # purge all caches
419
- if(isset($_GET['page']) && $_GET['page'] == 'fastvelocity-min') {
420
- if((isset($_POST['purgeall']) && $_POST['purgeall'] == 1) || isset($_GET['fvm_flush']) && $_GET['fvm_flush'] == 1) {
421
- fvm_purge_all(); # purge all
422
- echo __('<div class="notice notice-success is-dismissible"><p>All caches from <strong>FVM</strong> have been purged!</p></div>');
423
- echo fastvelocity_purge_others(); # purge third party caches
424
- }
425
- }
426
-
427
- ?>
428
-
429
  <h2 class="nav-tab-wrapper wp-clearfix">
430
  <a href="?page=fastvelocity-min&tab=status" class="nav-tab <?php echo $active_tab == 'status' ? 'nav-tab-active' : ''; ?>">Status</a>
431
  <a href="?page=fastvelocity-min&tab=set" class="nav-tab <?php echo $active_tab == 'set' ? 'nav-tab-active' : ''; ?>">Settings</a>
@@ -570,7 +613,7 @@ Cleanup Header <span class="note-info">[ Remove resource hints, generator tag, s
570
 
571
 
572
  <tr>
573
- <th scope="row">Fonts Options</th>
574
  <td>
575
  <p class="fvm-bold-green fvm-rowintro">The default options are usually good for performance.</p>
576
  <fieldset>
@@ -603,15 +646,35 @@ $a = ''; if($sel == 1 || empty($sel)) { $a = ' checked="checked"'; }
603
  $b = ''; if($sel == 2) { $b = ' checked="checked"'; }
604
  $c = ''; if($sel == 3) { $c = ' checked="checked"'; }
605
  ?>
606
- <p class="fvm-bold-green fvm-rowintro">Choose how to include your Google Fonts CSS on your pages:</p>
607
  <fieldset>
608
- <label><input type="radio" name="fastvelocity_gfonts_method" value="1" <?php echo $a; ?>> Inline Google Fonts CSS</label> <span class="note-info">[ Will inline in the <a target="_blank" href="https://caniuse.com/#feat=woff">woof</a> format only ]</span><br>
609
  <label><input type="radio" name="fastvelocity_gfonts_method" value="2"<?php echo $b; ?>> Async Google Fonts CSS files</label> <span class="note-info">[ Will use <a target="_blank" href="https://caniuse.com/#feat=link-rel-preload">preload</a> with <a href="https://github.com/filamentgroup/loadCSS">LoadCSS</a> polyfill ]</span><br>
610
- <label><input type="radio" name="fastvelocity_gfonts_method" value="3"<?php echo $c; ?>> Async and exclude CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
611
  </fieldset>
612
  </td>
613
  </tr>
614
 
 
615
  <tr>
616
  <th scope="row">CSS Options</th>
617
  <td>
@@ -636,7 +699,7 @@ Remove the "Print" related stylesheets <span class="note-info">[ If selected, CS
636
  <br />
637
  <label for="fastvelocity_min_force_inline_css">
638
  <input name="fastvelocity_min_force_inline_css" type="checkbox" id="fastvelocity_min_force_inline_css" value="1" <?php echo checked(1 == get_option('fastvelocity_min_force_inline_css'), true, false); ?>>
639
- Inline all CSS files <span class="note-info">[ If selected, CSS will be inlined to avoid the "render blocking" on PSI ]</span></label>
640
  <br />
641
  </fieldset></td>
642
  </tr>
@@ -645,7 +708,7 @@ Inline all CSS files <span class="note-info">[ If selected, CSS will be inlined
645
  <tr>
646
  <th scope="row">JavaScript Options</th>
647
  <td>
648
- <p class="fvm-bold-green fvm-rowintro">Try to disable minification (and purge the cache), if you have trouble with JavaScript in the frontend.</p>
649
  <fieldset>
650
  <label for="fastvelocity_min_disable_js_merge">
651
  <input name="fastvelocity_min_disable_js_merge" type="checkbox" id="fastvelocity_min_disable_js_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_merge'), true, false); ?> >
@@ -1100,7 +1163,7 @@ if( $active_tab == 'help' ) { ?>
1100
  # process header javascript ###############
1101
  ###########################################
1102
  function fastvelocity_min_merge_header_scripts() {
1103
- global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery, $fvm_debug;
1104
  if(!is_object($wp_scripts)) { return false; }
1105
  $scripts = wp_clone($wp_scripts);
1106
  $scripts->all_deps($scripts->queue);
@@ -1125,6 +1188,24 @@ $is_footer = 0; if (isset($wp_scripts->registered[$handle]->extra["group"]) || i
1125
  # get full url
1126
  $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1128
  # IE only files don't increment things
1129
  $ieonly = fastvelocity_ie_blacklist($hurl);
1130
  if($ieonly == true) { continue; }
@@ -1240,8 +1321,7 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1240
  if(count($data) > 0) { $wp_scripts->registered["fvm-header-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1241
 
1242
  # enqueue file, if not empty
1243
- $check = ''; $check = trim(file_get_contents($file));
1244
- if(file_exists($file) && (!empty($check) || count($data) > 0)) {
1245
  wp_enqueue_script("fvm-header-$i");
1246
  }
1247
 
@@ -1263,7 +1343,7 @@ $wp_scripts->done = $done;
1263
  # process js in the footer ################
1264
  ###########################################
1265
  function fastvelocity_min_merge_footer_scripts() {
1266
- global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery, $fvm_debug;
1267
  if(!is_object($wp_scripts)) { return false; }
1268
  $ctime = get_option('fvm-last-cache-update', '0');
1269
  $scripts = wp_clone($wp_scripts);
@@ -1283,6 +1363,24 @@ foreach( $scripts->to_do as $handle ) :
1283
  # get full url
1284
  $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1286
  # IE only files don't increment things
1287
  $ieonly = fastvelocity_ie_blacklist($hurl);
1288
  if($ieonly == true) { continue; }
@@ -1381,10 +1479,6 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1381
  # register minified file
1382
  wp_register_script("fvm-footer-$i", $file_url, array(), null, false);
1383
 
1384
- # associate generated file to current url so it can be send with preload later
1385
-
1386
-
1387
-
1388
  # add all extra data from wp_localize_script
1389
  $data = array();
1390
  foreach($footer[$i]['handles'] as $handle) {
@@ -1393,8 +1487,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1393
  if(count($data) > 0) { $wp_scripts->registered["fvm-footer-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1394
 
1395
  # enqueue file, if not empty
1396
- $check = ''; $check = trim(file_get_contents($file));
1397
- if(file_exists($file) && (!empty($check) || count($data) > 0)) {
1398
  wp_enqueue_script("fvm-footer-$i");
1399
  }
1400
 
@@ -1484,7 +1577,7 @@ return $tag;
1484
  # process header css ######################
1485
  ###########################################
1486
  function fastvelocity_min_merge_header_css() {
1487
- global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_min_excludecsslist, $fvm_debug, $fvm_min_excludecsslist;
1488
  if(!is_object($wp_styles)) { return false; }
1489
  $ctime = get_option('fvm-last-cache-update', '0');
1490
  $styles = wp_clone($wp_styles);
@@ -1519,8 +1612,9 @@ foreach( $styles->to_do as $handle):
1519
  }
1520
 
1521
  # mediatype
1522
- $mediatype = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all'; # such as all, print, mobile, etc
1523
- if ($mediatype == 'screen' || $mediatype == 'screen, print') { $mediatype = 'all'; }
 
1524
 
1525
  # full url or empty
1526
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
@@ -1540,6 +1634,23 @@ foreach( $styles->to_do as $handle):
1540
  $done = array_merge($done, array($handle)); continue;
1541
  }
1542
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1543
  # array of info to save
1544
  $arr = array('handle'=>$handle, 'url'=>$hurl, 'conditional'=>$conditional, 'mediatype'=>$mediatype);
1545
 
@@ -1615,6 +1726,12 @@ if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts
1615
 
1616
  # inline css or fail
1617
  if($res['code'] !== false) {
 
 
 
 
 
 
1618
  echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
1619
  } else {
1620
  echo "<!-- GOOGLE FONTS REQUEST FAILED for $gfurl -->\n";
@@ -1648,8 +1765,10 @@ $mediatype = $process[$handle]['mediatype'];
1648
  $ieonly = fastvelocity_ie_blacklist($hurl);
1649
  if($ieonly == true) { continue; }
1650
 
1651
- # skip ignore list, conditional css, external css
1652
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
 
 
1653
 
1654
  # colect inline css for this handle
1655
  if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
@@ -1673,7 +1792,6 @@ $mediatype = $process[$handle]['mediatype'];
1673
  }
1674
  endforeach;
1675
 
1676
-
1677
  # reorder CSS by mediatypes
1678
  if(!$skip_cssorder) {
1679
  if(count($header) > 0) {
@@ -1683,12 +1801,12 @@ if(!$skip_cssorder) {
1683
  foreach($header as $array) {
1684
  if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1685
  }
1686
-
1687
  # extract handles by mediatype
1688
  $grouphandles = array();
1689
  foreach ($allmedia as $md=>$var) {
1690
  foreach($header as $array) {
1691
- if (isset($array['media']) && $array['media'] == $md) {
1692
  foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1693
  }
1694
  }
@@ -1792,13 +1910,16 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1792
 
1793
  # enqueue file, if not empty
1794
  } else {
1795
- $check = ''; $check = trim(file_get_contents($file));
1796
- if(file_exists($file) && !empty($check)) {
1797
 
1798
- # enqueue it
1799
- wp_register_style("fvm-header-$i", $file_url, array(), null, $header[$i]['media']);
1800
- wp_enqueue_style("fvm-header-$i");
1801
-
 
 
 
 
1802
  }
1803
  }
1804
  }
@@ -1821,7 +1942,7 @@ $wp_styles->done = $done;
1821
  # process css in the footer ###############
1822
  ###########################################
1823
  function fastvelocity_min_merge_footer_css() {
1824
- global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_debug;
1825
 
1826
  if(!is_object($wp_styles)) { return false; }
1827
  $ctime = get_option('fvm-last-cache-update', '0');
@@ -1849,8 +1970,10 @@ $ignore = fastvelocity_default_ignore($ignore);
1849
 
1850
  # google fonts to the top
1851
  foreach( $styles->to_do as $handle ) :
 
1852
  # dequeue and get a list of google fonts, or requeue external
1853
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
 
1854
  if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1855
  wp_dequeue_style($handle);
1856
  if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
@@ -1862,6 +1985,7 @@ foreach( $styles->to_do as $handle ) :
1862
  } else {
1863
  wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
1864
  }
 
1865
  endforeach;
1866
 
1867
 
@@ -1939,28 +2063,66 @@ if(!$skip_google_fonts && count($google_fonts) > 0 || ($force_inline_googlefonts
1939
 
1940
 
1941
  # get groups of handles
 
1942
  foreach( $styles->to_do as $handle ) :
1943
 
1944
  # skip already processed google fonts
1945
  if(isset($google_fonts[$handle])) { continue; }
1946
-
 
 
 
 
 
 
 
 
 
 
1947
  # get full url
1948
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1949
-
1950
- # media type
1951
- $media = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
 
 
 
1952
 
1953
  # IE only files don't increment things
1954
  $ieonly = fastvelocity_ie_blacklist($hurl);
1955
  if($ieonly == true) { continue; }
1956
 
1957
- # conditionals
1958
- $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
1959
- $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1960
  }
1961
 
1962
- # skip ignore list, conditional css, external css
1963
- if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
 
 
1964
 
1965
  # colect inline css for this handle
1966
  if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
@@ -1970,7 +2132,7 @@ foreach( $styles->to_do as $handle ) :
1970
 
1971
  # process
1972
  if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0 || $footer[count($footer)-1]['media'] != $wp_styles->registered[$handle]->args) {
1973
- array_push($footer, array('handles'=>array(),'media'=>$media));
1974
  }
1975
 
1976
  # push it to the array get latest modified time
@@ -1999,7 +2161,7 @@ if(!$skip_cssorder) {
1999
  $grouphandles = array();
2000
  foreach ($allmedia as $md=>$var) {
2001
  foreach($footer as $array) {
2002
- if (isset($array['media']) && $array['media'] == $md) {
2003
  foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
2004
  }
2005
  }
@@ -2090,7 +2252,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
2090
  }
2091
 
2092
  # register and enqueue minified file, consider excluding of mediatype "print" and inline css
2093
- if ($remove_print_mediatypes != true || ($remove_print_mediatypes == true && $header[$i]['media'] != 'print')) {
2094
 
2095
  # the developers tab, takes precedence
2096
 
@@ -2103,13 +2265,15 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
2103
 
2104
  # enqueue file, if not empty
2105
  } else {
2106
- $check = ''; $check = trim(file_get_contents($file));
2107
- if(file_exists($file) && !empty($check)) {
2108
-
2109
- # enqueue it
2110
- wp_register_style("fvm-footer-$i", $file_url, array(), null, $footer[$i]['media']);
2111
- wp_enqueue_style("fvm-footer-$i");
2112
-
 
 
2113
  }
2114
  }
2115
  }
@@ -2136,8 +2300,6 @@ function fvm_add_loadcss() {
2136
 
2137
  echo <<<EOF
2138
  <script>
2139
- /*! fvm load async scripts with clallback */
2140
- function loadAsync(e,a){var t=document.createElement("script");t.src=e,null!==a&&(t.readyState?t.onreadystatechange=function(){"loaded"!=t.readyState&&"complete"!=t.readyState||(t.onreadystatechange=null,a())}:t.onload=function(){a()}),document.getElementsByTagName("head")[0].appendChild(t)}
2141
  /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
2142
  !function(n){"use strict";n.loadCSS||(n.loadCSS=function(){});var o=loadCSS.relpreload={};if(o.support=function(){var e;try{e=n.document.createElement("link").relList.supports("preload")}catch(t){e=!1}return function(){return e}}(),o.bindMediaToggle=function(t){var e=t.media||"all";function a(){t.media=e}t.addEventListener?t.addEventListener("load",a):t.attachEvent&&t.attachEvent("onload",a),setTimeout(function(){t.rel="stylesheet",t.media="only x"}),setTimeout(a,3e3)},o.poly=function(){if(!o.support())for(var t=n.document.getElementsByTagName("link"),e=0;e<t.length;e++){var a=t[e];"preload"!==a.rel||"style"!==a.getAttribute("as")||a.getAttribute("data-loadcss")||(a.setAttribute("data-loadcss",!0),o.bindMediaToggle(a))}},!o.support()){o.poly();var t=n.setInterval(o.poly,500);n.addEventListener?n.addEventListener("load",function(){o.poly(),n.clearInterval(t)}):n.attachEvent&&n.attachEvent("onload",function(){o.poly(),n.clearInterval(t)})}"undefined"!=typeof exports?exports.loadCSS=loadCSS:n.loadCSS=loadCSS}("undefined"!=typeof global?global:this);
2143
  </script>
@@ -2145,6 +2307,14 @@ EOF;
2145
 
2146
  }
2147
 
 
 
 
 
 
 
 
 
2148
 
2149
 
2150
 
@@ -2217,10 +2387,10 @@ if($fvm_headers != false) {
2217
  # optimize the ignore list for pagespeed insights + Exclude JS files from PSI (Async)
2218
  ###########################################
2219
  function fastvelocity_min_defer_js_optimize($tag, $handle, $src) {
2220
- global $defer_for_pagespeed, $defer_for_pagespeed_optimize, $fvm_fix_editor, $fvm_min_excludejslist, $fvmualist;
2221
 
2222
  # return if there are linebreaks (will break document.write)
2223
- if (stripos($tag, "\n") !== false) { return $tag; }
2224
 
2225
  # fix page editors
2226
  if($fvm_fix_editor == true && is_user_logged_in()) { return $tag; }
@@ -2233,21 +2403,6 @@ if (stripos($src, '?ver') !== false) {
2233
  $src = stristr($src, '?ver', true);
2234
  }
2235
 
2236
- # Exclude JS files from PSI (Async) takes priority over defering the ignore list
2237
- if($fvm_min_excludejslist != false || is_array($fvm_min_excludejslist)) {
2238
- # check for string match
2239
- foreach($fvm_min_excludejslist as $l) {
2240
- if (stripos($src, $l) !== false) {
2241
-
2242
- # print code if there are no linebreaks, or return
2243
- echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2244
- echo "loadAsync('$src', null);";
2245
- echo '}</script>';
2246
- return false;
2247
- }
2248
- }
2249
- }
2250
-
2251
  # exclude ignored scripts
2252
  if(substr($handle, 0, 4) != "fvm-" && $defer_for_pagespeed == true && $defer_for_pagespeed_optimize == true) {
2253
 
@@ -2278,7 +2433,7 @@ return $tag;
2278
 
2279
  # inline css in place, instead of inlining the large file
2280
  function fastvelocity_optimizecss($html, $handle, $href, $media){
2281
- global $fvm_debug, $wp_domain, $wp_home, $force_inline_css, $fvmualist, $fvm_collect_google_fonts, $force_inline_googlefonts, $min_async_googlefonts, $remove_googlefonts, $skip_google_fonts, $css_hide_googlefonts, $remove_print_mediatypes, $ignore, $blacklist, $ignorelist, $wp_home, $fvmloadcss, $fvm_remove_css, $fvm_cdn_url, $disable_minification, $fvm_min_excludecsslist, $disable_css_minification, $fvm_fix_editor;
2282
 
2283
  # current timestamp
2284
  $ctime = get_option('fvm-last-cache-update', '0');
@@ -2310,7 +2465,7 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2310
  }
2311
 
2312
  # mediatype fix for some plugins + remove print mediatypes
2313
- if ($media == 'screen' || $media == 'screen, print') { $media = 'all'; }
2314
  if($remove_print_mediatypes != false && $media == 'print') {
2315
  return false;
2316
  }
@@ -2335,7 +2490,6 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2335
  return false;
2336
  }
2337
 
2338
-
2339
  # handle google fonts here, when merging is disabled
2340
  if(stripos($href, 'fonts.googleapis.com') !== false && $skip_google_fonts != false) {
2341
 
@@ -2357,6 +2511,52 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2357
  }
2358
  }
2359
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2360
  # inline google fonts, do not collect
2361
  if(stripos($href, 'fonts.googleapis.com') !== false && $force_inline_googlefonts != false && $css_hide_googlefonts != true && $min_async_googlefonts != true) {
2362
 
@@ -2372,6 +2572,10 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2372
  # decode
2373
  $res = json_decode($json, true);
2374
 
 
 
 
 
2375
  # inline css or fail
2376
  if($res['status'] != false) {
2377
  echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
@@ -2388,7 +2592,6 @@ function fastvelocity_optimizecss($html, $handle, $href, $media){
2388
  return false;
2389
  }
2390
 
2391
-
2392
  # skip external scripts that are not specifically allowed
2393
  if (fvm_internal_url($href, $wp_home) === false || empty($href)) {
2394
  if($fvm_debug == true) { echo "<!-- FVM DEBUG: Skipped the next external enqueued CSS -->" . PHP_EOL; }
5
  Description: Improve your speed score on GTmetrix, Pingdom Tools and Google PageSpeed Insights by merging and minifying CSS and JavaScript files into groups, compressing HTML and other speed optimizations.
6
  Author: Raul Peixoto
7
  Author URI: http://fastvelocity.com
8
+ Version: 2.4.3
9
  License: GPL2
10
 
11
  ------------------------------------------------------------------------
137
  $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
138
  $fvm_enabled_css_preload = get_option('fastvelocity_enabled_css_preload');
139
  $fvm_enabled_js_preload = get_option('fastvelocity_enabled_css_preload');
140
+ $fvm_fawesome_method = get_option("fastvelocity_fontawesome_method");
141
 
142
  # default options
143
  $used_css_files = array();
231
 
232
  # add the CSS async polyfil + LoadAsync JavaScript functions
233
  add_action('wp_footer', 'fvm_add_loadcss', PHP_INT_MAX);
234
+ add_action('wp_head', 'fvm_add_loadasync', 0);
235
 
236
  # remove query from static assets and process defering (if enabled)
237
  add_filter('style_loader_src', 'fastvelocity_remove_cssjs_ver', 10, 2);
279
  $wp_admin_bar->add_node(array(
280
  'id' => 'fvm',
281
  'title' => '<span class="ab-icon"></span><span class="ab-label">' . __("FVM Purge",'fvm') . '</span>',
282
+ 'href' => wp_nonce_url( add_query_arg('_fvmcache', 'clear'), 'fvm_clear_nonce')
283
  ));
284
 
285
  }
289
  # function to list all cache files
290
  function fastvelocity_min_files_callback() {
291
  global $cachedir;
292
+
293
  # default
294
  $size = fastvelocity_get_cachestats();
295
+ $return = array('js' => array(), 'css' => array(), 'stamp' => $_POST['stamp'], 'cachesize'=> $size);
296
 
297
  # inspect directory with opendir, since glob might not be available in some systems
298
  clearstatcache();
300
  while (false !== ($file = readdir($handle))) {
301
  $file = $cachedir.'/'.$file;
302
  $ext = pathinfo($file, PATHINFO_EXTENSION);
303
+ if (in_array($ext, array('js', 'css'))) {
304
+ $log = file_get_contents($file.'.txt');
305
+ $mincss = substr($file, 0, -4).'.min.css';
306
+ $minjs = substr($file, 0, -3).'.min.js';
307
+ $filename = basename($file);
308
+ if ($ext == 'css' && file_exists($mincss)) { $filename = basename($mincss); }
309
+ if ($ext == 'js' && file_exists($minjs)) { $filename = basename($minjs); }
310
  $fsize = fastvelocity_format_filesize(filesize($file));
311
+ $uid = hash('adler32', $filename);
312
+ array_push($return[$ext], array('uid'=>$uid, 'filename' => $filename, 'log' => $log, 'fsize' => $fsize));
313
+ }
 
 
 
314
  }
315
  closedir($handle);
316
  }
317
+
318
+ header('Content-Type: application/json');
319
+ echo json_encode($return);
320
+ wp_die();
321
  }
322
 
323
 
352
  register_setting('fvm-group', 'fastvelocity_min_force_inline_css');
353
  register_setting('fvm-group', 'fastvelocity_min_remove_googlefonts');
354
  register_setting('fvm-group', 'fastvelocity_gfonts_method');
355
+ register_setting('fvm-group', 'fastvelocity_fontawesome_method');
356
  register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed');
357
  register_setting('fvm-group', 'fastvelocity_min_defer_for_pagespeed_optimize');
358
  register_setting('fvm-group', 'fastvelocity_min_exclude_defer_login');
398
  add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
399
 
400
 
401
+ # purge all caches by request
402
+ add_action('init','fastvelocity_process_cache_purge_request');
403
+ function fastvelocity_process_cache_purge_request(){
404
+ if((isset($_POST['purgeall']) && $_POST['purgeall'] == 1) || isset($_GET['_fvmcache'])) {
405
+
406
+ # must be able to cleanup cache
407
+ if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
408
+
409
+ # validate nonce
410
+ if(isset($_GET['wordpress_fvmcache']) && (empty($_GET['_wpnonce']) || !wp_verify_nonce($_GET['_wpnonce'], 'fvm_clear_nonce'))) {
411
+ wp_die( __('Invalid or expired request... please go back and refresh before trying again!'));
412
+ }
413
+
414
+ if(is_admin()) {
415
+ fvm_purge_all(); # purge all
416
+ fastvelocity_purge_others(); # purge third party caches
417
+ $others = fastvelocity_purge_others(); # purge third party caches
418
+ $notice = array('All caches from <strong>FVM</strong> have been purged!', strip_tags($others, '<strong>'));
419
+ $notice = base64_encode(json_encode($notice)); # encode
420
+ setcookie('wordpress_fvmcache', $notice, time()+60, COOKIEPATH, COOKIE_DOMAIN );
421
+ wp_safe_redirect(remove_query_arg('_wpnonce', remove_query_arg('_fvmcache', wp_get_referer())));
422
+ } else {
423
+ fvm_purge_all(); # purge all
424
+ fastvelocity_purge_others(); # purge third party caches
425
+ wp_safe_redirect(remove_query_arg('_wpnonce', remove_query_arg('_fvmcache', wp_get_referer())));
426
+ }
427
+ }
428
+ }
429
+
430
+ # print admin notices after purging caches, if on wp-admin
431
+ add_action( 'admin_notices', 'fastvelocity_admin_notices' );
432
+ function fastvelocity_admin_notices() {
433
+
434
+ # cache purge notices
435
+ if(isset($_COOKIE['wordpress_fvmcache']) && !empty($_COOKIE['wordpress_fvmcache'])) {
436
+
437
+ # decode to array or null
438
+ $jsonarr = json_decode(base64_decode($_COOKIE['wordpress_fvmcache']), true);
439
+ if(!is_null($jsonarr) && is_array($jsonarr)){
440
+
441
+ # must be able to cleanup cache
442
+ if (!current_user_can('manage_options')) { wp_die( __('You do not have sufficient permissions to access this page.')); }
443
+
444
+ # print notices
445
+ foreach ($jsonarr as $notice) {
446
+ echo __('<div class="notice notice-success is-dismissible"><p>'.$notice.'</p></div>');
447
+ }
448
+ }
449
+
450
+ # remove
451
+ setcookie('wordpress_fvmcache', $notice, time()-3600, COOKIEPATH, COOKIE_DOMAIN );
452
+ }
453
+ }
454
+
455
+
456
+
457
 
458
  # manage settings page
459
  function fastvelocity_min_settings() {
469
  <div class="wrap">
470
  <h1>Fast Velocity Minify</h1>
471
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472
  <h2 class="nav-tab-wrapper wp-clearfix">
473
  <a href="?page=fastvelocity-min&tab=status" class="nav-tab <?php echo $active_tab == 'status' ? 'nav-tab-active' : ''; ?>">Status</a>
474
  <a href="?page=fastvelocity-min&tab=set" class="nav-tab <?php echo $active_tab == 'set' ? 'nav-tab-active' : ''; ?>">Settings</a>
613
 
614
 
615
  <tr>
616
+ <th scope="row">Font Options</th>
617
  <td>
618
  <p class="fvm-bold-green fvm-rowintro">The default options are usually good for performance.</p>
619
  <fieldset>
646
  $b = ''; if($sel == 2) { $b = ' checked="checked"'; }
647
  $c = ''; if($sel == 3) { $c = ' checked="checked"'; }
648
  ?>
649
+ <p class="fvm-bold-green fvm-rowintro">Choose how to include Google Fonts on your pages, when available:</p>
650
  <fieldset>
651
+ <label><input type="radio" name="fastvelocity_gfonts_method" value="1" <?php echo $a; ?>> Inline Google Fonts CSS</label> <span class="note-info">[ Will inline the <a target="_blank" href="https://caniuse.com/#feat=woff">woof</a> format only (with font hinting) ]</span><br>
652
  <label><input type="radio" name="fastvelocity_gfonts_method" value="2"<?php echo $b; ?>> Async Google Fonts CSS files</label> <span class="note-info">[ Will use <a target="_blank" href="https://caniuse.com/#feat=link-rel-preload">preload</a> with <a href="https://github.com/filamentgroup/loadCSS">LoadCSS</a> polyfill ]</span><br>
653
+ <label><input type="radio" name="fastvelocity_gfonts_method" value="3"<?php echo $c; ?>> Async and exclude Google Fonts CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
654
+ </fieldset>
655
+ </td>
656
+ </tr>
657
+
658
+ <tr>
659
+ <th scope="row">Font Awesome</th>
660
+ <td>
661
+ <?php
662
+ # what to select
663
+ $sel = get_option('fastvelocity_fontawesome_method');
664
+ $a = ''; if($sel == 1 || empty($sel)) { $a = ' checked="checked"'; }
665
+ $b = ''; if($sel == 2) { $b = ' checked="checked"'; }
666
+ $c = ''; if($sel == 3) { $c = ' checked="checked"'; }
667
+ ?>
668
+ <p class="fvm-bold-green fvm-rowintro">Only if available and if it has "font-awesome" in the url:</p>
669
+ <fieldset>
670
+ <label><input type="radio" name="fastvelocity_fontawesome_method" value="1" <?php echo $a; ?>> Merge or Inline Font Awesome CSS</label> <span class="note-info">[ Depends on if you have the Inline CSS option enabled or not ]</span><br>
671
+ <label><input type="radio" name="fastvelocity_fontawesome_method" value="2"<?php echo $b; ?>> Async Font Awesome CSS file</label> <span class="note-info">[ Will use <a target="_blank" href="https://caniuse.com/#feat=link-rel-preload">preload</a> with <a href="https://github.com/filamentgroup/loadCSS">LoadCSS</a> polyfill ]</span><br>
672
+ <label><input type="radio" name="fastvelocity_fontawesome_method" value="3"<?php echo $c; ?>> Async and exclude Font Awesome CSS from PSI</label> <span class="note-info">[ Will use JavaScript to load the fonts conditionally ] </span><br>
673
  </fieldset>
674
  </td>
675
  </tr>
676
 
677
+
678
  <tr>
679
  <th scope="row">CSS Options</th>
680
  <td>
699
  <br />
700
  <label for="fastvelocity_min_force_inline_css">
701
  <input name="fastvelocity_min_force_inline_css" type="checkbox" id="fastvelocity_min_force_inline_css" value="1" <?php echo checked(1 == get_option('fastvelocity_min_force_inline_css'), true, false); ?>>
702
+ Inline all CSS files <span class="note-info">[ If selected, CSS will be inlined to avoid the "render blocking" on PSI... good for small CSS code ]</span></label>
703
  <br />
704
  </fieldset></td>
705
  </tr>
708
  <tr>
709
  <th scope="row">JavaScript Options</th>
710
  <td>
711
+ <p class="fvm-bold-green fvm-rowintro">Try to disable minification (and purge the cache) first, if you have trouble with JavaScript in the frontend.</p>
712
  <fieldset>
713
  <label for="fastvelocity_min_disable_js_merge">
714
  <input name="fastvelocity_min_disable_js_merge" type="checkbox" id="fastvelocity_min_disable_js_merge" value="1" <?php echo checked(1 == get_option('fastvelocity_min_disable_js_merge'), true, false); ?> >
1163
  # process header javascript ###############
1164
  ###########################################
1165
  function fastvelocity_min_merge_header_scripts() {
1166
+ global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery, $fvm_debug, $fvm_min_excludejslist, $fvmualist;
1167
  if(!is_object($wp_scripts)) { return false; }
1168
  $scripts = wp_clone($wp_scripts);
1169
  $scripts->all_deps($scripts->queue);
1188
  # get full url
1189
  $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1190
 
1191
+ # Exclude JS files from PSI (Async) takes priority over the ignore list
1192
+ if($fvm_min_excludejslist != false || is_array($fvm_min_excludejslist)) {
1193
+
1194
+ # check for string match
1195
+ $skipjs = false;
1196
+ foreach($fvm_min_excludejslist as $l) {
1197
+ if (stripos($hurl, $l) !== false) {
1198
+ # print code if there are no linebreaks, or return
1199
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
1200
+ echo "loadAsync('$hurl', null);";
1201
+ echo '}</script>';
1202
+ $skipjs = true;
1203
+ break;
1204
+ }
1205
+ }
1206
+ if($skipjs != false) { continue; }
1207
+ }
1208
+
1209
  # IE only files don't increment things
1210
  $ieonly = fastvelocity_ie_blacklist($hurl);
1211
  if($ieonly == true) { continue; }
1321
  if(count($data) > 0) { $wp_scripts->registered["fvm-header-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1322
 
1323
  # enqueue file, if not empty
1324
+ if(file_exists($file) && (filesize($file) > 0 || count($data) > 0)) {
 
1325
  wp_enqueue_script("fvm-header-$i");
1326
  }
1327
 
1343
  # process js in the footer ################
1344
  ###########################################
1345
  function fastvelocity_min_merge_footer_scripts() {
1346
+ global $wp_scripts, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_js_merge, $disable_js_minification, $enable_defer_js, $exclude_defer_jquery, $fvm_debug, $fvm_min_excludejslist, $fvmualist;
1347
  if(!is_object($wp_scripts)) { return false; }
1348
  $ctime = get_option('fvm-last-cache-update', '0');
1349
  $scripts = wp_clone($wp_scripts);
1363
  # get full url
1364
  $hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
1365
 
1366
+ # Exclude JS files from PSI (Async) takes priority over the ignore list
1367
+ if($fvm_min_excludejslist != false || is_array($fvm_min_excludejslist)) {
1368
+
1369
+ # check for string match
1370
+ $skipjs = false;
1371
+ foreach($fvm_min_excludejslist as $l) {
1372
+ if (stripos($hurl, $l) !== false) {
1373
+ # print code if there are no linebreaks, or return
1374
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
1375
+ echo "loadAsync('$hurl', null);";
1376
+ echo '}</script>';
1377
+ $skipjs = true;
1378
+ break;
1379
+ }
1380
+ }
1381
+ if($skipjs != false) { continue; }
1382
+ }
1383
+
1384
  # IE only files don't increment things
1385
  $ieonly = fastvelocity_ie_blacklist($hurl);
1386
  if($ieonly == true) { continue; }
1479
  # register minified file
1480
  wp_register_script("fvm-footer-$i", $file_url, array(), null, false);
1481
 
 
 
 
 
1482
  # add all extra data from wp_localize_script
1483
  $data = array();
1484
  foreach($footer[$i]['handles'] as $handle) {
1487
  if(count($data) > 0) { $wp_scripts->registered["fvm-footer-$i"]->extra['data'] = implode(PHP_EOL, $data); }
1488
 
1489
  # enqueue file, if not empty
1490
+ if(file_exists($file) && (filesize($file) > 0 || count($data) > 0)) {
 
1491
  wp_enqueue_script("fvm-footer-$i");
1492
  }
1493
 
1577
  # process header css ######################
1578
  ###########################################
1579
  function fastvelocity_min_merge_header_css() {
1580
+ global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_min_excludecsslist, $fvm_debug, $fvm_min_excludecsslist, $fvm_fawesome_method;
1581
  if(!is_object($wp_styles)) { return false; }
1582
  $ctime = get_option('fvm-last-cache-update', '0');
1583
  $styles = wp_clone($wp_styles);
1612
  }
1613
 
1614
  # mediatype
1615
+ $mt = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
1616
+ if ($mt == 'screen' || $mt == 'screen, print' || empty($mt) || is_null($mt) || $mt == false) { $mt = 'all'; }
1617
+ $mediatype = $mt;
1618
 
1619
  # full url or empty
1620
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1634
  $done = array_merge($done, array($handle)); continue;
1635
  }
1636
 
1637
+ # font awesome processing, async css
1638
+ if($fvm_fawesome_method == 2 && stripos($hurl, 'font-awesome') !== false) {
1639
+ echo '<link rel="preload" href="'.$hurl.'" as="style" media="'.$mediatype.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
1640
+ echo '<noscript><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /></noscript>';
1641
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /><![endif]-->';
1642
+ $done = array_merge($done, array($handle)); continue;
1643
+ }
1644
+
1645
+ # font awesome processing, async and exclude from PSI
1646
+ if($fvm_fawesome_method == 3 && stripos($hurl, 'font-awesome') !== false) {
1647
+ $cssguid = 'fvm'.hash('adler32', $hurl);
1648
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
1649
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
1650
+ echo '}</script>';
1651
+ $done = array_merge($done, array($handle)); continue;
1652
+ }
1653
+
1654
  # array of info to save
1655
  $arr = array('handle'=>$handle, 'url'=>$hurl, 'conditional'=>$conditional, 'mediatype'=>$mediatype);
1656
 
1726
 
1727
  # inline css or fail
1728
  if($res['code'] !== false) {
1729
+
1730
+ # add font-display
1731
+ # https://developers.google.com/web/updates/2016/02/font-display
1732
+ $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
1733
+
1734
+ # inline
1735
  echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
1736
  } else {
1737
  echo "<!-- GOOGLE FONTS REQUEST FAILED for $gfurl -->\n";
1765
  $ieonly = fastvelocity_ie_blacklist($hurl);
1766
  if($ieonly == true) { continue; }
1767
 
1768
+ # skip ignore list, conditional css, external css, font-awesome merge
1769
+ if ( (!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home))
1770
+ || empty($hurl)
1771
+ || ($fvm_fawesome_method == 1 && stripos($href, 'font-awesome') !== false)) {
1772
 
1773
  # colect inline css for this handle
1774
  if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
1792
  }
1793
  endforeach;
1794
 
 
1795
  # reorder CSS by mediatypes
1796
  if(!$skip_cssorder) {
1797
  if(count($header) > 0) {
1801
  foreach($header as $array) {
1802
  if(isset($array['media'])) { $allmedia[$array['media']] = ''; }
1803
  }
1804
+
1805
  # extract handles by mediatype
1806
  $grouphandles = array();
1807
  foreach ($allmedia as $md=>$var) {
1808
  foreach($header as $array) {
1809
+ if (isset($array['media']) && $array['media'] === $md) {
1810
  foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
1811
  }
1812
  }
1910
 
1911
  # enqueue file, if not empty
1912
  } else {
1913
+ if(file_exists($file) && filesize($file) > 0) {
 
1914
 
1915
+ # inline CSS if mediatype is not of type "all" (such as mobile only), if the file is smaller than 20KB
1916
+ if(filesize($file) < 20000 && $header[$i]['media'] != 'all') {
1917
+ echo '<style id="fvm-header-'.$i.'" media="'.$header[$i]['media'].'">'.file_get_contents($file).'</style>';
1918
+ } else {
1919
+ # enqueue it
1920
+ wp_enqueue_style("fvm-header-$i", $file_url, array(), null, $header[$i]['media']);
1921
+ }
1922
+
1923
  }
1924
  }
1925
  }
1942
  # process css in the footer ###############
1943
  ###########################################
1944
  function fastvelocity_min_merge_footer_css() {
1945
+ global $wp_styles, $wp_domain, $wp_home, $wp_home_path, $cachedir, $cachedirurl, $ignore, $disable_css_merge, $disable_css_minification, $skip_google_fonts, $skip_cssorder, $remove_print_mediatypes, $force_inline_googlefonts, $css_hide_googlefonts, $min_async_googlefonts, $remove_googlefonts, $fvmloadcss, $fvm_remove_css, $fvmualist, $fvm_debug, $fvm_fawesome_method, $fvm_min_excludecsslist;
1946
 
1947
  if(!is_object($wp_styles)) { return false; }
1948
  $ctime = get_option('fvm-last-cache-update', '0');
1970
 
1971
  # google fonts to the top
1972
  foreach( $styles->to_do as $handle ) :
1973
+
1974
  # dequeue and get a list of google fonts, or requeue external
1975
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
1976
+
1977
  if (stripos($hurl, 'fonts.googleapis.com') !== false) {
1978
  wp_dequeue_style($handle);
1979
  if($remove_googlefonts != false) { $done = array_merge($done, array($handle)); continue; } # mark as done if to be removed
1985
  } else {
1986
  wp_dequeue_style($handle); wp_enqueue_style($handle); # failsafe
1987
  }
1988
+
1989
  endforeach;
1990
 
1991
 
2063
 
2064
 
2065
  # get groups of handles
2066
+ $uniq = array();
2067
  foreach( $styles->to_do as $handle ) :
2068
 
2069
  # skip already processed google fonts
2070
  if(isset($google_fonts[$handle])) { continue; }
2071
+
2072
+ # conditionals
2073
+ $conditional = NULL; if(isset($wp_styles->registered[$handle]->extra["conditional"])) {
2074
+ $conditional = $wp_styles->registered[$handle]->extra["conditional"]; # such as ie7, ie8, ie9, etc
2075
+ }
2076
+
2077
+ # mediatype
2078
+ $mt = isset($wp_styles->registered[$handle]->args) ? $wp_styles->registered[$handle]->args : 'all';
2079
+ if ($mt == 'screen' || $mt == 'screen, print' || empty($mt) || is_null($mt) || $mt == false) { $mt = 'all'; }
2080
+ $mediatype = $mt;
2081
+
2082
  # get full url
2083
  $hurl = fastvelocity_min_get_hurl($wp_styles->registered[$handle]->src, $wp_domain, $wp_home);
2084
+
2085
+ # mark duplicates as done and remove from the queue
2086
+ if(!empty($hurl)) {
2087
+ $key = hash('adler32', $hurl);
2088
+ if (isset($uniq[$key])) { $done = array_merge($done, array($handle)); continue; } else { $uniq[$key] = $handle; }
2089
+ }
2090
 
2091
  # IE only files don't increment things
2092
  $ieonly = fastvelocity_ie_blacklist($hurl);
2093
  if($ieonly == true) { continue; }
2094
 
2095
+
2096
+ # Exclude specific CSS files from PSI?
2097
+ if($fvm_min_excludecsslist != false && is_array($fvm_min_excludecsslist) && fastvelocity_min_in_arrayi($hurl, $fvm_min_excludecsslist)) {
2098
+ $cssguid = 'fvm'.hash('adler32', $hurl);
2099
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2100
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2101
+ echo '}</script>';
2102
+ $done = array_merge($done, array($handle)); continue;
2103
+ }
2104
+
2105
+ # font awesome processing, async css
2106
+ if($fvm_fawesome_method == 2 && stripos($hurl, 'font-awesome') !== false) {
2107
+ echo '<link rel="preload" href="'.$hurl.'" as="style" media="'.$mediatype.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2108
+ echo '<noscript><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /></noscript>';
2109
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$hurl.'" media="'.$mediatype.'" /><![endif]-->';
2110
+ $done = array_merge($done, array($handle)); continue;
2111
+ }
2112
+
2113
+ # font awesome processing, async and exclude from PSI
2114
+ if($fvm_fawesome_method == 3 && stripos($hurl, 'font-awesome') !== false) {
2115
+ $cssguid = 'fvm'.hash('adler32', $hurl);
2116
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2117
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$hurl.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$mediatype.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2118
+ echo '}</script>';
2119
+ $done = array_merge($done, array($handle)); continue;
2120
  }
2121
 
2122
+ # skip ignore list, conditional css, external css, font-awesome merge
2123
+ if ( (!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($conditional) && fvm_internal_url($hurl, $wp_home))
2124
+ || empty($hurl)
2125
+ || ($fvm_fawesome_method == 1 && stripos($href, 'font-awesome') !== false)) {
2126
 
2127
  # colect inline css for this handle
2128
  if(isset($wp_styles->registered[$handle]->extra['after']) && is_array($wp_styles->registered[$handle]->extra['after'])) {
2132
 
2133
  # process
2134
  if(isset($footer[count($footer)-1]['handle']) || count($footer) == 0 || $footer[count($footer)-1]['media'] != $wp_styles->registered[$handle]->args) {
2135
+ array_push($footer, array('handles'=>array(),'media'=>$mediatype));
2136
  }
2137
 
2138
  # push it to the array get latest modified time
2161
  $grouphandles = array();
2162
  foreach ($allmedia as $md=>$var) {
2163
  foreach($footer as $array) {
2164
+ if (isset($array['media']) && $array['media'] === $md) {
2165
  foreach($array['handles'] as $h) { $grouphandles[$md][] = $h; }
2166
  }
2167
  }
2252
  }
2253
 
2254
  # register and enqueue minified file, consider excluding of mediatype "print" and inline css
2255
+ if ($remove_print_mediatypes != true || ($remove_print_mediatypes == true && $footer[$i]['media'] != 'print')) {
2256
 
2257
  # the developers tab, takes precedence
2258
 
2265
 
2266
  # enqueue file, if not empty
2267
  } else {
2268
+ if(file_exists($file) && filesize($file) > 0) {
2269
+
2270
+ # inline if the file is smaller than 20KB
2271
+ if(filesize($file) < 20000) {
2272
+ echo '<style id="fvm-footer-'.$i.'" media="'.$footer[$i]['media'].'">'.file_get_contents($file).'</style>';
2273
+ } else {
2274
+ # enqueue it
2275
+ wp_enqueue_style("fvm-footer-$i", $file_url, array(), null, $footer[$i]['media']);
2276
+ }
2277
  }
2278
  }
2279
  }
2300
 
2301
  echo <<<EOF
2302
  <script>
 
 
2303
  /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
2304
  !function(n){"use strict";n.loadCSS||(n.loadCSS=function(){});var o=loadCSS.relpreload={};if(o.support=function(){var e;try{e=n.document.createElement("link").relList.supports("preload")}catch(t){e=!1}return function(){return e}}(),o.bindMediaToggle=function(t){var e=t.media||"all";function a(){t.media=e}t.addEventListener?t.addEventListener("load",a):t.attachEvent&&t.attachEvent("onload",a),setTimeout(function(){t.rel="stylesheet",t.media="only x"}),setTimeout(a,3e3)},o.poly=function(){if(!o.support())for(var t=n.document.getElementsByTagName("link"),e=0;e<t.length;e++){var a=t[e];"preload"!==a.rel||"style"!==a.getAttribute("as")||a.getAttribute("data-loadcss")||(a.setAttribute("data-loadcss",!0),o.bindMediaToggle(a))}},!o.support()){o.poly();var t=n.setInterval(o.poly,500);n.addEventListener?n.addEventListener("load",function(){o.poly(),n.clearInterval(t)}):n.attachEvent&&n.attachEvent("onload",function(){o.poly(),n.clearInterval(t)})}"undefined"!=typeof exports?exports.loadCSS=loadCSS:n.loadCSS=loadCSS}("undefined"!=typeof global?global:this);
2305
  </script>
2307
 
2308
  }
2309
 
2310
+ # fvm load async scripts with callback
2311
+ function fvm_add_loadasync() {
2312
+
2313
+ echo <<<EOF
2314
+ <script>function loadAsync(e,a){var t=document.createElement("script");t.src=e,null!==a&&(t.readyState?t.onreadystatechange=function(){"loaded"!=t.readyState&&"complete"!=t.readyState||(t.onreadystatechange=null,a())}:t.onload=function(){a()}),document.getElementsByTagName("head")[0].appendChild(t)}</script>
2315
+ EOF;
2316
+
2317
+ }
2318
 
2319
 
2320
 
2387
  # optimize the ignore list for pagespeed insights + Exclude JS files from PSI (Async)
2388
  ###########################################
2389
  function fastvelocity_min_defer_js_optimize($tag, $handle, $src) {
2390
+ global $defer_for_pagespeed, $defer_for_pagespeed_optimize, $fvm_fix_editor, $fvmualist;
2391
 
2392
  # return if there are linebreaks (will break document.write)
2393
+ if (stripos($tag, PHP_EOL) !== false) { return $tag; }
2394
 
2395
  # fix page editors
2396
  if($fvm_fix_editor == true && is_user_logged_in()) { return $tag; }
2403
  $src = stristr($src, '?ver', true);
2404
  }
2405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2406
  # exclude ignored scripts
2407
  if(substr($handle, 0, 4) != "fvm-" && $defer_for_pagespeed == true && $defer_for_pagespeed_optimize == true) {
2408
 
2433
 
2434
  # inline css in place, instead of inlining the large file
2435
  function fastvelocity_optimizecss($html, $handle, $href, $media){
2436
+ global $fvm_debug, $wp_domain, $wp_home, $force_inline_css, $fvmualist, $fvm_collect_google_fonts, $force_inline_googlefonts, $min_async_googlefonts, $remove_googlefonts, $skip_google_fonts, $css_hide_googlefonts, $remove_print_mediatypes, $ignore, $blacklist, $ignorelist, $wp_home, $fvmloadcss, $fvm_remove_css, $fvm_cdn_url, $disable_minification, $fvm_min_excludecsslist, $disable_css_minification, $fvm_fix_editor, $fvm_fawesome_method;
2437
 
2438
  # current timestamp
2439
  $ctime = get_option('fvm-last-cache-update', '0');
2465
  }
2466
 
2467
  # mediatype fix for some plugins + remove print mediatypes
2468
+ if ($media == 'screen' || $media == 'screen, print' || empty($media) || is_null($media) || $media == false) { $media = 'all'; }
2469
  if($remove_print_mediatypes != false && $media == 'print') {
2470
  return false;
2471
  }
2490
  return false;
2491
  }
2492
 
 
2493
  # handle google fonts here, when merging is disabled
2494
  if(stripos($href, 'fonts.googleapis.com') !== false && $skip_google_fonts != false) {
2495
 
2511
  }
2512
  }
2513
 
2514
+ # font awesome processing, async css
2515
+ if($fvm_fawesome_method == 2 && stripos($href, 'font-awesome') !== false) {
2516
+ echo '<link rel="preload" href="'.$href.'" as="style" media="'.$media.'" onload="this.onload=null;this.rel=\'stylesheet\'" />';
2517
+ echo '<noscript><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /></noscript>';
2518
+ echo '<!--[if IE]><link rel="stylesheet" href="'.$href.'" media="'.$media.'" /><![endif]-->';
2519
+ return false;
2520
+ }
2521
+
2522
+ # font awesome processing, async and exclude from PSI
2523
+ if($fvm_fawesome_method == 3 && stripos($href, 'font-awesome') !== false) {
2524
+ $cssguid = 'fvm'.hash('adler32', $href);
2525
+ echo '<script type="text/javascript">if(!navigator.userAgent.match(/'.implode('|', $fvmualist).'/i)){';
2526
+ echo 'var '.$cssguid.'=document.createElement("link");'.$cssguid.'.rel="stylesheet",'.$cssguid.'.type="text/css",'.$cssguid.'.media="async",'.$cssguid.'.href="'.$href.'",'.$cssguid.'.onload=function(){'.$cssguid.'.media="'.$media.'"},document.getElementsByTagName("head")[0].appendChild('.$cssguid.');';
2527
+ echo '}</script>';
2528
+ return false;
2529
+ }
2530
+
2531
+ # font awesome processing, inline
2532
+ if($fvm_fawesome_method == 1 && stripos($href, 'font-awesome') !== false) {
2533
+
2534
+ # download, minify, cache
2535
+ $tkey = 'css-'.$ctime.'-'.hash('adler32', $handle.$href).'.css';
2536
+ $json = false; $json = fvm_get_transient($tkey);
2537
+ if ( $json === false) {
2538
+ $json = fvm_download_and_minify($href, null, $disable_css_minification, 'css', $handle);
2539
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Uncached file processing now for $handle / $href -->" . PHP_EOL; }
2540
+ fvm_set_transient($tkey, $json);
2541
+ }
2542
+
2543
+ # decode
2544
+ $res = json_decode($json, true);
2545
+
2546
+ # add font-display
2547
+ # https://developers.google.com/web/updates/2016/02/font-display
2548
+ $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
2549
+
2550
+ # inline css or fail
2551
+ if($res['status'] != false) {
2552
+ echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2553
+ return false;
2554
+ } else {
2555
+ if($fvm_debug == true) { echo "<!-- FVM DEBUG: Font Awesome request failed for $href -->" . PHP_EOL; }
2556
+ return $html;
2557
+ }
2558
+ }
2559
+
2560
  # inline google fonts, do not collect
2561
  if(stripos($href, 'fonts.googleapis.com') !== false && $force_inline_googlefonts != false && $css_hide_googlefonts != true && $min_async_googlefonts != true) {
2562
 
2572
  # decode
2573
  $res = json_decode($json, true);
2574
 
2575
+ # add font-display
2576
+ # https://developers.google.com/web/updates/2016/02/font-display
2577
+ $res['code'] = str_ireplace('font-style:normal;', 'font-display:block;font-style:normal;', $res['code']);
2578
+
2579
  # inline css or fail
2580
  if($res['status'] != false) {
2581
  echo '<style type="text/css" media="all">'.$res['code'].'</style>'.PHP_EOL;
2592
  return false;
2593
  }
2594
 
 
2595
  # skip external scripts that are not specifically allowed
2596
  if (fvm_internal_url($href, $wp_home) === false || empty($href)) {
2597
  if($fvm_debug == true) { echo "<!-- FVM DEBUG: Skipped the next external enqueued CSS -->" . PHP_EOL; }
inc/functions.php CHANGED
@@ -7,7 +7,7 @@ if(function_exists('mb_internal_encoding')) { mb_internal_encoding('UTF-8'); }
7
  @ini_set('pcre.backtrack_limit',5000000);
8
  @ini_set('pcre.recursion_limit',5000000);
9
 
10
- # Consider fallback to PHP Minify [2017.12.17] from https://github.com/matthiasmullie/minify (must be defined on the outer scope)
11
  $path = $plugindir . 'libs/matthiasmullie';
12
  require_once $path . '/minify/src/Minify.php';
13
  require_once $path . '/minify/src/CSS.php';
@@ -66,7 +66,7 @@ function fastvelocity_plugin_activate() {
66
  fvm_cache_increment();
67
 
68
  # default blacklist
69
- $exc = array('/html5shiv.js', '/html5shiv-printshiv.min.js', '/excanvas.js', '/avada-ie9.js', '/respond.js', '/respond.min.js', '/selectivizr.js', '/Avada/assets/css/ie.css', '/html5.js', '/IE9.js', '/fusion-ie9.js', '/vc_lte_ie9.min.css', '/old-ie.css', '/ie.css', '/vc-ie8.min.css', '/mailchimp-for-wp/assets/js/third-party/placeholders.min.js', '/assets/js/plugins/wp-enqueue/min/webfontloader.js', '/a.optnmstr.com/app/js/api.min.js', '/pixelyoursite/js/public.js');
70
  update_option('fastvelocity_min_blacklist', implode(PHP_EOL, $exc));
71
 
72
  # default ignore list
@@ -273,6 +273,11 @@ if(!$disable_js_minification) {
273
  $js = fvm_compat_urls($js);
274
  }
275
 
 
 
 
 
 
276
  # needed when merging js files
277
  $js = trim($js);
278
  if(substr($js, -1) != ';'){ $js = $js.';'; }
@@ -286,15 +291,17 @@ return $js . PHP_EOL;
286
  # minify JS string with PHP Minify or YUI Compressors
287
  function fastvelocity_min_minify_js_string($js) {
288
  global $tmpdir, $plugindir;
289
-
290
- # PHP Minify [2016.08.01] from https://github.com/matthiasmullie/minify
291
- $minifier = new Minify\JS($js);
292
- $min = $minifier->minify();
293
- if($min !== false && (strlen(trim($js)) == strlen(trim($min)) || strlen(trim($min)) > 0)) { return fvm_compat_urls($min); }
294
-
295
- # if we are here, something went wrong and minification didn't work
296
- $js = "\n/*! Fast Velocity Minify: Minification of the following section has failed, so it has been merged instead. */\n".$js;
297
- return fvm_compat_urls($js);
 
 
298
  }
299
 
300
  # functions, minify html
7
  @ini_set('pcre.backtrack_limit',5000000);
8
  @ini_set('pcre.recursion_limit',5000000);
9
 
10
+ # Consider fallback to PHP Minify [2018.12.03] from https://github.com/matthiasmullie/minify (must be defined on the outer scope)
11
  $path = $plugindir . 'libs/matthiasmullie';
12
  require_once $path . '/minify/src/Minify.php';
13
  require_once $path . '/minify/src/CSS.php';
66
  fvm_cache_increment();
67
 
68
  # default blacklist
69
+ $exc = array('/html5shiv.js', '/html5shiv-printshiv.min.js', '/excanvas.js', '/avada-ie9.js', '/respond.js', '/respond.min.js', '/selectivizr.js', '/Avada/assets/css/ie.css', '/html5.js', '/IE9.js', '/fusion-ie9.js', '/vc_lte_ie9.min.css', '/old-ie.css', '/ie.css', '/vc-ie8.min.css', '/mailchimp-for-wp/assets/js/third-party/placeholders.min.js', '/assets/js/plugins/wp-enqueue/min/webfontloader.js', '/a.optnmstr.com/app/js/api.min.js', '/pixelyoursite/js/public.js', '/assets/js/wcdrip-drip.js');
70
  update_option('fastvelocity_min_blacklist', implode(PHP_EOL, $exc));
71
 
72
  # default ignore list
273
  $js = fvm_compat_urls($js);
274
  }
275
 
276
+ # try to remove source mapping files
277
+ $filename = basename($url);
278
+ $remove = array("//# sourceMappingURL=$filename.map", "//# sourceMappingURL = $filename.map");
279
+ $js = str_ireplace($remove, '', $js);
280
+
281
  # needed when merging js files
282
  $js = trim($js);
283
  if(substr($js, -1) != ';'){ $js = $js.';'; }
291
  # minify JS string with PHP Minify or YUI Compressors
292
  function fastvelocity_min_minify_js_string($js) {
293
  global $tmpdir, $plugindir;
294
+
295
+ # PHP Minify from https://github.com/matthiasmullie/minify
296
+ $minifier = new Minify\JS($js);
297
+ $min = $minifier->minify();
298
+ if($min !== false && (strlen(trim($js)) == strlen(trim($min)) || strlen(trim($min)) > 0)) {
299
+ return fvm_compat_urls($min);
300
+ }
301
+
302
+ # if we are here, something went wrong and minification didn't work
303
+ $js = "\n/*! FVM: Minification of the following section failed, so it has been merged instead. */\n".$js;
304
+ return fvm_compat_urls($js);
305
  }
306
 
307
  # functions, minify html
libs/matthiasmullie/minify/src/CSS.php CHANGED
@@ -307,10 +307,11 @@ class CSS extends Minify
307
  */
308
  $this->extractStrings();
309
  $this->stripComments();
 
310
  $css = $this->replace($css);
311
 
312
  $css = $this->stripWhitespace($css);
313
- $css = $this->shortenHex($css);
314
  $css = $this->shortenZeroes($css);
315
  $css = $this->shortenFontWeights($css);
316
  $css = $this->stripEmptyTags($css);
@@ -481,12 +482,16 @@ class CSS extends Minify
481
  *
482
  * @return string
483
  */
484
- protected function shortenHex($content)
485
  {
486
- $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?=[; }])/i', '#$1$2$3', $content);
 
 
 
 
487
 
488
- // we can shorten some even more by replacing them with their color name
489
  $colors = array(
 
490
  '#F0FFFF' => 'azure',
491
  '#F5F5DC' => 'beige',
492
  '#A52A2A' => 'brown',
@@ -514,6 +519,9 @@ class CSS extends Minify
514
  '#FF6347' => 'tomato',
515
  '#EE82EE' => 'violet',
516
  '#F5DEB3' => 'wheat',
 
 
 
517
  );
518
 
519
  return preg_replace_callback(
@@ -559,11 +567,7 @@ class CSS extends Minify
559
  // `5px - 0px` is valid, but `5px - 0` is not
560
  // `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
561
  // `10 * 0` is invalid
562
- // best to just leave `calc()`s alone, even if they could be optimized
563
- // (which is a whole other undertaking, where units & order of
564
- // operations all need to be considered...)
565
- $calcs = $this->findCalcs($content);
566
- $content = str_replace($calcs, array_keys($calcs), $content);
567
 
568
  // reusable bits of code throughout these regexes:
569
  // before & after are used to make sure we don't match lose unintended
@@ -600,9 +604,6 @@ class CSS extends Minify
600
  $content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content);
601
  $content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
602
 
603
- // restore `calc()` expressions
604
- $content = str_replace(array_keys($calcs), $calcs, $content);
605
-
606
  return $content;
607
  }
608
 
@@ -626,6 +627,17 @@ class CSS extends Minify
626
  */
627
  protected function stripComments()
628
  {
 
 
 
 
 
 
 
 
 
 
 
629
  $this->registerPattern('/\/\*.*?\*\//s', '');
630
  }
631
 
@@ -648,8 +660,8 @@ class CSS extends Minify
648
  // remove whitespace around meta characters
649
  // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
650
  $content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
651
- $content = preg_replace('/([\[(:])\s+/', '$1', $content);
652
- $content = preg_replace('/\s+([\]\)])/', '$1', $content);
653
  $content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
654
 
655
  // whitespace around + and - can only be stripped inside some pseudo-
@@ -666,18 +678,13 @@ class CSS extends Minify
666
  }
667
 
668
  /**
669
- * Find all `calc()` occurrences.
670
- *
671
- * @param string $content The CSS content to find `calc()`s in.
672
- *
673
- * @return string[]
674
  */
675
- protected function findCalcs($content)
676
  {
677
- $results = array();
678
- preg_match_all('/calc(\(.+?)(?=$|;|calc\()/', $content, $matches, PREG_SET_ORDER);
679
-
680
- foreach ($matches as $match) {
681
  $length = strlen($match[1]);
682
  $expr = '';
683
  $opened = 0;
@@ -691,11 +698,17 @@ class CSS extends Minify
691
  break;
692
  }
693
  }
 
 
694
 
695
- $results['calc('.count($results).')'] = 'calc'.$expr;
696
- }
 
 
 
 
697
 
698
- return $results;
699
  }
700
 
701
  /**
307
  */
308
  $this->extractStrings();
309
  $this->stripComments();
310
+ $this->extractCalcs();
311
  $css = $this->replace($css);
312
 
313
  $css = $this->stripWhitespace($css);
314
+ $css = $this->shortenColors($css);
315
  $css = $this->shortenZeroes($css);
316
  $css = $this->shortenFontWeights($css);
317
  $css = $this->stripEmptyTags($css);
482
  *
483
  * @return string
484
  */
485
+ protected function shortenColors($content)
486
  {
487
+ $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?:([0-9a-z])\\4)?(?=[; }])/i', '#$1$2$3$4', $content);
488
+
489
+ // remove alpha channel if it's pointless...
490
+ $content = preg_replace('/(?<=[: ])#([0-9a-z]{6})ff?(?=[; }])/i', '#$1', $content);
491
+ $content = preg_replace('/(?<=[: ])#([0-9a-z]{3})f?(?=[; }])/i', '#$1', $content);
492
 
 
493
  $colors = array(
494
+ // we can shorten some even more by replacing them with their color name
495
  '#F0FFFF' => 'azure',
496
  '#F5F5DC' => 'beige',
497
  '#A52A2A' => 'brown',
519
  '#FF6347' => 'tomato',
520
  '#EE82EE' => 'violet',
521
  '#F5DEB3' => 'wheat',
522
+ // or the other way around
523
+ 'WHITE' => '#fff',
524
+ 'BLACK' => '#000',
525
  );
526
 
527
  return preg_replace_callback(
567
  // `5px - 0px` is valid, but `5px - 0` is not
568
  // `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
569
  // `10 * 0` is invalid
570
+ // we've extracted calcs earlier, so we don't need to worry about this
 
 
 
 
571
 
572
  // reusable bits of code throughout these regexes:
573
  // before & after are used to make sure we don't match lose unintended
604
  $content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content);
605
  $content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
606
 
 
 
 
607
  return $content;
608
  }
609
 
627
  */
628
  protected function stripComments()
629
  {
630
+ // PHP only supports $this inside anonymous functions since 5.4
631
+ $minifier = $this;
632
+ $callback = function ($match) use ($minifier) {
633
+ $count = count($minifier->extracted);
634
+ $placeholder = '/*'.$count.'*/';
635
+ $minifier->extracted[$placeholder] = $match[0];
636
+
637
+ return $placeholder;
638
+ };
639
+ $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback);
640
+
641
  $this->registerPattern('/\/\*.*?\*\//s', '');
642
  }
643
 
660
  // remove whitespace around meta characters
661
  // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
662
  $content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
663
+ $content = preg_replace('/([\[(:>\+])\s+/', '$1', $content);
664
+ $content = preg_replace('/\s+([\]\)>\+])/', '$1', $content);
665
  $content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
666
 
667
  // whitespace around + and - can only be stripped inside some pseudo-
678
  }
679
 
680
  /**
681
+ * Replace all `calc()` occurrences.
 
 
 
 
682
  */
683
+ protected function extractCalcs()
684
  {
685
+ // PHP only supports $this inside anonymous functions since 5.4
686
+ $minifier = $this;
687
+ $callback = function ($match) use ($minifier) {
 
688
  $length = strlen($match[1]);
689
  $expr = '';
690
  $opened = 0;
698
  break;
699
  }
700
  }
701
+ $rest = str_replace($expr, '', $match[1]);
702
+ $expr = trim(substr($expr, 1, -1));
703
 
704
+ $count = count($minifier->extracted);
705
+ $placeholder = 'calc('.$count.')';
706
+ $minifier->extracted[$placeholder] = 'calc('.$expr.')';
707
+
708
+ return $placeholder.$rest;
709
+ };
710
 
711
+ $this->registerPattern('/calc(\(.+?)(?=$|;|calc\()/', $callback);
712
  }
713
 
714
  /**
libs/matthiasmullie/minify/src/JS.php CHANGED
@@ -195,11 +195,21 @@ class JS extends Minify
195
  */
196
  protected function stripComments()
197
  {
198
- // single-line comments
199
- $this->registerPattern('/\/\/.*$/m', '');
 
 
 
 
200
 
 
 
201
  // multi-line comments
 
202
  $this->registerPattern('/\/\*.*?\*\//s', '');
 
 
 
203
  }
204
 
205
  /**
@@ -238,7 +248,7 @@ class JS extends Minify
238
  // closing the regex)
239
  // then also ignore bare `/` inside `[]`, where they don't need to be
240
  // escaped: anything inside `[]` can be ignored safely
241
- $pattern = '\\/(?:[^\\[\\/\\\\\n\r]+|(?:\\\\.)+|(?:\\[(?:[^\\]\\\\\n\r]+|(?:\\\\.)+)+\\])+)++\\/[gimuy]*';
242
 
243
  // a regular expression can only be followed by a few operators or some
244
  // of the RegExp methods (a `\` followed by a variable or value is
@@ -335,7 +345,9 @@ class JS extends Minify
335
  array(
336
  '/('.implode('|', $operatorsBefore).')\s+/',
337
  '/\s+('.implode('|', $operatorsAfter).')/',
338
- ), '\\1', $content
 
 
339
  );
340
 
341
  // make sure + and - can't be mistaken for, or joined into ++ and --
@@ -343,7 +355,9 @@ class JS extends Minify
343
  array(
344
  '/(?<![\+\-])\s*([\+\-])(?![\+\-])/',
345
  '/(?<![\+\-])([\+\-])\s*(?![\+\-])/',
346
- ), '\\1', $content
 
 
347
  );
348
 
349
  // collapse whitespace around reserved words into single space
195
  */
196
  protected function stripComments()
197
  {
198
+ // PHP only supports $this inside anonymous functions since 5.4
199
+ $minifier = $this;
200
+ $callback = function ($match) use ($minifier) {
201
+ $count = count($minifier->extracted);
202
+ $placeholder = '/*'.$count.'*/';
203
+ $minifier->extracted[$placeholder] = $match[0];
204
 
205
+ return $placeholder;
206
+ };
207
  // multi-line comments
208
+ $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback);
209
  $this->registerPattern('/\/\*.*?\*\//s', '');
210
+
211
+ // single-line comments
212
+ $this->registerPattern('/\/\/.*$/m', '');
213
  }
214
 
215
  /**
248
  // closing the regex)
249
  // then also ignore bare `/` inside `[]`, where they don't need to be
250
  // escaped: anything inside `[]` can be ignored safely
251
+ $pattern = '\\/(?!\*)(?:[^\\[\\/\\\\\n\r]++|(?:\\\\.)++|(?:\\[(?:[^\\]\\\\\n\r]++|(?:\\\\.)++)++\\])++)++\\/[gimuy]*';
252
 
253
  // a regular expression can only be followed by a few operators or some
254
  // of the RegExp methods (a `\` followed by a variable or value is
345
  array(
346
  '/('.implode('|', $operatorsBefore).')\s+/',
347
  '/\s+('.implode('|', $operatorsAfter).')/',
348
+ ),
349
+ '\\1',
350
+ $content
351
  );
352
 
353
  // make sure + and - can't be mistaken for, or joined into ++ and --
355
  array(
356
  '/(?<![\+\-])\s*([\+\-])(?![\+\-])/',
357
  '/(?<![\+\-])([\+\-])\s*(?![\+\-])/',
358
+ ),
359
+ '\\1',
360
+ $content
361
  );
362
 
363
  // collapse whitespace around reserved words into single space
libs/matthiasmullie/minify/src/Minify.php CHANGED
@@ -241,7 +241,7 @@ abstract class Minify
241
 
242
  // we can safely ignore patterns for positions we've unset earlier,
243
  // because we know these won't show up anymore
244
- if (!isset($positions[$i])) {
245
  continue;
246
  }
247
 
241
 
242
  // we can safely ignore patterns for positions we've unset earlier,
243
  // because we know these won't show up anymore
244
+ if (array_key_exists($i, $positions) == false) {
245
  continue;
246
  }
247
 
libs/matthiasmullie/path-converter/src/Converter.php CHANGED
@@ -31,16 +31,17 @@ class Converter implements ConverterInterface
31
  /**
32
  * @param string $from The original base path (directory, not file!)
33
  * @param string $to The new base path (directory, not file!)
 
34
  */
35
- public function __construct($from, $to)
36
  {
37
  $shared = $this->shared($from, $to);
38
  if ($shared === '') {
39
  // when both paths have nothing in common, one of them is probably
40
  // absolute while the other is relative
41
- $cwd = getcwd();
42
- $from = strpos($from, $cwd) === 0 ? $from : $cwd.'/'.$from;
43
- $to = strpos($to, $cwd) === 0 ? $to : $cwd.'/'.$to;
44
 
45
  // or traveling the tree via `..`
46
  // attempt to resolve path, or assume it's fine if it doesn't exist
@@ -155,7 +156,7 @@ class Converter implements ConverterInterface
155
  $to = mb_substr($this->to, mb_strlen($shared));
156
 
157
  // add .. for every directory that needs to be traversed to new path
158
- $to = str_repeat('../', mb_substr_count($to, '/'));
159
 
160
  return $to.ltrim($path, '/');
161
  }
31
  /**
32
  * @param string $from The original base path (directory, not file!)
33
  * @param string $to The new base path (directory, not file!)
34
+ * @param string $root Root directory (defaults to `getcwd`)
35
  */
36
+ public function __construct($from, $to, $root = '')
37
  {
38
  $shared = $this->shared($from, $to);
39
  if ($shared === '') {
40
  // when both paths have nothing in common, one of them is probably
41
  // absolute while the other is relative
42
+ $root = $root ?: getcwd();
43
+ $from = strpos($from, $root) === 0 ? $from : preg_replace('/\/+/', '/', $root.'/'.$from);
44
+ $to = strpos($to, $root) === 0 ? $to : preg_replace('/\/+/', '/', $root.'/'.$to);
45
 
46
  // or traveling the tree via `..`
47
  // attempt to resolve path, or assume it's fine if it doesn't exist
156
  $to = mb_substr($this->to, mb_strlen($shared));
157
 
158
  // add .. for every directory that needs to be traversed to new path
159
+ $to = str_repeat('../', count(array_filter(explode('/', $to))));
160
 
161
  return $to.ltrim($path, '/');
162
  }
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: Alignak
3
  Tags: PHP Minify, Lighthouse, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance, Optimization, Speed, Fast
4
  Requires at least: 4.5
5
- Stable tag: 2.4.2
6
  Tested up to: 5.0
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -202,6 +202,16 @@ If you would like to donate any amount to the plugin author (thank you in advanc
202
 
203
  == Changelog ==
204
 
 
 
 
 
 
 
 
 
 
 
205
  = 2.4.2 [2018.11.29] =
206
  * fixed a bug with the "Exclude JS files in the ignore list from PSI" option (it wasn't excluding properly)
207
  * improved functionality with the "Exclude CSS files from PSI" option (now works with both inline and link stylesheets)
2
  Contributors: Alignak
3
  Tags: PHP Minify, Lighthouse, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance, Optimization, Speed, Fast
4
  Requires at least: 4.5
5
+ Stable tag: 2.4.3
6
  Tested up to: 5.0
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
202
 
203
  == Changelog ==
204
 
205
+ = 2.4.3 [2018.12.03] =
206
+ * added font-display, to ensure text remains visible during webfont load for inlined google fonts and font-awesome
207
+ * added automatic removal of "source mappings" from JS files during merging or minification
208
+ * added font awesome async and exclusion from PSI options, as well as merging and inlining when the url matches "font-awesome" (ie: cdnjs)
209
+ * added automatically inline of small CSS code (up to 20KB) for any FVM CSS files in the footer (requests reduction)
210
+ * added automatically inline of small CSS code (up to 20KB) for any FVM CSS files in the header, which are not of mediatype "all"
211
+ * improved the cache purge button (no more redirect from frontend to backend)
212
+ * updated PHP Minify and Path Converter from master
213
+ * bug fixes related to "Exclude JS files from PSI" option
214
+
215
  = 2.4.2 [2018.11.29] =
216
  * fixed a bug with the "Exclude JS files in the ignore list from PSI" option (it wasn't excluding properly)
217
  * improved functionality with the "Exclude CSS files from PSI" option (now works with both inline and link stylesheets)