Version Description
[2018.02.19] = * fixed a bug with the blacklist functionality * replaced PHP Minify with JSMin as the default JS minification * replaced PHP Minify with CSSTidy as the default CSS minification * replaced PHP Minify with Minify HTML as the default HTML minification * moved the intermediary cache from transients to disk files
Download this release
Release Info
Developer | Alignak |
Plugin | Fast Velocity Minify |
Version | 2.2.7 |
Comparing to | |
See all releases |
Code changes from version 2.2.6 to 2.2.7
- fvm.php +13 -10
- inc/functions-serverinfo.php +6 -5
- inc/functions.php +153 -74
- libs/CSSTidy/class.csstidy.php +1296 -0
- libs/CSSTidy/class.csstidy_optimise.php +963 -0
- libs/CSSTidy/class.csstidy_print.php +446 -0
- libs/CSSTidy/data.inc.php +646 -0
- libs/CSSTidy/lang.inc.php +309 -0
- libs/JSMin/jsmin.php +386 -0
- libs/matthiasmullie/index.html +0 -0
- libs/matthiasmullie/minify/bin/index.html +0 -0
- libs/matthiasmullie/minify/bin/minifycss +0 -45
- libs/matthiasmullie/minify/bin/minifyjs +0 -45
- libs/matthiasmullie/minify/data/index.html +0 -0
- libs/matthiasmullie/minify/data/js/index.html +0 -0
- libs/matthiasmullie/minify/data/js/keywords_after.txt +0 -7
- libs/matthiasmullie/minify/data/js/keywords_before.txt +0 -26
- libs/matthiasmullie/minify/data/js/keywords_reserved.txt +0 -63
- libs/matthiasmullie/minify/data/js/operators.txt +0 -46
- libs/matthiasmullie/minify/data/js/operators_after.txt +0 -43
- libs/matthiasmullie/minify/data/js/operators_before.txt +0 -43
- libs/matthiasmullie/minify/index.html +0 -0
- libs/matthiasmullie/minify/src/CSS.php +0 -735
- libs/matthiasmullie/minify/src/Exception.php +0 -20
- libs/matthiasmullie/minify/src/Exceptions/BasicException.php +0 -23
- libs/matthiasmullie/minify/src/Exceptions/FileImportException.php +0 -21
- libs/matthiasmullie/minify/src/Exceptions/IOException.php +0 -21
- libs/matthiasmullie/minify/src/Exceptions/index.html +0 -0
- libs/matthiasmullie/minify/src/JS.php +0 -577
- libs/matthiasmullie/minify/src/Minify.php +0 -444
- libs/matthiasmullie/minify/src/index.html +0 -0
- libs/matthiasmullie/path-converter/index.html +0 -0
- libs/matthiasmullie/path-converter/src/Converter.php +0 -195
- libs/matthiasmullie/path-converter/src/ConverterInterface.php +0 -24
- libs/matthiasmullie/path-converter/src/NoConverter.php +0 -23
- libs/matthiasmullie/path-converter/src/index.html +0 -0
- libs/mrclay/HTML.php +0 -241
- libs/mrclay/index.html +0 -0
- readme.txt +58 -91
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.2.
|
9 |
License: GPL2
|
10 |
|
11 |
------------------------------------------------------------------------
|
@@ -127,7 +127,7 @@ $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
|
|
127 |
$used_css_files = array();
|
128 |
|
129 |
# default blacklist
|
130 |
-
$exc = array('/html5shiv.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');
|
131 |
if(!is_array($blacklist) || strlen(implode($blacklist)) == 0) { update_option('fastvelocity_min_blacklist', implode("\n", $exc)); }
|
132 |
|
133 |
# default ignore list
|
@@ -862,7 +862,7 @@ $is_footer = 0; if (isset($wp_scripts->registered[$handle]->extra["group"]) || i
|
|
862 |
# IE only files don't increment things
|
863 |
$ieonly = fastvelocity_ie_blacklist($hurl);
|
864 |
if($ieonly == true) { continue; }
|
865 |
-
|
866 |
# skip ignore list, scripts with conditionals, external scripts
|
867 |
if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
|
868 |
|
@@ -887,6 +887,9 @@ $is_footer = 0; if (isset($wp_scripts->registered[$handle]->extra["group"]) || i
|
|
887 |
endforeach;
|
888 |
|
889 |
|
|
|
|
|
|
|
890 |
# loop through header scripts and merge
|
891 |
for($i=0,$l=count($header);$i<$l;$i++) {
|
892 |
if(!isset($header[$i]['handle'])) {
|
@@ -915,9 +918,9 @@ for($i=0,$l=count($header);$i<$l;$i++) {
|
|
915 |
$hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
|
916 |
$printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
|
917 |
|
918 |
-
# get
|
919 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
|
920 |
-
$newcode = false; $newcode =
|
921 |
if ( $newcode === false) {
|
922 |
$res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
|
923 |
if(is_array($res)) {
|
@@ -1050,7 +1053,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
|
|
1050 |
|
1051 |
# get css from hurl, if available and valid
|
1052 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
|
1053 |
-
$newcode = false; $newcode =
|
1054 |
if ( $newcode === false) {
|
1055 |
$res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
|
1056 |
if(is_array($res)) {
|
@@ -1255,7 +1258,7 @@ if(!$skip_google_fonts && count($google_fonts) > 0) {
|
|
1255 |
|
1256 |
# google fonts download and inlining, ignore logs
|
1257 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
|
1258 |
-
$newcode = false; $newcode =
|
1259 |
if ( $newcode === false) {
|
1260 |
$res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
|
1261 |
if(is_array($res)) { $newcode = $res['code']; }
|
@@ -1383,7 +1386,7 @@ for($i=0,$l=count($header);$i<$l;$i++) {
|
|
1383 |
|
1384 |
# get css from hurl, if available and valid
|
1385 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
|
1386 |
-
$newcode = false; $newcode =
|
1387 |
if ( $newcode === false) {
|
1388 |
$res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
|
1389 |
if(is_array($res)) {
|
@@ -1519,7 +1522,7 @@ if(!$skip_google_fonts && count($google_fonts) > 0) {
|
|
1519 |
|
1520 |
# google fonts download and inlining, ignore logs
|
1521 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
|
1522 |
-
$newcode = false; $newcode =
|
1523 |
if ( $newcode === false) {
|
1524 |
$res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
|
1525 |
if(is_array($res)) { $newcode = $res['code']; }
|
@@ -1644,7 +1647,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
|
|
1644 |
|
1645 |
# get css from hurl, if available and valid
|
1646 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
|
1647 |
-
$newcode = false; $newcode =
|
1648 |
if ( $newcode === false) {
|
1649 |
$res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
|
1650 |
if(is_array($res)) {
|
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.2.7
|
9 |
License: GPL2
|
10 |
|
11 |
------------------------------------------------------------------------
|
127 |
$used_css_files = array();
|
128 |
|
129 |
# default blacklist
|
130 |
+
$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');
|
131 |
if(!is_array($blacklist) || strlen(implode($blacklist)) == 0) { update_option('fastvelocity_min_blacklist', implode("\n", $exc)); }
|
132 |
|
133 |
# default ignore list
|
862 |
# IE only files don't increment things
|
863 |
$ieonly = fastvelocity_ie_blacklist($hurl);
|
864 |
if($ieonly == true) { continue; }
|
865 |
+
|
866 |
# skip ignore list, scripts with conditionals, external scripts
|
867 |
if ((!fastvelocity_min_in_arrayi($hurl, $ignore) && !isset($wp_scripts->registered[$handle]->extra["conditional"]) && fvm_internal_url($hurl, $wp_home)) || empty($hurl)) {
|
868 |
|
887 |
endforeach;
|
888 |
|
889 |
|
890 |
+
|
891 |
+
|
892 |
+
|
893 |
# loop through header scripts and merge
|
894 |
for($i=0,$l=count($header);$i<$l;$i++) {
|
895 |
if(!isset($header[$i]['handle'])) {
|
918 |
$hurl = fastvelocity_min_get_hurl($wp_scripts->registered[$handle]->src, $wp_domain, $wp_home);
|
919 |
$printurl = str_ireplace(array(site_url(), home_url(), 'http:', 'https:'), '', $hurl);
|
920 |
|
921 |
+
# get code from hurl, if available and valid
|
922 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
|
923 |
+
$newcode = false; $newcode = fvm_get_transient($tkey);
|
924 |
if ( $newcode === false) {
|
925 |
$res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
|
926 |
if(is_array($res)) {
|
1053 |
|
1054 |
# get css from hurl, if available and valid
|
1055 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
|
1056 |
+
$newcode = false; $newcode = fvm_get_transient($tkey);
|
1057 |
if ( $newcode === false) {
|
1058 |
$res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
|
1059 |
if(is_array($res)) {
|
1258 |
|
1259 |
# google fonts download and inlining, ignore logs
|
1260 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
|
1261 |
+
$newcode = false; $newcode = fvm_get_transient($tkey);
|
1262 |
if ( $newcode === false) {
|
1263 |
$res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
|
1264 |
if(is_array($res)) { $newcode = $res['code']; }
|
1386 |
|
1387 |
# get css from hurl, if available and valid
|
1388 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
|
1389 |
+
$newcode = false; $newcode = fvm_get_transient($tkey);
|
1390 |
if ( $newcode === false) {
|
1391 |
$res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
|
1392 |
if(is_array($res)) {
|
1522 |
|
1523 |
# google fonts download and inlining, ignore logs
|
1524 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
|
1525 |
+
$newcode = false; $newcode = fvm_get_transient($tkey);
|
1526 |
if ( $newcode === false) {
|
1527 |
$res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
|
1528 |
if(is_array($res)) { $newcode = $res['code']; }
|
1647 |
|
1648 |
# get css from hurl, if available and valid
|
1649 |
$tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
|
1650 |
+
$newcode = false; $newcode = fvm_get_transient($tkey);
|
1651 |
if ( $newcode === false) {
|
1652 |
$res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
|
1653 |
if(is_array($res)) {
|
inc/functions-serverinfo.php
CHANGED
@@ -108,6 +108,7 @@ function fvm_get_generalinfo() {
|
|
108 |
### Function: Format Bytes Into TiB/GiB/MiB/KiB/Bytes
|
109 |
if(!function_exists('fvm_format_filesize')) {
|
110 |
function fvm_format_filesize($rawSize) {
|
|
|
111 |
if($rawSize / 1099511627776 > 1) {
|
112 |
return number_format_i18n($rawSize/1099511627776, 1).' '.__('TiB', 'fvm-serverinfo');
|
113 |
} elseif($rawSize / 1073741824 > 1) {
|
@@ -229,10 +230,10 @@ if(!function_exists('fvm_get_mysql_version')) {
|
|
229 |
if(!function_exists('fvm_get_mysql_data_usage')) {
|
230 |
function fvm_get_mysql_data_usage() {
|
231 |
global $wpdb;
|
232 |
-
$data_usage =
|
233 |
$tablesstatus = $wpdb->get_results("SHOW TABLE STATUS");
|
234 |
-
foreach($tablesstatus as
|
235 |
-
|
236 |
}
|
237 |
if (!$data_usage) {
|
238 |
$data_usage = __('N/A', 'fvm-serverinfo');
|
@@ -246,10 +247,10 @@ if(!function_exists('fvm_get_mysql_data_usage')) {
|
|
246 |
if(!function_exists('fvm_get_mysql_index_usage')) {
|
247 |
function fvm_get_mysql_index_usage() {
|
248 |
global $wpdb;
|
249 |
-
$index_usage =
|
250 |
$tablesstatus = $wpdb->get_results("SHOW TABLE STATUS");
|
251 |
foreach($tablesstatus as $tablestatus) {
|
252 |
-
$index_usage += $tablestatus->Index_length;
|
253 |
}
|
254 |
if (!$index_usage){
|
255 |
$index_usage = __('N/A', 'fvm-serverinfo');
|
108 |
### Function: Format Bytes Into TiB/GiB/MiB/KiB/Bytes
|
109 |
if(!function_exists('fvm_format_filesize')) {
|
110 |
function fvm_format_filesize($rawSize) {
|
111 |
+
if(!is_numeric($rawSize)) { return __('unknown', 'fvm-serverinfo'); }
|
112 |
if($rawSize / 1099511627776 > 1) {
|
113 |
return number_format_i18n($rawSize/1099511627776, 1).' '.__('TiB', 'fvm-serverinfo');
|
114 |
} elseif($rawSize / 1073741824 > 1) {
|
230 |
if(!function_exists('fvm_get_mysql_data_usage')) {
|
231 |
function fvm_get_mysql_data_usage() {
|
232 |
global $wpdb;
|
233 |
+
$data_usage = 0;
|
234 |
$tablesstatus = $wpdb->get_results("SHOW TABLE STATUS");
|
235 |
+
foreach($tablesstatus as $tablestatus) {
|
236 |
+
if(is_numeric($tablestatus->Data_length)) { $data_usage += $tablestatus->Data_length; }
|
237 |
}
|
238 |
if (!$data_usage) {
|
239 |
$data_usage = __('N/A', 'fvm-serverinfo');
|
247 |
if(!function_exists('fvm_get_mysql_index_usage')) {
|
248 |
function fvm_get_mysql_index_usage() {
|
249 |
global $wpdb;
|
250 |
+
$index_usage = 0;
|
251 |
$tablesstatus = $wpdb->get_results("SHOW TABLE STATUS");
|
252 |
foreach($tablesstatus as $tablestatus) {
|
253 |
+
if(is_numeric($tablestatus->Index_length)) { $index_usage += $tablestatus->Index_length; }
|
254 |
}
|
255 |
if (!$index_usage){
|
256 |
$index_usage = __('N/A', 'fvm-serverinfo');
|
inc/functions.php
CHANGED
@@ -3,21 +3,119 @@
|
|
3 |
# handle better utf-8 and unicode encoding
|
4 |
if(function_exists('mb_internal_encoding')) { mb_internal_encoding('UTF-8'); }
|
5 |
|
6 |
-
#
|
7 |
-
|
8 |
-
require_once $
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
# get cache directories and urls
|
23 |
function fvm_cachepath() {
|
@@ -133,7 +231,7 @@ function fastvelocity_min_in_arrayi($hurl, $ignore){
|
|
133 |
foreach ($ignore as $i) {
|
134 |
$i = str_ireplace(array('http://', 'https://'), '//', $i); # better compatibility
|
135 |
$i = strtok(urldecode(rawurldecode($i)), '?'); # no query string, decode entities
|
136 |
-
$i = trim(trim($i, '/'), '*'); # wildcard removal
|
137 |
if (stripos($hurl, $i) !== false) { return true; }
|
138 |
}
|
139 |
}
|
@@ -149,12 +247,19 @@ function fvm_compat_urls($code) {
|
|
149 |
}
|
150 |
|
151 |
|
152 |
-
# minify css string with
|
153 |
function fastvelocity_min_minify_css_string($css) {
|
154 |
-
$
|
155 |
-
$
|
156 |
-
$
|
157 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
return fvm_compat_urls($css);
|
159 |
}
|
160 |
|
@@ -191,7 +296,7 @@ if(!$disable_js_minification) {
|
|
191 |
}
|
192 |
|
193 |
# needed when merging js files
|
194 |
-
$js = $js
|
195 |
|
196 |
# return html
|
197 |
return $js;
|
@@ -224,9 +329,9 @@ if($use_yui == true && function_exists('exec') && exec('command -v java >/dev/nu
|
|
224 |
}
|
225 |
}
|
226 |
|
227 |
-
|
228 |
-
|
229 |
-
$min =
|
230 |
if($min !== false && (strlen(trim($js)) == strlen(trim($min)) || strlen(trim($min)) > 0)) { return fvm_compat_urls($min); }
|
231 |
|
232 |
# if we are here, something went wrong and minification didn't work
|
@@ -236,16 +341,16 @@ return fvm_compat_urls($js);
|
|
236 |
|
237 |
# functions, minify html
|
238 |
function fastvelocity_min_minify_html($html) {
|
239 |
-
return
|
240 |
}
|
241 |
|
242 |
# functions to minify HTML
|
243 |
function fastvelocity_min_html_compression_finish($html) { return fastvelocity_min_minify_html($html); }
|
244 |
function fastvelocity_min_html_compression_start() {
|
245 |
-
if (fastvelocity_exclude_contents() == true) { return; }
|
246 |
-
$use_alt_html_minification = get_option('fastvelocity_min_use_alt_html_minification', '0');
|
247 |
-
if($use_alt_html_minification == '1') { ob_start('fastvelocity_min_minify_alt_html'); }
|
248 |
-
else { ob_start('fastvelocity_min_html_compression_finish'); }
|
249 |
}
|
250 |
|
251 |
# alternative html minification, minimal
|
@@ -261,16 +366,15 @@ return $html;
|
|
261 |
function fastvelocity_rrmdir($dir) {
|
262 |
if(is_dir(rtrim($dir, '/'))) {
|
263 |
if ($handle = opendir($dir.'/')) {
|
264 |
-
while (false !== ($file = readdir($handle))) {
|
265 |
-
|
266 |
-
|
|
|
267 |
closedir($handle); }
|
268 |
}
|
269 |
}
|
270 |
|
271 |
|
272 |
-
|
273 |
-
|
274 |
# return size in human format
|
275 |
function fastvelocity_format_filesize($bytes, $decimals = 2) {
|
276 |
$units = array( 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' );
|
@@ -360,8 +464,7 @@ if (stripos($hurl, $wp_domain) !== false) {
|
|
360 |
if (file_exists($f)) {
|
361 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
|
362 |
else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
|
363 |
-
|
364 |
-
fvm_update_transient_keys($tkey); # keep track
|
365 |
$log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
|
366 |
return array('log'=>$log, 'code'=>$code);
|
367 |
}
|
@@ -373,8 +476,7 @@ if (stripos($hurl, $wp_domain) !== false) {
|
|
373 |
if (file_exists($f)) {
|
374 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
|
375 |
else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
|
376 |
-
|
377 |
-
fvm_update_transient_keys($tkey); # keep track
|
378 |
$log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
|
379 |
return array('log'=>$log, 'code'=>$code);
|
380 |
}
|
@@ -388,8 +490,7 @@ $code = fastvelocity_download($hurl, $tkey, $ttl);
|
|
388 |
if($code !== false) {
|
389 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
|
390 |
else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
|
391 |
-
|
392 |
-
fvm_update_transient_keys($tkey); # keep track
|
393 |
$log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
|
394 |
return array('log'=>$log, 'code'=>$code);
|
395 |
}
|
@@ -402,8 +503,7 @@ if(stripos($hurl, $wp_domain) !== false && home_url() != site_url()) {
|
|
402 |
if($code !== false) {
|
403 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
|
404 |
else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
|
405 |
-
|
406 |
-
fvm_update_transient_keys($tkey); # keep track
|
407 |
$log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
|
408 |
return array('log'=>$log, 'code'=>$code);
|
409 |
}
|
@@ -418,8 +518,7 @@ if (stripos($hurl, $wp_domain) !== false) {
|
|
418 |
if (file_exists($f)) {
|
419 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
|
420 |
else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
|
421 |
-
|
422 |
-
fvm_update_transient_keys($tkey); # keep track
|
423 |
$log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
|
424 |
return array('log'=>$log, 'code'=>$code);
|
425 |
}
|
@@ -431,8 +530,7 @@ if (stripos($hurl, $wp_domain) !== false) {
|
|
431 |
if (file_exists($f)) {
|
432 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
|
433 |
else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
|
434 |
-
|
435 |
-
fvm_update_transient_keys($tkey); # keep track
|
436 |
$log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
|
437 |
return array('log'=>$log, 'code'=>$code);
|
438 |
}
|
@@ -643,27 +741,11 @@ function fvm_get_protocol($url) {
|
|
643 |
return $url;
|
644 |
}
|
645 |
|
646 |
-
# keep track of transients, whenever we save a transient.
|
647 |
-
function fvm_update_transient_keys($new_transient_key) {
|
648 |
-
$transient_keys = get_option('fvm_transient_keys'); # get
|
649 |
-
$transient_keys[]= $new_transient_key; # append
|
650 |
-
update_option( 'fvm_transient_keys', $transient_keys); # save
|
651 |
-
}
|
652 |
-
|
653 |
-
# keep track of transients, dump our plugin transients as needed
|
654 |
-
function fvm_transients_purge() {
|
655 |
-
update_option('fvm-last-cache-update', time()); # last cache update to now
|
656 |
-
$transient_keys = get_option( 'fvm_transient_keys' ); # get
|
657 |
-
update_option( 'fvm_transient_keys', array()); # reset
|
658 |
-
foreach( $transient_keys as $t ) { delete_transient( $t ); } # delete
|
659 |
-
}
|
660 |
|
661 |
|
662 |
# purge all caches
|
663 |
function fvm_purge_all() {
|
664 |
|
665 |
-
|
666 |
-
|
667 |
# get cache directories and urls
|
668 |
$cachepath = fvm_cachepath();
|
669 |
$tmpdir = $cachepath['tmpdir'];
|
@@ -671,9 +753,8 @@ $cachedir = $cachepath['cachedir'];
|
|
671 |
$cachedirurl = $cachepath['cachedirurl'];
|
672 |
|
673 |
# delete minification files and transients
|
674 |
-
if(
|
675 |
-
fastvelocity_rrmdir($
|
676 |
-
fvm_transients_purge();
|
677 |
|
678 |
return true;
|
679 |
}
|
@@ -750,22 +831,21 @@ function fastvelocity_ie_blacklist($url) {
|
|
750 |
function fastvelocity_download($url, $tkey, $ttl) {
|
751 |
|
752 |
# rate limit requests, prevent slowdowns
|
753 |
-
$rtlim = false; $rtlim =
|
754 |
if ( $rtlim !== false) { return false; }
|
755 |
|
756 |
# info (needed for google fonts woff files + hinted fonts)
|
757 |
$uagent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586';
|
758 |
-
$data = false; $data =
|
759 |
if ( $data === false) {
|
760 |
|
761 |
-
# get
|
762 |
$response = wp_remote_get($url, array('user-agent'=>$uagent, 'timeout' => 7, 'httpversion' => '1.1', 'sslverify'=>false));
|
763 |
$res_code = wp_remote_retrieve_response_code($response);
|
764 |
if($res_code == '200') {
|
765 |
$data = wp_remote_retrieve_body($response);
|
766 |
if(strlen($data) > 1 && $ttl > 0) {
|
767 |
-
|
768 |
-
fvm_update_transient_keys($tkey); # keep track
|
769 |
return $data;
|
770 |
}
|
771 |
}
|
@@ -774,14 +854,13 @@ function fastvelocity_download($url, $tkey, $ttl) {
|
|
774 |
if(function_exists('curl_version')) {
|
775 |
$curl = fvm_file_get_contents_curl($url, $uagent);
|
776 |
if(!empty($curl) && strlen($curl) > 1 && $ttl > 0) {
|
777 |
-
|
778 |
-
fvm_update_transient_keys($tkey); # keep track
|
779 |
return $data;
|
780 |
}
|
781 |
}
|
782 |
|
783 |
# error
|
784 |
-
|
785 |
return false;
|
786 |
}
|
787 |
|
3 |
# handle better utf-8 and unicode encoding
|
4 |
if(function_exists('mb_internal_encoding')) { mb_internal_encoding('UTF-8'); }
|
5 |
|
6 |
+
# minification libraries
|
7 |
+
require_once ($plugindir . 'libs/JSMin/jsmin.php');
|
8 |
+
require_once ($plugindir . 'libs/CSSTidy/class.csstidy.php');
|
9 |
+
|
10 |
+
|
11 |
+
# html minification function from https://wordpress.org/plugins/minify-html-markup/
|
12 |
+
function fvm_minify_html_output($buffer) {
|
13 |
+
if ( substr( ltrim( $buffer ), 0, 5) == '<?xml' ) {
|
14 |
+
return ($buffer);
|
15 |
+
}
|
16 |
+
|
17 |
+
# defaults
|
18 |
+
$minify_html_comments = get_option('fastvelocity_min_strip_htmlcomments', 'no');
|
19 |
+
$minify_javascript = 'yes';
|
20 |
+
$minify_html_utf8 = 'yes';
|
21 |
+
$minify_html_xhtml = 'no';
|
22 |
+
$minify_html_relative = 'no';
|
23 |
+
$minify_html_scheme = 'yes';
|
24 |
+
|
25 |
+
# utf8 or not?
|
26 |
+
if ( $minify_html_utf8 == 'yes' && mb_detect_encoding($buffer, 'UTF-8', true) ) {
|
27 |
+
$mod = '/u';
|
28 |
+
} else {
|
29 |
+
$mod = '/s';
|
30 |
+
}
|
31 |
+
|
32 |
+
|
33 |
+
$buffer = str_replace(array (chr(13) . chr(10), chr(9)), array (chr(10), ''), $buffer);
|
34 |
+
$buffer = str_ireplace(array ('<script', '/script>', '<pre', '/pre>', '<textarea', '/textarea>', '<style', '/style>'), array ('M1N1FY-ST4RT<script', '/script>M1N1FY-3ND', 'M1N1FY-ST4RT<pre', '/pre>M1N1FY-3ND', 'M1N1FY-ST4RT<textarea', '/textarea>M1N1FY-3ND', 'M1N1FY-ST4RT<style', '/style>M1N1FY-3ND'), $buffer);
|
35 |
+
$split = explode('M1N1FY-3ND', $buffer);
|
36 |
+
$buffer = '';
|
37 |
+
for ($i=0; $i<count($split); $i++) {
|
38 |
+
$ii = strpos($split[$i], 'M1N1FY-ST4RT');
|
39 |
+
if ($ii !== false) {
|
40 |
+
$process = substr($split[$i], 0, $ii);
|
41 |
+
$asis = substr($split[$i], $ii + 12);
|
42 |
+
if (substr($asis, 0, 7) == '<script') {
|
43 |
+
$split2 = explode(chr(10), $asis);
|
44 |
+
$asis = '';
|
45 |
+
for ($iii = 0; $iii < count($split2); $iii ++) {
|
46 |
+
if ($split2[$iii])
|
47 |
+
$asis .= trim($split2[$iii]) . chr(10);
|
48 |
+
if ( $minify_javascript != 'no' )
|
49 |
+
if (strpos($split2[$iii], '//') !== false && substr(trim($split2[$iii]), -1) == ';' )
|
50 |
+
$asis .= chr(10);
|
51 |
+
}
|
52 |
+
if ($asis)
|
53 |
+
$asis = substr($asis, 0, -1);
|
54 |
+
if ( $minify_html_comments != 'no' )
|
55 |
+
$asis = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $asis);
|
56 |
+
if ( $minify_javascript != 'no' )
|
57 |
+
$asis = str_replace(array (';' . chr(10), '>' . chr(10), '{' . chr(10), '}' . chr(10), ',' . chr(10)), array(';', '>', '{', '}', ','), $asis);
|
58 |
+
} else if (substr($asis, 0, 6) == '<style') {
|
59 |
+
$asis = preg_replace(array ('/\>[^\S ]+' . $mod, '/[^\S ]+\<' . $mod, '/(\s)+' . $mod), array('>', '<', '\\1'), $asis);
|
60 |
+
if ( $minify_html_comments != 'no' )
|
61 |
+
$asis = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $asis);
|
62 |
+
$asis = str_replace(array (chr(10), ' {', '{ ', ' }', '} ', '( ', ' )', ' :', ': ', ' ;', '; ', ' ,', ', ', ';}'), array('', '{', '{', '}', '}', '(', ')', ':', ':', ';', ';', ',', ',', '}'), $asis);
|
63 |
+
}
|
64 |
+
} else {
|
65 |
+
$process = $split[$i];
|
66 |
+
$asis = '';
|
67 |
+
}
|
68 |
+
$process = preg_replace(array ('/\>[^\S ]+' . $mod, '/[^\S ]+\<' . $mod, '/(\s)+' . $mod), array('>', '<', '\\1'), $process);
|
69 |
+
if ( $minify_html_comments != 'no' )
|
70 |
+
$process = preg_replace('/<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->).)*-->' . $mod, '', $process);
|
71 |
+
$buffer .= $process.$asis;
|
72 |
+
}
|
73 |
+
|
74 |
+
$buffer = str_replace(array (chr(10) . '<script', chr(10) . '<style', '*/' . chr(10), 'M1N1FY-ST4RT'), array('<script', '<style', '*/', ''), $buffer);
|
75 |
+
|
76 |
+
# extra
|
77 |
+
if ( $minify_html_xhtml == 'yes' && strtolower( substr( ltrim( $buffer ), 0, 15 ) ) == '<!doctype html>' )
|
78 |
+
$buffer = str_replace( ' />', '>', $buffer );
|
79 |
+
if ( $minify_html_relative == 'yes' )
|
80 |
+
$buffer = str_replace( array ( 'https://' . $_SERVER['HTTP_HOST'] . '/', 'http://' . $_SERVER['HTTP_HOST'] . '/', '//' . $_SERVER['HTTP_HOST'] . '/' ), array( '/', '/', '/' ), $buffer );
|
81 |
+
if ( $minify_html_scheme == 'yes' )
|
82 |
+
$buffer = str_replace( array( 'http://', 'https://' ), '//', $buffer );
|
83 |
+
return ($buffer);
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
# transients on the disk
|
88 |
+
function fvm_get_transient($key, $ttl=NULL) {
|
89 |
+
|
90 |
+
$cachepath = fvm_cachepath();
|
91 |
+
$tmpdir = $cachepath['tmpdir'];
|
92 |
+
clearstatcache();
|
93 |
+
if(file_exists($tmpdir.'/'.$key)) {
|
94 |
+
|
95 |
+
# expired?
|
96 |
+
if(!is_null($ttl) && filemtime($tmpdir.'/'.$key) < time()-$ttl) {
|
97 |
+
@unlink($tmpdir.'/'.$key);
|
98 |
+
return false;
|
99 |
+
}
|
100 |
+
|
101 |
+
# return
|
102 |
+
return file_get_contents($tmpdir.'/'.$key);
|
103 |
+
} else {
|
104 |
+
return false;
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
function fvm_set_transient($key, $code) {
|
109 |
+
if(is_null($code) || empty($code)) { return false; }
|
110 |
+
$cachepath = fvm_cachepath();
|
111 |
+
$tmpdir = $cachepath['tmpdir'];
|
112 |
+
clearstatcache();
|
113 |
+
if(!file_exists($tmpdir.'/'.$key) || (file_exists($tmpdir.'/'.$key) && filesize($tmpdir.'/'.$key) == 0)) {
|
114 |
+
file_put_contents($tmpdir.'/'.$key, $code);
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
|
119 |
|
120 |
# get cache directories and urls
|
121 |
function fvm_cachepath() {
|
231 |
foreach ($ignore as $i) {
|
232 |
$i = str_ireplace(array('http://', 'https://'), '//', $i); # better compatibility
|
233 |
$i = strtok(urldecode(rawurldecode($i)), '?'); # no query string, decode entities
|
234 |
+
$i = trim(trim(trim(rtrim($i, '/')), '*')); # wildcard char removal
|
235 |
if (stripos($hurl, $i) !== false) { return true; }
|
236 |
}
|
237 |
}
|
247 |
}
|
248 |
|
249 |
|
250 |
+
# minify css string with CSSTidy http://manpages.ubuntu.com/manpages/xenial/man1/csstidy.1.html
|
251 |
function fastvelocity_min_minify_css_string($css) {
|
252 |
+
$tidy = new csstidy();
|
253 |
+
$tidy->set_cfg('preserve_css',true);
|
254 |
+
$tidy->set_cfg('merge_selectors', 1);
|
255 |
+
$tidy->set_cfg('template', 'highest');
|
256 |
+
$tidy->parse($css);
|
257 |
+
$min = $tidy->print->plain();
|
258 |
+
if($min !== false) {
|
259 |
+
return fvm_compat_urls($min);
|
260 |
+
}
|
261 |
+
|
262 |
+
# fallback
|
263 |
return fvm_compat_urls($css);
|
264 |
}
|
265 |
|
296 |
}
|
297 |
|
298 |
# needed when merging js files
|
299 |
+
$js = trim($js); if(!empty($js) && substr($js, 0, 1) != ';') { $js = ';'.$js; }
|
300 |
|
301 |
# return html
|
302 |
return $js;
|
329 |
}
|
330 |
}
|
331 |
|
332 |
+
|
333 |
+
# JSMin https://github.com/rgrove/jsmin-php
|
334 |
+
$min = JSMin::minify($js);
|
335 |
if($min !== false && (strlen(trim($js)) == strlen(trim($min)) || strlen(trim($min)) > 0)) { return fvm_compat_urls($min); }
|
336 |
|
337 |
# if we are here, something went wrong and minification didn't work
|
341 |
|
342 |
# functions, minify html
|
343 |
function fastvelocity_min_minify_html($html) {
|
344 |
+
return fvm_minify_html_output($html);
|
345 |
}
|
346 |
|
347 |
# functions to minify HTML
|
348 |
function fastvelocity_min_html_compression_finish($html) { return fastvelocity_min_minify_html($html); }
|
349 |
function fastvelocity_min_html_compression_start() {
|
350 |
+
if (fastvelocity_exclude_contents() == true) { return; }
|
351 |
+
$use_alt_html_minification = get_option('fastvelocity_min_use_alt_html_minification', '0');
|
352 |
+
if($use_alt_html_minification == '1') { ob_start('fastvelocity_min_minify_alt_html'); }
|
353 |
+
else { ob_start('fastvelocity_min_html_compression_finish'); }
|
354 |
}
|
355 |
|
356 |
# alternative html minification, minimal
|
366 |
function fastvelocity_rrmdir($dir) {
|
367 |
if(is_dir(rtrim($dir, '/'))) {
|
368 |
if ($handle = opendir($dir.'/')) {
|
369 |
+
while (false !== ($file = readdir($handle))) {
|
370 |
+
if ($file == '.' || $file == '..') { continue; }
|
371 |
+
if(is_file($dir.'/'.$file)) { @unlink($dir.'/'.$file); }
|
372 |
+
}
|
373 |
closedir($handle); }
|
374 |
}
|
375 |
}
|
376 |
|
377 |
|
|
|
|
|
378 |
# return size in human format
|
379 |
function fastvelocity_format_filesize($bytes, $decimals = 2) {
|
380 |
$units = array( 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' );
|
464 |
if (file_exists($f)) {
|
465 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
|
466 |
else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
|
467 |
+
fvm_set_transient($tkey, $code);
|
|
|
468 |
$log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
|
469 |
return array('log'=>$log, 'code'=>$code);
|
470 |
}
|
476 |
if (file_exists($f)) {
|
477 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
|
478 |
else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
|
479 |
+
fvm_set_transient($tkey, $code);
|
|
|
480 |
$log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
|
481 |
return array('log'=>$log, 'code'=>$code);
|
482 |
}
|
490 |
if($code !== false) {
|
491 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
|
492 |
else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
|
493 |
+
fvm_set_transient($tkey, $code);
|
|
|
494 |
$log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
|
495 |
return array('log'=>$log, 'code'=>$code);
|
496 |
}
|
503 |
if($code !== false) {
|
504 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
|
505 |
else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
|
506 |
+
fvm_set_transient($tkey, $code);
|
|
|
507 |
$log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
|
508 |
return array('log'=>$log, 'code'=>$code);
|
509 |
}
|
518 |
if (file_exists($f)) {
|
519 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
|
520 |
else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
|
521 |
+
fvm_set_transient($tkey, $code);
|
|
|
522 |
$log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
|
523 |
return array('log'=>$log, 'code'=>$code);
|
524 |
}
|
530 |
if (file_exists($f)) {
|
531 |
if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
|
532 |
else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
|
533 |
+
fvm_set_transient($tkey, $code);
|
|
|
534 |
$log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
|
535 |
return array('log'=>$log, 'code'=>$code);
|
536 |
}
|
741 |
return $url;
|
742 |
}
|
743 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
744 |
|
745 |
|
746 |
# purge all caches
|
747 |
function fvm_purge_all() {
|
748 |
|
|
|
|
|
749 |
# get cache directories and urls
|
750 |
$cachepath = fvm_cachepath();
|
751 |
$tmpdir = $cachepath['tmpdir'];
|
753 |
$cachedirurl = $cachepath['cachedirurl'];
|
754 |
|
755 |
# delete minification files and transients
|
756 |
+
if(is_dir($cachedir)) { fastvelocity_rrmdir($cachedir); }
|
757 |
+
if(is_dir($tmpdir)) { fastvelocity_rrmdir($tmpdir); }
|
|
|
758 |
|
759 |
return true;
|
760 |
}
|
831 |
function fastvelocity_download($url, $tkey, $ttl) {
|
832 |
|
833 |
# rate limit requests, prevent slowdowns
|
834 |
+
$rtlim = false; $rtlim = fvm_get_transient($tkey.'_access', $ttl);
|
835 |
if ( $rtlim !== false) { return false; }
|
836 |
|
837 |
# info (needed for google fonts woff files + hinted fonts)
|
838 |
$uagent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586';
|
839 |
+
$data = false; $data = fvm_get_transient($tkey, $ttl);
|
840 |
if ( $data === false) {
|
841 |
|
842 |
+
# get contents and cache for the ttl time
|
843 |
$response = wp_remote_get($url, array('user-agent'=>$uagent, 'timeout' => 7, 'httpversion' => '1.1', 'sslverify'=>false));
|
844 |
$res_code = wp_remote_retrieve_response_code($response);
|
845 |
if($res_code == '200') {
|
846 |
$data = wp_remote_retrieve_body($response);
|
847 |
if(strlen($data) > 1 && $ttl > 0) {
|
848 |
+
fvm_set_transient($tkey, $data);
|
|
|
849 |
return $data;
|
850 |
}
|
851 |
}
|
854 |
if(function_exists('curl_version')) {
|
855 |
$curl = fvm_file_get_contents_curl($url, $uagent);
|
856 |
if(!empty($curl) && strlen($curl) > 1 && $ttl > 0) {
|
857 |
+
fvm_set_transient($tkey, $curl);
|
|
|
858 |
return $data;
|
859 |
}
|
860 |
}
|
861 |
|
862 |
# error
|
863 |
+
fvm_set_transient($tkey, '_access', "Failed to fetch: $url on ".current_time('timestamp'));
|
864 |
return false;
|
865 |
}
|
866 |
|
libs/CSSTidy/class.csstidy.php
ADDED
@@ -0,0 +1,1296 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* CSSTidy - CSS Parser and Optimiser
|
5 |
+
*
|
6 |
+
* CSS Parser class
|
7 |
+
*
|
8 |
+
* Copyright 2005, 2006, 2007 Florian Schmitz
|
9 |
+
*
|
10 |
+
* This file is part of CSSTidy.
|
11 |
+
*
|
12 |
+
* CSSTidy is free software; you can redistribute it and/or modify
|
13 |
+
* it under the terms of the GNU Lesser General Public License as published by
|
14 |
+
* the Free Software Foundation; either version 2.1 of the License, or
|
15 |
+
* (at your option) any later version.
|
16 |
+
*
|
17 |
+
* CSSTidy is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU Lesser General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU Lesser General Public License
|
23 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*
|
25 |
+
* @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
|
26 |
+
* @package csstidy
|
27 |
+
* @author Florian Schmitz (floele at gmail dot com) 2005-2007
|
28 |
+
* @author Brett Zamir (brettz9 at yahoo dot com) 2007
|
29 |
+
* @author Nikolay Matsievsky (speed at webo dot name) 2009-2010
|
30 |
+
* @author Cedric Morin (cedric at yterium dot com) 2010-2012
|
31 |
+
* @author Christopher Finke (cfinke at gmail.com) 2012
|
32 |
+
* @author Mark Scherer (remove $GLOBALS once and for all + PHP5.4 comp) 2012
|
33 |
+
*/
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Defines ctype functions if required.
|
37 |
+
*
|
38 |
+
* @TODO: Make these methods of CSSTidy.
|
39 |
+
* @since 1.0.0
|
40 |
+
*/
|
41 |
+
if (!function_exists('ctype_space')){
|
42 |
+
/* ctype_space Check for whitespace character(s) */
|
43 |
+
function ctype_space($text){
|
44 |
+
return (1===preg_match("/^[ \r\n\t\f]+$/", $text));
|
45 |
+
}
|
46 |
+
}
|
47 |
+
if (!function_exists('ctype_alpha')){
|
48 |
+
/* ctype_alpha Check for alphabetic character(s) */
|
49 |
+
function ctype_alpha($text){
|
50 |
+
return (1===preg_match('/^[a-zA-Z]+$/', $text));
|
51 |
+
}
|
52 |
+
}
|
53 |
+
if (!function_exists('ctype_xdigit')){
|
54 |
+
/* ctype_xdigit Check for HEX character(s) */
|
55 |
+
function ctype_xdigit($text){
|
56 |
+
return (1===preg_match('/^[a-fA-F0-9]+$/', $text));
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Defines constants
|
62 |
+
* @todo //TODO: make them class constants of csstidy
|
63 |
+
*/
|
64 |
+
define('AT_START', 1);
|
65 |
+
define('AT_END', 2);
|
66 |
+
define('SEL_START', 3);
|
67 |
+
define('SEL_END', 4);
|
68 |
+
define('PROPERTY', 5);
|
69 |
+
define('VALUE', 6);
|
70 |
+
define('COMMENT', 7);
|
71 |
+
define('DEFAULT_AT', 41);
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Contains a class for printing CSS code
|
75 |
+
*
|
76 |
+
* @version 1.0
|
77 |
+
*/
|
78 |
+
require('class.csstidy_print.php');
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Contains a class for optimising CSS code
|
82 |
+
*
|
83 |
+
* @version 1.0
|
84 |
+
*/
|
85 |
+
require('class.csstidy_optimise.php');
|
86 |
+
|
87 |
+
/**
|
88 |
+
* CSS Parser class
|
89 |
+
*
|
90 |
+
* This class represents a CSS parser which reads CSS code and saves it in an array.
|
91 |
+
* In opposite to most other CSS parsers, it does not use regular expressions and
|
92 |
+
* thus has full CSS2 support and a higher reliability.
|
93 |
+
* Additional to that it applies some optimisations and fixes to the CSS code.
|
94 |
+
* An online version should be available here: http://cdburnerxp.se/cssparse/css_optimiser.php
|
95 |
+
* @package csstidy
|
96 |
+
* @author Florian Schmitz (floele at gmail dot com) 2005-2006
|
97 |
+
* @version 1.5.6
|
98 |
+
*/
|
99 |
+
class csstidy {
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Saves the parsed CSS. This array is empty if preserve_css is on.
|
103 |
+
* @var array
|
104 |
+
* @access public
|
105 |
+
*/
|
106 |
+
public $css = array();
|
107 |
+
/**
|
108 |
+
* Saves the parsed CSS (raw)
|
109 |
+
* @var array
|
110 |
+
* @access private
|
111 |
+
*/
|
112 |
+
public $tokens = array();
|
113 |
+
/**
|
114 |
+
* Printer class
|
115 |
+
* @see csstidy_print
|
116 |
+
* @var object
|
117 |
+
* @access public
|
118 |
+
*/
|
119 |
+
public $print;
|
120 |
+
/**
|
121 |
+
* Optimiser class
|
122 |
+
* @see csstidy_optimise
|
123 |
+
* @var object
|
124 |
+
* @access private
|
125 |
+
*/
|
126 |
+
public $optimise;
|
127 |
+
/**
|
128 |
+
* Saves the CSS charset (@charset)
|
129 |
+
* @var string
|
130 |
+
* @access private
|
131 |
+
*/
|
132 |
+
public $charset = '';
|
133 |
+
/**
|
134 |
+
* Saves all @import URLs
|
135 |
+
* @var array
|
136 |
+
* @access private
|
137 |
+
*/
|
138 |
+
public $import = array();
|
139 |
+
/**
|
140 |
+
* Saves the namespace
|
141 |
+
* @var string
|
142 |
+
* @access private
|
143 |
+
*/
|
144 |
+
public $namespace = '';
|
145 |
+
/**
|
146 |
+
* Contains the version of csstidy
|
147 |
+
* @var string
|
148 |
+
* @access private
|
149 |
+
*/
|
150 |
+
public $version = '1.5.6';
|
151 |
+
/**
|
152 |
+
* Stores the settings
|
153 |
+
* @var array
|
154 |
+
* @access private
|
155 |
+
*/
|
156 |
+
public $settings = array();
|
157 |
+
/**
|
158 |
+
* Saves the parser-status.
|
159 |
+
*
|
160 |
+
* Possible values:
|
161 |
+
* - is = in selector
|
162 |
+
* - ip = in property
|
163 |
+
* - iv = in value
|
164 |
+
* - instr = in string (started at " or ' or ( )
|
165 |
+
* - ic = in comment (ignore everything)
|
166 |
+
* - at = in @-block
|
167 |
+
*
|
168 |
+
* @var string
|
169 |
+
* @access private
|
170 |
+
*/
|
171 |
+
public $status = 'is';
|
172 |
+
/**
|
173 |
+
* Saves the current at rule (@media)
|
174 |
+
* @var string
|
175 |
+
* @access private
|
176 |
+
*/
|
177 |
+
public $at = '';
|
178 |
+
/**
|
179 |
+
* Saves the at rule for next selector (during @font-face or other @)
|
180 |
+
* @var string
|
181 |
+
* @access private
|
182 |
+
*/
|
183 |
+
public $next_selector_at = '';
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Saves the current selector
|
187 |
+
* @var string
|
188 |
+
* @access private
|
189 |
+
*/
|
190 |
+
public $selector = '';
|
191 |
+
/**
|
192 |
+
* Saves the current property
|
193 |
+
* @var string
|
194 |
+
* @access private
|
195 |
+
*/
|
196 |
+
public $property = '';
|
197 |
+
/**
|
198 |
+
* Saves the position of , in selectors
|
199 |
+
* @var array
|
200 |
+
* @access private
|
201 |
+
*/
|
202 |
+
public $sel_separate = array();
|
203 |
+
/**
|
204 |
+
* Saves the current value
|
205 |
+
* @var string
|
206 |
+
* @access private
|
207 |
+
*/
|
208 |
+
public $value = '';
|
209 |
+
/**
|
210 |
+
* Saves the current sub-value
|
211 |
+
*
|
212 |
+
* Example for a subvalue:
|
213 |
+
* background:url(foo.png) red no-repeat;
|
214 |
+
* "url(foo.png)", "red", and "no-repeat" are subvalues,
|
215 |
+
* seperated by whitespace
|
216 |
+
* @var string
|
217 |
+
* @access private
|
218 |
+
*/
|
219 |
+
public $sub_value = '';
|
220 |
+
/**
|
221 |
+
* Array which saves all subvalues for a property.
|
222 |
+
* @var array
|
223 |
+
* @see sub_value
|
224 |
+
* @access private
|
225 |
+
*/
|
226 |
+
public $sub_value_arr = array();
|
227 |
+
/**
|
228 |
+
* Saves the stack of characters that opened the current strings
|
229 |
+
* @var array
|
230 |
+
* @access private
|
231 |
+
*/
|
232 |
+
public $str_char = array();
|
233 |
+
public $cur_string = array();
|
234 |
+
/**
|
235 |
+
* Status from which the parser switched to ic or instr
|
236 |
+
* @var array
|
237 |
+
* @access private
|
238 |
+
*/
|
239 |
+
public $from = array();
|
240 |
+
/**
|
241 |
+
/**
|
242 |
+
* =true if in invalid at-rule
|
243 |
+
* @var bool
|
244 |
+
* @access private
|
245 |
+
*/
|
246 |
+
public $invalid_at = false;
|
247 |
+
/**
|
248 |
+
* =true if something has been added to the current selector
|
249 |
+
* @var bool
|
250 |
+
* @access private
|
251 |
+
*/
|
252 |
+
public $added = false;
|
253 |
+
/**
|
254 |
+
* Array which saves the message log
|
255 |
+
* @var array
|
256 |
+
* @access private
|
257 |
+
*/
|
258 |
+
public $log = array();
|
259 |
+
/**
|
260 |
+
* Saves the line number
|
261 |
+
* @var integer
|
262 |
+
* @access private
|
263 |
+
*/
|
264 |
+
public $line = 1;
|
265 |
+
/**
|
266 |
+
* Marks if we need to leave quotes for a string
|
267 |
+
* @var array
|
268 |
+
* @access private
|
269 |
+
*/
|
270 |
+
public $quoted_string = array();
|
271 |
+
|
272 |
+
/**
|
273 |
+
* List of tokens
|
274 |
+
* @var string
|
275 |
+
*/
|
276 |
+
public $tokens_list = "";
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Various CSS Data for CSSTidy
|
280 |
+
* @var array
|
281 |
+
*/
|
282 |
+
public $data = array();
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Loads standard template and sets default settings
|
286 |
+
* @access private
|
287 |
+
* @version 1.3
|
288 |
+
*/
|
289 |
+
public function __construct() {
|
290 |
+
$data = array();
|
291 |
+
include('data.inc.php');
|
292 |
+
$this->data = $data;
|
293 |
+
|
294 |
+
$this->settings['remove_bslash'] = true;
|
295 |
+
$this->settings['compress_colors'] = true;
|
296 |
+
$this->settings['compress_font-weight'] = true;
|
297 |
+
$this->settings['lowercase_s'] = false;
|
298 |
+
/*
|
299 |
+
1 common shorthands optimization
|
300 |
+
2 + font property optimization
|
301 |
+
3 + background property optimization
|
302 |
+
*/
|
303 |
+
$this->settings['optimise_shorthands'] = 1;
|
304 |
+
$this->settings['remove_last_;'] = true;
|
305 |
+
$this->settings['space_before_important'] = false;
|
306 |
+
/* rewrite all properties with low case, better for later gzip OK, safe*/
|
307 |
+
$this->settings['case_properties'] = 1;
|
308 |
+
/* sort properties in alpabetic order, better for later gzip
|
309 |
+
* but can cause trouble in case of overiding same propertie or using hack
|
310 |
+
*/
|
311 |
+
$this->settings['sort_properties'] = false;
|
312 |
+
/*
|
313 |
+
1, 3, 5, etc -- enable sorting selectors inside @media: a{}b{}c{}
|
314 |
+
2, 5, 8, etc -- enable sorting selectors inside one CSS declaration: a,b,c{}
|
315 |
+
preserve order by default cause it can break functionnality
|
316 |
+
*/
|
317 |
+
$this->settings['sort_selectors'] = 0;
|
318 |
+
/* is dangeroues to be used: CSS is broken sometimes */
|
319 |
+
$this->settings['merge_selectors'] = 0;
|
320 |
+
/* preserve or not browser hacks */
|
321 |
+
$this->settings['discard_invalid_selectors'] = false;
|
322 |
+
$this->settings['discard_invalid_properties'] = false;
|
323 |
+
$this->settings['css_level'] = 'CSS3.0';
|
324 |
+
$this->settings['preserve_css'] = false;
|
325 |
+
$this->settings['timestamp'] = false;
|
326 |
+
$this->settings['template'] = ''; // say that propertie exist
|
327 |
+
$this->set_cfg('template','default'); // call load_template
|
328 |
+
$this->optimise = new csstidy_optimise($this);
|
329 |
+
|
330 |
+
$this->tokens_list = & $this->data['csstidy']['tokens'];
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Get the value of a setting.
|
335 |
+
* @param string $setting
|
336 |
+
* @access public
|
337 |
+
* @return mixed
|
338 |
+
* @version 1.0
|
339 |
+
*/
|
340 |
+
public function get_cfg($setting) {
|
341 |
+
if (isset($this->settings[$setting])) {
|
342 |
+
return $this->settings[$setting];
|
343 |
+
}
|
344 |
+
return false;
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Load a template
|
349 |
+
* @param string $template used by set_cfg to load a template via a configuration setting
|
350 |
+
* @access private
|
351 |
+
* @version 1.4
|
352 |
+
*/
|
353 |
+
public function _load_template($template) {
|
354 |
+
switch ($template) {
|
355 |
+
case 'default':
|
356 |
+
$this->load_template('default');
|
357 |
+
break;
|
358 |
+
|
359 |
+
case 'highest':
|
360 |
+
$this->load_template('highest_compression');
|
361 |
+
break;
|
362 |
+
|
363 |
+
case 'high':
|
364 |
+
$this->load_template('high_compression');
|
365 |
+
break;
|
366 |
+
|
367 |
+
case 'low':
|
368 |
+
$this->load_template('low_compression');
|
369 |
+
break;
|
370 |
+
|
371 |
+
default:
|
372 |
+
$this->load_template($template);
|
373 |
+
break;
|
374 |
+
}
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* Set the value of a setting.
|
379 |
+
* @param string $setting
|
380 |
+
* @param mixed $value
|
381 |
+
* @access public
|
382 |
+
* @return bool
|
383 |
+
* @version 1.0
|
384 |
+
*/
|
385 |
+
public function set_cfg($setting, $value=null) {
|
386 |
+
if (is_array($setting) && $value === null) {
|
387 |
+
foreach ($setting as $setprop => $setval) {
|
388 |
+
$this->settings[$setprop] = $setval;
|
389 |
+
}
|
390 |
+
if (array_key_exists('template', $setting)) {
|
391 |
+
$this->_load_template($this->settings['template']);
|
392 |
+
}
|
393 |
+
return true;
|
394 |
+
} elseif (isset($this->settings[$setting]) && $value !== '') {
|
395 |
+
$this->settings[$setting] = $value;
|
396 |
+
if ($setting === 'template') {
|
397 |
+
$this->_load_template($this->settings['template']);
|
398 |
+
}
|
399 |
+
return true;
|
400 |
+
}
|
401 |
+
return false;
|
402 |
+
}
|
403 |
+
|
404 |
+
/**
|
405 |
+
* Adds a token to $this->tokens
|
406 |
+
* @param mixed $type
|
407 |
+
* @param string $data
|
408 |
+
* @param bool $do add a token even if preserve_css is off
|
409 |
+
* @access private
|
410 |
+
* @version 1.0
|
411 |
+
*/
|
412 |
+
public function _add_token($type, $data, $do = false) {
|
413 |
+
if ($this->get_cfg('preserve_css') || $do) {
|
414 |
+
$this->tokens[] = array($type, ($type == COMMENT) ? $data : trim($data));
|
415 |
+
}
|
416 |
+
}
|
417 |
+
|
418 |
+
/**
|
419 |
+
* Add a message to the message log
|
420 |
+
* @param string $message
|
421 |
+
* @param string $type
|
422 |
+
* @param integer $line
|
423 |
+
* @access private
|
424 |
+
* @version 1.0
|
425 |
+
*/
|
426 |
+
public function log($message, $type, $line = -1) {
|
427 |
+
if ($line === -1) {
|
428 |
+
$line = $this->line;
|
429 |
+
}
|
430 |
+
$line = intval($line);
|
431 |
+
$add = array('m' => $message, 't' => $type);
|
432 |
+
if (!isset($this->log[$line]) || !in_array($add, $this->log[$line])) {
|
433 |
+
$this->log[$line][] = $add;
|
434 |
+
}
|
435 |
+
}
|
436 |
+
|
437 |
+
/**
|
438 |
+
* Parse unicode notations and find a replacement character
|
439 |
+
* @param string $string
|
440 |
+
* @param integer $i
|
441 |
+
* @access private
|
442 |
+
* @return string
|
443 |
+
* @version 1.2
|
444 |
+
*/
|
445 |
+
public function _unicode(&$string, &$i) {
|
446 |
+
++$i;
|
447 |
+
$add = '';
|
448 |
+
$replaced = false;
|
449 |
+
|
450 |
+
while ($i < strlen($string) && (ctype_xdigit($string{$i}) || ctype_space($string{$i})) && strlen($add) < 6) {
|
451 |
+
$add .= $string{$i};
|
452 |
+
|
453 |
+
if (ctype_space($string{$i})) {
|
454 |
+
break;
|
455 |
+
}
|
456 |
+
$i++;
|
457 |
+
}
|
458 |
+
|
459 |
+
if (hexdec($add) > 47 && hexdec($add) < 58 || hexdec($add) > 64 && hexdec($add) < 91 || hexdec($add) > 96 && hexdec($add) < 123) {
|
460 |
+
$this->log('Replaced unicode notation: Changed \\' . $add . ' to ' . chr(hexdec($add)), 'Information');
|
461 |
+
$add = chr(hexdec($add));
|
462 |
+
$replaced = true;
|
463 |
+
} else {
|
464 |
+
$add = trim('\\' . $add);
|
465 |
+
}
|
466 |
+
|
467 |
+
if (@ctype_xdigit($string{$i + 1}) && ctype_space($string{$i})
|
468 |
+
&& !$replaced || !ctype_space($string{$i})) {
|
469 |
+
$i--;
|
470 |
+
}
|
471 |
+
|
472 |
+
if ($add !== '\\' || !$this->get_cfg('remove_bslash') || strpos($this->tokens_list, $string{$i + 1}) !== false) {
|
473 |
+
return $add;
|
474 |
+
}
|
475 |
+
|
476 |
+
if ($add === '\\') {
|
477 |
+
$this->log('Removed unnecessary backslash', 'Information');
|
478 |
+
}
|
479 |
+
return '';
|
480 |
+
}
|
481 |
+
|
482 |
+
/**
|
483 |
+
* Write formatted output to a file
|
484 |
+
* @param string $filename
|
485 |
+
* @param string $doctype when printing formatted, is a shorthand for the document type
|
486 |
+
* @param bool $externalcss when printing formatted, indicates whether styles to be attached internally or as an external stylesheet
|
487 |
+
* @param string $title when printing formatted, is the title to be added in the head of the document
|
488 |
+
* @param string $lang when printing formatted, gives a two-letter language code to be added to the output
|
489 |
+
* @access public
|
490 |
+
* @version 1.4
|
491 |
+
*/
|
492 |
+
public function write_page($filename, $doctype='xhtml1.1', $externalcss=true, $title='', $lang='en') {
|
493 |
+
$this->write($filename, true);
|
494 |
+
}
|
495 |
+
|
496 |
+
/**
|
497 |
+
* Write plain output to a file
|
498 |
+
* @param string $filename
|
499 |
+
* @param bool $formatted whether to print formatted or not
|
500 |
+
* @param string $doctype when printing formatted, is a shorthand for the document type
|
501 |
+
* @param bool $externalcss when printing formatted, indicates whether styles to be attached internally or as an external stylesheet
|
502 |
+
* @param string $title when printing formatted, is the title to be added in the head of the document
|
503 |
+
* @param string $lang when printing formatted, gives a two-letter language code to be added to the output
|
504 |
+
* @param bool $pre_code whether to add pre and code tags around the code (for light HTML formatted templates)
|
505 |
+
* @access public
|
506 |
+
* @version 1.4
|
507 |
+
*/
|
508 |
+
public function write($filename, $formatted=false, $doctype='xhtml1.1', $externalcss=true, $title='', $lang='en', $pre_code=true) {
|
509 |
+
$filename .= ( $formatted) ? '.xhtml' : '.css';
|
510 |
+
|
511 |
+
if (!is_dir('temp')) {
|
512 |
+
$madedir = mkdir('temp');
|
513 |
+
if (!$madedir) {
|
514 |
+
print 'Could not make directory "temp" in ' . dirname(__FILE__);
|
515 |
+
exit;
|
516 |
+
}
|
517 |
+
}
|
518 |
+
$handle = fopen('temp/' . $filename, 'w');
|
519 |
+
if ($handle) {
|
520 |
+
if (!$formatted) {
|
521 |
+
fwrite($handle, $this->print->plain());
|
522 |
+
} else {
|
523 |
+
fwrite($handle, $this->print->formatted_page($doctype, $externalcss, $title, $lang, $pre_code));
|
524 |
+
}
|
525 |
+
}
|
526 |
+
fclose($handle);
|
527 |
+
}
|
528 |
+
|
529 |
+
/**
|
530 |
+
* Loads a new template
|
531 |
+
* @param string $content either filename (if $from_file == true), content of a template file, "high_compression", "highest_compression", "low_compression", or "default"
|
532 |
+
* @param bool $from_file uses $content as filename if true
|
533 |
+
* @access public
|
534 |
+
* @version 1.1
|
535 |
+
* @see http://csstidy.sourceforge.net/templates.php
|
536 |
+
*/
|
537 |
+
public function load_template($content, $from_file=true) {
|
538 |
+
$predefined_templates = & $this->data['csstidy']['predefined_templates'];
|
539 |
+
if ($content === 'high_compression' || $content === 'default' || $content === 'highest_compression' || $content === 'low_compression') {
|
540 |
+
$this->template = $predefined_templates[$content];
|
541 |
+
return;
|
542 |
+
}
|
543 |
+
|
544 |
+
|
545 |
+
if ($from_file) {
|
546 |
+
$content = strip_tags(file_get_contents($content), '<span>');
|
547 |
+
}
|
548 |
+
$content = str_replace("\r\n", "\n", $content); // Unify newlines (because the output also only uses \n)
|
549 |
+
$template = explode('|', $content);
|
550 |
+
|
551 |
+
for ($i = 0; $i < count($template); $i++) {
|
552 |
+
$this->template[$i] = $template[$i];
|
553 |
+
}
|
554 |
+
}
|
555 |
+
|
556 |
+
/**
|
557 |
+
* Starts parsing from URL
|
558 |
+
* @param string $url
|
559 |
+
* @access public
|
560 |
+
* @version 1.0
|
561 |
+
*/
|
562 |
+
public function parse_from_url($url) {
|
563 |
+
return $this->parse(@file_get_contents($url));
|
564 |
+
}
|
565 |
+
|
566 |
+
/**
|
567 |
+
* Checks if there is a token at the current position
|
568 |
+
* @param string $string
|
569 |
+
* @param integer $i
|
570 |
+
* @access public
|
571 |
+
* @version 1.11
|
572 |
+
*/
|
573 |
+
public function is_token(&$string, $i) {
|
574 |
+
return (strpos($this->tokens_list, $string{$i}) !== false && !$this->escaped($string, $i));
|
575 |
+
}
|
576 |
+
|
577 |
+
/**
|
578 |
+
* Parses CSS in $string. The code is saved as array in $this->css
|
579 |
+
* @param string $string the CSS code
|
580 |
+
* @access public
|
581 |
+
* @return bool
|
582 |
+
* @version 1.1
|
583 |
+
*/
|
584 |
+
public function parse($string) {
|
585 |
+
// Temporarily set locale to en_US in order to handle floats properly
|
586 |
+
$old = @setlocale(LC_ALL, 0);
|
587 |
+
@setlocale(LC_ALL, 'C');
|
588 |
+
|
589 |
+
// PHP bug? Settings need to be refreshed in PHP4
|
590 |
+
$this->print = new csstidy_print($this);
|
591 |
+
$this->optimise = new csstidy_optimise($this);
|
592 |
+
|
593 |
+
$all_properties = & $this->data['csstidy']['all_properties'];
|
594 |
+
$at_rules = & $this->data['csstidy']['at_rules'];
|
595 |
+
$quoted_string_properties = & $this->data['csstidy']['quoted_string_properties'];
|
596 |
+
|
597 |
+
$this->css = array();
|
598 |
+
$this->print->input_css = $string;
|
599 |
+
$string = str_replace("\r\n", "\n", $string) . ' ';
|
600 |
+
$cur_comment = '';
|
601 |
+
|
602 |
+
for ($i = 0, $size = strlen($string); $i < $size; $i++) {
|
603 |
+
if ($string{$i} === "\n" || $string{$i} === "\r") {
|
604 |
+
++$this->line;
|
605 |
+
}
|
606 |
+
|
607 |
+
switch ($this->status) {
|
608 |
+
/* Case in at-block */
|
609 |
+
case 'at':
|
610 |
+
if ($this->is_token($string, $i)) {
|
611 |
+
if ($string{$i} === '/' && @$string{$i + 1} === '*') {
|
612 |
+
$this->status = 'ic';
|
613 |
+
++$i;
|
614 |
+
$this->from[] = 'at';
|
615 |
+
} elseif ($string{$i} === '{') {
|
616 |
+
$this->status = 'is';
|
617 |
+
$this->at = $this->css_new_media_section($this->at);
|
618 |
+
$this->_add_token(AT_START, $this->at);
|
619 |
+
} elseif ($string{$i} === ',') {
|
620 |
+
$this->at = trim($this->at) . ',';
|
621 |
+
} elseif ($string{$i} === '\\') {
|
622 |
+
$this->at .= $this->_unicode($string, $i);
|
623 |
+
}
|
624 |
+
// fix for complicated media, i.e @media screen and (-webkit-min-device-pixel-ratio:1.5)
|
625 |
+
elseif (in_array($string{$i}, array('(', ')', ':', '.', '/'))) {
|
626 |
+
$this->at .= $string{$i};
|
627 |
+
}
|
628 |
+
} else {
|
629 |
+
$lastpos = strlen($this->at) - 1;
|
630 |
+
if (!( (ctype_space($this->at{$lastpos}) || $this->is_token($this->at, $lastpos) && $this->at{$lastpos} === ',') && ctype_space($string{$i}))) {
|
631 |
+
$this->at .= $string{$i};
|
632 |
+
}
|
633 |
+
}
|
634 |
+
break;
|
635 |
+
|
636 |
+
/* Case in-selector */
|
637 |
+
case 'is':
|
638 |
+
if ($this->is_token($string, $i)) {
|
639 |
+
if ($string{$i} === '/' && @$string{$i + 1} === '*' && trim($this->selector) == '') {
|
640 |
+
$this->status = 'ic';
|
641 |
+
++$i;
|
642 |
+
$this->from[] = 'is';
|
643 |
+
} elseif ($string{$i} === '@' && trim($this->selector) == '') {
|
644 |
+
// Check for at-rule
|
645 |
+
$this->invalid_at = true;
|
646 |
+
foreach ($at_rules as $name => $type) {
|
647 |
+
if (!strcasecmp(substr($string, $i + 1, strlen($name)), $name)) {
|
648 |
+
($type === 'at') ? $this->at = '@' . $name : $this->selector = '@' . $name;
|
649 |
+
if ($type === 'atis') {
|
650 |
+
$this->next_selector_at = ($this->next_selector_at?$this->next_selector_at:($this->at?$this->at:DEFAULT_AT));
|
651 |
+
$this->at = $this->css_new_media_section(' ');
|
652 |
+
$type = 'is';
|
653 |
+
}
|
654 |
+
$this->status = $type;
|
655 |
+
$i += strlen($name);
|
656 |
+
$this->invalid_at = false;
|
657 |
+
}
|
658 |
+
}
|
659 |
+
|
660 |
+
if ($this->invalid_at) {
|
661 |
+
$this->selector = '@';
|
662 |
+
$invalid_at_name = '';
|
663 |
+
for ($j = $i + 1; $j < $size; ++$j) {
|
664 |
+
if (!ctype_alpha($string{$j})) {
|
665 |
+
break;
|
666 |
+
}
|
667 |
+
$invalid_at_name .= $string{$j};
|
668 |
+
}
|
669 |
+
$this->log('Invalid @-rule: ' . $invalid_at_name . ' (removed)', 'Warning');
|
670 |
+
}
|
671 |
+
} elseif (($string{$i} === '"' || $string{$i} === "'")) {
|
672 |
+
$this->cur_string[] = $string{$i};
|
673 |
+
$this->status = 'instr';
|
674 |
+
$this->str_char[] = $string{$i};
|
675 |
+
$this->from[] = 'is';
|
676 |
+
/* fixing CSS3 attribute selectors, i.e. a[href$=".mp3" */
|
677 |
+
$this->quoted_string[] = ($string{$i - 1} === '=' );
|
678 |
+
} elseif ($this->invalid_at && $string{$i} === ';') {
|
679 |
+
$this->invalid_at = false;
|
680 |
+
$this->status = 'is';
|
681 |
+
if ($this->next_selector_at) {
|
682 |
+
$this->at = $this->css_new_media_section($this->next_selector_at);
|
683 |
+
$this->next_selector_at = '';
|
684 |
+
}
|
685 |
+
} elseif ($string{$i} === '{') {
|
686 |
+
$this->status = 'ip';
|
687 |
+
if ($this->at == '') {
|
688 |
+
$this->at = $this->css_new_media_section(DEFAULT_AT);
|
689 |
+
}
|
690 |
+
$this->selector = $this->css_new_selector($this->at,$this->selector);
|
691 |
+
$this->_add_token(SEL_START, $this->selector);
|
692 |
+
$this->added = false;
|
693 |
+
} elseif ($string{$i} === '}') {
|
694 |
+
$this->_add_token(AT_END, $this->at);
|
695 |
+
$this->at = '';
|
696 |
+
$this->selector = '';
|
697 |
+
$this->sel_separate = array();
|
698 |
+
} elseif ($string{$i} === ',') {
|
699 |
+
$this->selector = trim($this->selector) . ',';
|
700 |
+
$this->sel_separate[] = strlen($this->selector);
|
701 |
+
} elseif ($string{$i} === '\\') {
|
702 |
+
$this->selector .= $this->_unicode($string, $i);
|
703 |
+
} elseif ($string{$i} === '*' && @in_array($string{$i + 1}, array('.', '#', '[', ':')) && ($i==0 OR $string{$i - 1}!=='/')) {
|
704 |
+
// remove unnecessary universal selector, FS#147, but not comment in selector
|
705 |
+
} else {
|
706 |
+
$this->selector .= $string{$i};
|
707 |
+
}
|
708 |
+
} else {
|
709 |
+
$lastpos = strlen($this->selector) - 1;
|
710 |
+
if ($lastpos == -1 || !( (ctype_space($this->selector{$lastpos}) || $this->is_token($this->selector, $lastpos) && $this->selector{$lastpos} === ',') && ctype_space($string{$i}))) {
|
711 |
+
$this->selector .= $string{$i};
|
712 |
+
}
|
713 |
+
}
|
714 |
+
break;
|
715 |
+
|
716 |
+
/* Case in-property */
|
717 |
+
case 'ip':
|
718 |
+
if ($this->is_token($string, $i)) {
|
719 |
+
if (($string{$i} === ':' || $string{$i} === '=') && $this->property != '') {
|
720 |
+
$this->status = 'iv';
|
721 |
+
if (!$this->get_cfg('discard_invalid_properties') || $this->property_is_valid($this->property)) {
|
722 |
+
$this->property = $this->css_new_property($this->at,$this->selector,$this->property);
|
723 |
+
$this->_add_token(PROPERTY, $this->property);
|
724 |
+
}
|
725 |
+
} elseif ($string{$i} === '/' && @$string{$i + 1} === '*' && $this->property == '') {
|
726 |
+
$this->status = 'ic';
|
727 |
+
++$i;
|
728 |
+
$this->from[] = 'ip';
|
729 |
+
} elseif ($string{$i} === '}') {
|
730 |
+
$this->explode_selectors();
|
731 |
+
$this->status = 'is';
|
732 |
+
$this->invalid_at = false;
|
733 |
+
$this->_add_token(SEL_END, $this->selector);
|
734 |
+
$this->selector = '';
|
735 |
+
$this->property = '';
|
736 |
+
if ($this->next_selector_at) {
|
737 |
+
$this->at = $this->css_new_media_section($this->next_selector_at);
|
738 |
+
$this->next_selector_at = '';
|
739 |
+
}
|
740 |
+
} elseif ($string{$i} === ';') {
|
741 |
+
$this->property = '';
|
742 |
+
} elseif ($string{$i} === '\\') {
|
743 |
+
$this->property .= $this->_unicode($string, $i);
|
744 |
+
}
|
745 |
+
// else this is dumb IE a hack, keep it
|
746 |
+
// including //
|
747 |
+
elseif (($this->property === '' && !ctype_space($string{$i}))
|
748 |
+
|| ($this->property === '/' || $string{$i} === '/')) {
|
749 |
+
$this->property .= $string{$i};
|
750 |
+
}
|
751 |
+
} elseif (!ctype_space($string{$i})) {
|
752 |
+
$this->property .= $string{$i};
|
753 |
+
}
|
754 |
+
break;
|
755 |
+
|
756 |
+
/* Case in-value */
|
757 |
+
case 'iv':
|
758 |
+
$pn = (($string{$i} === "\n" || $string{$i} === "\r") && $this->property_is_next($string, $i + 1) || $i == strlen($string) - 1);
|
759 |
+
if ($this->is_token($string, $i) || $pn) {
|
760 |
+
if ($string{$i} === '/' && @$string{$i + 1} === '*') {
|
761 |
+
$this->status = 'ic';
|
762 |
+
++$i;
|
763 |
+
$this->from[] = 'iv';
|
764 |
+
} elseif (($string{$i} === '"' || $string{$i} === "'" || $string{$i} === '(')) {
|
765 |
+
$this->cur_string[] = $string{$i};
|
766 |
+
$this->str_char[] = ($string{$i} === '(') ? ')' : $string{$i};
|
767 |
+
$this->status = 'instr';
|
768 |
+
$this->from[] = 'iv';
|
769 |
+
$this->quoted_string[] = in_array(strtolower($this->property), $quoted_string_properties);
|
770 |
+
} elseif ($string{$i} === ',') {
|
771 |
+
$this->sub_value = trim($this->sub_value) . ',';
|
772 |
+
} elseif ($string{$i} === '\\') {
|
773 |
+
$this->sub_value .= $this->_unicode($string, $i);
|
774 |
+
} elseif ($string{$i} === ';' || $pn) {
|
775 |
+
if ($this->selector{0} === '@' && isset($at_rules[substr($this->selector, 1)]) && $at_rules[substr($this->selector, 1)] === 'iv') {
|
776 |
+
/* Add quotes to charset, import, namespace */
|
777 |
+
$this->sub_value_arr[] = trim($this->sub_value);
|
778 |
+
|
779 |
+
$this->status = 'is';
|
780 |
+
|
781 |
+
switch ($this->selector) {
|
782 |
+
case '@charset': $this->charset = '"'.$this->sub_value_arr[0].'"';
|
783 |
+
break;
|
784 |
+
case '@namespace': $this->namespace = implode(' ', $this->sub_value_arr);
|
785 |
+
break;
|
786 |
+
case '@import': $this->import[] = implode(' ', $this->sub_value_arr);
|
787 |
+
break;
|
788 |
+
}
|
789 |
+
|
790 |
+
$this->sub_value_arr = array();
|
791 |
+
$this->sub_value = '';
|
792 |
+
$this->selector = '';
|
793 |
+
$this->sel_separate = array();
|
794 |
+
} else {
|
795 |
+
$this->status = 'ip';
|
796 |
+
}
|
797 |
+
} elseif ($string{$i} !== '}') {
|
798 |
+
$this->sub_value .= $string{$i};
|
799 |
+
}
|
800 |
+
if (($string{$i} === '}' || $string{$i} === ';' || $pn) && !empty($this->selector)) {
|
801 |
+
if ($this->at == '') {
|
802 |
+
$this->at = $this->css_new_media_section(DEFAULT_AT);
|
803 |
+
}
|
804 |
+
|
805 |
+
// case settings
|
806 |
+
if ($this->get_cfg('lowercase_s')) {
|
807 |
+
$this->selector = strtolower($this->selector);
|
808 |
+
}
|
809 |
+
$this->property = strtolower($this->property);
|
810 |
+
|
811 |
+
$this->optimise->subvalue();
|
812 |
+
if ($this->sub_value != '') {
|
813 |
+
$this->sub_value_arr[] = $this->sub_value;
|
814 |
+
$this->sub_value = '';
|
815 |
+
}
|
816 |
+
|
817 |
+
$this->value = '';
|
818 |
+
while (count($this->sub_value_arr)) {
|
819 |
+
$sub = array_shift($this->sub_value_arr);
|
820 |
+
if (strstr($this->selector, 'font-face')) {
|
821 |
+
$sub = $this->quote_font_format($sub);
|
822 |
+
}
|
823 |
+
|
824 |
+
if ($sub != '')
|
825 |
+
$this->value .= ((!strlen($this->value) || substr($this->value,-1,1) === ',')?'':' ').$sub;
|
826 |
+
}
|
827 |
+
|
828 |
+
$this->optimise->value();
|
829 |
+
|
830 |
+
$valid = $this->property_is_valid($this->property);
|
831 |
+
if ((!$this->invalid_at || $this->get_cfg('preserve_css')) && (!$this->get_cfg('discard_invalid_properties') || $valid)) {
|
832 |
+
$this->css_add_property($this->at, $this->selector, $this->property, $this->value);
|
833 |
+
$this->_add_token(VALUE, $this->value);
|
834 |
+
$this->optimise->shorthands();
|
835 |
+
}
|
836 |
+
if (!$valid) {
|
837 |
+
if ($this->get_cfg('discard_invalid_properties')) {
|
838 |
+
$this->log('Removed invalid property: ' . $this->property, 'Warning');
|
839 |
+
} else {
|
840 |
+
$this->log('Invalid property in ' . strtoupper($this->get_cfg('css_level')) . ': ' . $this->property, 'Warning');
|
841 |
+
}
|
842 |
+
}
|
843 |
+
|
844 |
+
$this->property = '';
|
845 |
+
$this->sub_value_arr = array();
|
846 |
+
$this->value = '';
|
847 |
+
}
|
848 |
+
if ($string{$i} === '}') {
|
849 |
+
$this->explode_selectors();
|
850 |
+
$this->_add_token(SEL_END, $this->selector);
|
851 |
+
$this->status = 'is';
|
852 |
+
$this->invalid_at = false;
|
853 |
+
$this->selector = '';
|
854 |
+
if ($this->next_selector_at) {
|
855 |
+
$this->at = $this->css_new_media_section($this->next_selector_at);
|
856 |
+
$this->next_selector_at = '';
|
857 |
+
}
|
858 |
+
}
|
859 |
+
} elseif (!$pn) {
|
860 |
+
$this->sub_value .= $string{$i};
|
861 |
+
|
862 |
+
if (ctype_space($string{$i})) {
|
863 |
+
$this->optimise->subvalue();
|
864 |
+
if ($this->sub_value != '') {
|
865 |
+
$this->sub_value_arr[] = $this->sub_value;
|
866 |
+
$this->sub_value = '';
|
867 |
+
}
|
868 |
+
}
|
869 |
+
}
|
870 |
+
break;
|
871 |
+
|
872 |
+
/* Case in string */
|
873 |
+
case 'instr':
|
874 |
+
$_str_char = $this->str_char[count($this->str_char)-1];
|
875 |
+
$_cur_string = $this->cur_string[count($this->cur_string)-1];
|
876 |
+
$_quoted_string = $this->quoted_string[count($this->quoted_string)-1];
|
877 |
+
$temp_add = $string{$i};
|
878 |
+
|
879 |
+
// Add another string to the stack. Strings can't be nested inside of quotes, only parentheses, but
|
880 |
+
// parentheticals can be nested more than once.
|
881 |
+
if ($_str_char === ")" && ($string{$i} === "(" || $string{$i} === '"' || $string{$i} === '\'') && !$this->escaped($string, $i)) {
|
882 |
+
$this->cur_string[] = $string{$i};
|
883 |
+
$this->str_char[] = $string{$i} === '(' ? ')' : $string{$i};
|
884 |
+
$this->from[] = 'instr';
|
885 |
+
$this->quoted_string[] = ($_str_char === ')' && $string{$i} !== '(' && trim($_cur_string)==='(')?$_quoted_string:!($string{$i} === '(');
|
886 |
+
continue;
|
887 |
+
}
|
888 |
+
|
889 |
+
if ($_str_char !== ")" && ($string{$i} === "\n" || $string{$i} === "\r") && !($string{$i - 1} === '\\' && !$this->escaped($string, $i - 1))) {
|
890 |
+
$temp_add = "\\A";
|
891 |
+
$this->log('Fixed incorrect newline in string', 'Warning');
|
892 |
+
}
|
893 |
+
|
894 |
+
$_cur_string .= $temp_add;
|
895 |
+
|
896 |
+
if ($string{$i} === $_str_char && !$this->escaped($string, $i)) {
|
897 |
+
$this->status = array_pop($this->from);
|
898 |
+
|
899 |
+
if (!preg_match('|[' . implode('', $this->data['csstidy']['whitespace']) . ']|uis', $_cur_string) && $this->property !== 'content') {
|
900 |
+
if (!$_quoted_string) {
|
901 |
+
if ($_str_char !== ')') {
|
902 |
+
// Convert properties like
|
903 |
+
// font-family: 'Arial';
|
904 |
+
// to
|
905 |
+
// font-family: Arial;
|
906 |
+
// or
|
907 |
+
// url("abc")
|
908 |
+
// to
|
909 |
+
// url(abc)
|
910 |
+
$_cur_string = substr($_cur_string, 1, -1);
|
911 |
+
}
|
912 |
+
} else {
|
913 |
+
$_quoted_string = false;
|
914 |
+
}
|
915 |
+
}
|
916 |
+
|
917 |
+
array_pop($this->cur_string);
|
918 |
+
array_pop($this->quoted_string);
|
919 |
+
array_pop($this->str_char);
|
920 |
+
|
921 |
+
if ($_str_char === ')') {
|
922 |
+
$_cur_string = '(' . trim(substr($_cur_string, 1, -1)) . ')';
|
923 |
+
}
|
924 |
+
|
925 |
+
if ($this->status === 'iv') {
|
926 |
+
if (!$_quoted_string) {
|
927 |
+
if (strpos($_cur_string,',') !== false)
|
928 |
+
// we can on only remove space next to ','
|
929 |
+
$_cur_string = implode(',', array_map('trim', explode(',',$_cur_string)));
|
930 |
+
// and multiple spaces (too expensive)
|
931 |
+
if (strpos($_cur_string, ' ') !== false)
|
932 |
+
$_cur_string = preg_replace(",\s+,", ' ', $_cur_string);
|
933 |
+
}
|
934 |
+
$this->sub_value .= $_cur_string;
|
935 |
+
} elseif ($this->status === 'is') {
|
936 |
+
$this->selector .= $_cur_string;
|
937 |
+
} elseif ($this->status === 'instr') {
|
938 |
+
$this->cur_string[count($this->cur_string)-1] .= $_cur_string;
|
939 |
+
}
|
940 |
+
} else {
|
941 |
+
$this->cur_string[count($this->cur_string)-1] = $_cur_string;
|
942 |
+
}
|
943 |
+
break;
|
944 |
+
|
945 |
+
/* Case in-comment */
|
946 |
+
case 'ic':
|
947 |
+
if ($string{$i} === '*' && $string{$i + 1} === '/') {
|
948 |
+
$this->status = array_pop($this->from);
|
949 |
+
$i++;
|
950 |
+
$this->_add_token(COMMENT, $cur_comment);
|
951 |
+
$cur_comment = '';
|
952 |
+
} else {
|
953 |
+
$cur_comment .= $string{$i};
|
954 |
+
}
|
955 |
+
break;
|
956 |
+
}
|
957 |
+
}
|
958 |
+
|
959 |
+
$this->optimise->postparse();
|
960 |
+
|
961 |
+
$this->print->_reset();
|
962 |
+
|
963 |
+
@setlocale(LC_ALL, $old); // Set locale back to original setting
|
964 |
+
|
965 |
+
return!(empty($this->css) && empty($this->import) && empty($this->charset) && empty($this->tokens) && empty($this->namespace));
|
966 |
+
}
|
967 |
+
|
968 |
+
|
969 |
+
/**
|
970 |
+
* format() in font-face needs quoted values for somes browser (FF at least)
|
971 |
+
*
|
972 |
+
* @param $value
|
973 |
+
* @return string
|
974 |
+
*/
|
975 |
+
public function quote_font_format($value) {
|
976 |
+
if (strncmp($value,'format',6) == 0) {
|
977 |
+
$p = strpos($value,')',7);
|
978 |
+
$end = substr($value,$p);
|
979 |
+
$format_strings = $this->parse_string_list(substr($value, 7, $p-7));
|
980 |
+
if (!$format_strings) {
|
981 |
+
$value = '';
|
982 |
+
} else {
|
983 |
+
$value = 'format(';
|
984 |
+
|
985 |
+
foreach ($format_strings as $format_string) {
|
986 |
+
$value .= '"' . str_replace('"', '\\"', $format_string) . '",';
|
987 |
+
}
|
988 |
+
|
989 |
+
$value = substr($value, 0, -1) . $end;
|
990 |
+
}
|
991 |
+
}
|
992 |
+
return $value;
|
993 |
+
}
|
994 |
+
|
995 |
+
/**
|
996 |
+
* Explodes selectors
|
997 |
+
* @access private
|
998 |
+
* @version 1.0
|
999 |
+
*/
|
1000 |
+
public function explode_selectors() {
|
1001 |
+
// Explode multiple selectors
|
1002 |
+
if ($this->get_cfg('merge_selectors') === 1) {
|
1003 |
+
$new_sels = array();
|
1004 |
+
$lastpos = 0;
|
1005 |
+
$this->sel_separate[] = strlen($this->selector);
|
1006 |
+
foreach ($this->sel_separate as $num => $pos) {
|
1007 |
+
if ($num == count($this->sel_separate) - 1) {
|
1008 |
+
$pos += 1;
|
1009 |
+
}
|
1010 |
+
|
1011 |
+
$new_sels[] = substr($this->selector, $lastpos, $pos - $lastpos - 1);
|
1012 |
+
$lastpos = $pos;
|
1013 |
+
}
|
1014 |
+
|
1015 |
+
if (count($new_sels) > 1) {
|
1016 |
+
foreach ($new_sels as $selector) {
|
1017 |
+
if (isset($this->css[$this->at][$this->selector])) {
|
1018 |
+
$this->merge_css_blocks($this->at, $selector, $this->css[$this->at][$this->selector]);
|
1019 |
+
}
|
1020 |
+
}
|
1021 |
+
unset($this->css[$this->at][$this->selector]);
|
1022 |
+
}
|
1023 |
+
}
|
1024 |
+
$this->sel_separate = array();
|
1025 |
+
}
|
1026 |
+
|
1027 |
+
/**
|
1028 |
+
* Checks if a character is escaped (and returns true if it is)
|
1029 |
+
* @param string $string
|
1030 |
+
* @param integer $pos
|
1031 |
+
* @access public
|
1032 |
+
* @return bool
|
1033 |
+
* @version 1.02
|
1034 |
+
*/
|
1035 |
+
static function escaped(&$string, $pos) {
|
1036 |
+
return!(@($string{$pos - 1} !== '\\') || csstidy::escaped($string, $pos - 1));
|
1037 |
+
}
|
1038 |
+
|
1039 |
+
/**
|
1040 |
+
* Adds a property with value to the existing CSS code
|
1041 |
+
* @param string $media
|
1042 |
+
* @param string $selector
|
1043 |
+
* @param string $property
|
1044 |
+
* @param string $new_val
|
1045 |
+
* @access private
|
1046 |
+
* @version 1.2
|
1047 |
+
*/
|
1048 |
+
public function css_add_property($media, $selector, $property, $new_val) {
|
1049 |
+
if ($this->get_cfg('preserve_css') || trim($new_val) == '') {
|
1050 |
+
return;
|
1051 |
+
}
|
1052 |
+
|
1053 |
+
$this->added = true;
|
1054 |
+
if (isset($this->css[$media][$selector][$property])) {
|
1055 |
+
if (($this->is_important($this->css[$media][$selector][$property]) && $this->is_important($new_val)) || !$this->is_important($this->css[$media][$selector][$property])) {
|
1056 |
+
$this->css[$media][$selector][$property] = trim($new_val);
|
1057 |
+
}
|
1058 |
+
} else {
|
1059 |
+
$this->css[$media][$selector][$property] = trim($new_val);
|
1060 |
+
}
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
/**
|
1064 |
+
* Start a new media section.
|
1065 |
+
* Check if the media is not already known,
|
1066 |
+
* else rename it with extra spaces
|
1067 |
+
* to avoid merging
|
1068 |
+
*
|
1069 |
+
* @param string $media
|
1070 |
+
* @return string
|
1071 |
+
*/
|
1072 |
+
public function css_new_media_section($media) {
|
1073 |
+
if ($this->get_cfg('preserve_css')) {
|
1074 |
+
return $media;
|
1075 |
+
}
|
1076 |
+
|
1077 |
+
// if the last @media is the same as this
|
1078 |
+
// keep it
|
1079 |
+
if (!$this->css || !is_array($this->css) || empty($this->css)) {
|
1080 |
+
return $media;
|
1081 |
+
}
|
1082 |
+
end($this->css);
|
1083 |
+
list($at,) = each($this->css);
|
1084 |
+
if ($at == $media) {
|
1085 |
+
return $media;
|
1086 |
+
}
|
1087 |
+
while (isset($this->css[$media]))
|
1088 |
+
if (is_numeric($media))
|
1089 |
+
$media++;
|
1090 |
+
else
|
1091 |
+
$media .= ' ';
|
1092 |
+
return $media;
|
1093 |
+
}
|
1094 |
+
|
1095 |
+
/**
|
1096 |
+
* Start a new selector.
|
1097 |
+
* If already referenced in this media section,
|
1098 |
+
* rename it with extra space to avoid merging
|
1099 |
+
* except if merging is required,
|
1100 |
+
* or last selector is the same (merge siblings)
|
1101 |
+
*
|
1102 |
+
* never merge @font-face
|
1103 |
+
*
|
1104 |
+
* @param string $media
|
1105 |
+
* @param string $selector
|
1106 |
+
* @return string
|
1107 |
+
*/
|
1108 |
+
public function css_new_selector($media,$selector) {
|
1109 |
+
if ($this->get_cfg('preserve_css')) {
|
1110 |
+
return $selector;
|
1111 |
+
}
|
1112 |
+
$selector = trim($selector);
|
1113 |
+
if (strncmp($selector,'@font-face',10)!=0) {
|
1114 |
+
if ($this->settings['merge_selectors'] != false)
|
1115 |
+
return $selector;
|
1116 |
+
|
1117 |
+
if (!$this->css || !isset($this->css[$media]) || !$this->css[$media])
|
1118 |
+
return $selector;
|
1119 |
+
|
1120 |
+
// if last is the same, keep it
|
1121 |
+
end($this->css[$media]);
|
1122 |
+
list($sel,) = each($this->css[$media]);
|
1123 |
+
if ($sel == $selector) {
|
1124 |
+
return $selector;
|
1125 |
+
}
|
1126 |
+
}
|
1127 |
+
|
1128 |
+
while (isset($this->css[$media][$selector]))
|
1129 |
+
$selector .= ' ';
|
1130 |
+
return $selector;
|
1131 |
+
}
|
1132 |
+
|
1133 |
+
/**
|
1134 |
+
* Start a new propertie.
|
1135 |
+
* If already references in this selector,
|
1136 |
+
* rename it with extra space to avoid override
|
1137 |
+
*
|
1138 |
+
* @param string $media
|
1139 |
+
* @param string $selector
|
1140 |
+
* @param string $property
|
1141 |
+
* @return string
|
1142 |
+
*/
|
1143 |
+
public function css_new_property($media, $selector, $property) {
|
1144 |
+
if ($this->get_cfg('preserve_css')) {
|
1145 |
+
return $property;
|
1146 |
+
}
|
1147 |
+
if (!$this->css || !isset($this->css[$media][$selector]) || !$this->css[$media][$selector])
|
1148 |
+
return $property;
|
1149 |
+
|
1150 |
+
while (isset($this->css[$media][$selector][$property]))
|
1151 |
+
$property .= ' ';
|
1152 |
+
|
1153 |
+
return $property;
|
1154 |
+
}
|
1155 |
+
|
1156 |
+
/**
|
1157 |
+
* Adds CSS to an existing media/selector
|
1158 |
+
* @param string $media
|
1159 |
+
* @param string $selector
|
1160 |
+
* @param array $css_add
|
1161 |
+
* @access private
|
1162 |
+
* @version 1.1
|
1163 |
+
*/
|
1164 |
+
public function merge_css_blocks($media, $selector, $css_add) {
|
1165 |
+
foreach ($css_add as $property => $value) {
|
1166 |
+
$this->css_add_property($media, $selector, $property, $value, false);
|
1167 |
+
}
|
1168 |
+
}
|
1169 |
+
|
1170 |
+
/**
|
1171 |
+
* Checks if $value is !important.
|
1172 |
+
* @param string $value
|
1173 |
+
* @return bool
|
1174 |
+
* @access public
|
1175 |
+
* @version 1.0
|
1176 |
+
*/
|
1177 |
+
public function is_important(&$value) {
|
1178 |
+
return (
|
1179 |
+
strpos($value, '!') !== false // quick test
|
1180 |
+
AND !strcasecmp(substr(str_replace($this->data['csstidy']['whitespace'], '', $value), -10, 10), '!important'));
|
1181 |
+
}
|
1182 |
+
|
1183 |
+
/**
|
1184 |
+
* Returns a value without !important
|
1185 |
+
* @param string $value
|
1186 |
+
* @return string
|
1187 |
+
* @access public
|
1188 |
+
* @version 1.0
|
1189 |
+
*/
|
1190 |
+
public function gvw_important($value) {
|
1191 |
+
if ($this->is_important($value)) {
|
1192 |
+
$value = trim($value);
|
1193 |
+
$value = substr($value, 0, -9);
|
1194 |
+
$value = trim($value);
|
1195 |
+
$value = substr($value, 0, -1);
|
1196 |
+
$value = trim($value);
|
1197 |
+
return $value;
|
1198 |
+
}
|
1199 |
+
return $value;
|
1200 |
+
}
|
1201 |
+
|
1202 |
+
/**
|
1203 |
+
* Checks if the next word in a string from pos is a CSS property
|
1204 |
+
* @param string $istring
|
1205 |
+
* @param integer $pos
|
1206 |
+
* @return bool
|
1207 |
+
* @access private
|
1208 |
+
* @version 1.2
|
1209 |
+
*/
|
1210 |
+
public function property_is_next($istring, $pos) {
|
1211 |
+
$all_properties = & $this->data['csstidy']['all_properties'];
|
1212 |
+
$istring = substr($istring, $pos, strlen($istring) - $pos);
|
1213 |
+
$pos = strpos($istring, ':');
|
1214 |
+
if ($pos === false) {
|
1215 |
+
return false;
|
1216 |
+
}
|
1217 |
+
$istring = strtolower(trim(substr($istring, 0, $pos)));
|
1218 |
+
if (isset($all_properties[$istring])) {
|
1219 |
+
$this->log('Added semicolon to the end of declaration', 'Warning');
|
1220 |
+
return true;
|
1221 |
+
}
|
1222 |
+
return false;
|
1223 |
+
}
|
1224 |
+
|
1225 |
+
/**
|
1226 |
+
* Checks if a property is valid
|
1227 |
+
* @param string $property
|
1228 |
+
* @return bool;
|
1229 |
+
* @access public
|
1230 |
+
* @version 1.0
|
1231 |
+
*/
|
1232 |
+
public function property_is_valid($property) {
|
1233 |
+
if (in_array(trim($property), $this->data['csstidy']['multiple_properties'])) $property = trim($property);
|
1234 |
+
$all_properties = & $this->data['csstidy']['all_properties'];
|
1235 |
+
return (isset($all_properties[$property]) && strpos($all_properties[$property], strtoupper($this->get_cfg('css_level'))) !== false );
|
1236 |
+
}
|
1237 |
+
|
1238 |
+
/**
|
1239 |
+
* Accepts a list of strings (e.g., the argument to format() in a @font-face src property)
|
1240 |
+
* and returns a list of the strings. Converts things like:
|
1241 |
+
*
|
1242 |
+
* format(abc) => format("abc")
|
1243 |
+
* format(abc def) => format("abc","def")
|
1244 |
+
* format(abc "def") => format("abc","def")
|
1245 |
+
* format(abc, def, ghi) => format("abc","def","ghi")
|
1246 |
+
* format("abc",'def') => format("abc","def")
|
1247 |
+
* format("abc, def, ghi") => format("abc, def, ghi")
|
1248 |
+
*
|
1249 |
+
* @param string
|
1250 |
+
* @return array
|
1251 |
+
*/
|
1252 |
+
|
1253 |
+
public function parse_string_list($value) {
|
1254 |
+
$value = trim($value);
|
1255 |
+
|
1256 |
+
// Case: empty
|
1257 |
+
if (!$value) return array();
|
1258 |
+
|
1259 |
+
$strings = array();
|
1260 |
+
|
1261 |
+
$in_str = false;
|
1262 |
+
$current_string = '';
|
1263 |
+
|
1264 |
+
for ($i = 0, $_len = strlen($value); $i < $_len; $i++) {
|
1265 |
+
if (($value{$i} === ',' || $value{$i} === ' ') && $in_str === true) {
|
1266 |
+
$in_str = false;
|
1267 |
+
$strings[] = $current_string;
|
1268 |
+
$current_string = '';
|
1269 |
+
} elseif ($value{$i} === '"' || $value{$i} === "'") {
|
1270 |
+
if ($in_str === $value{$i}) {
|
1271 |
+
$strings[] = $current_string;
|
1272 |
+
$in_str = false;
|
1273 |
+
$current_string = '';
|
1274 |
+
continue;
|
1275 |
+
} elseif (!$in_str) {
|
1276 |
+
$in_str = $value{$i};
|
1277 |
+
}
|
1278 |
+
} else {
|
1279 |
+
if ($in_str) {
|
1280 |
+
$current_string .= $value{$i};
|
1281 |
+
} else {
|
1282 |
+
if (!preg_match("/[\s,]/", $value{$i})) {
|
1283 |
+
$in_str = true;
|
1284 |
+
$current_string = $value{$i};
|
1285 |
+
}
|
1286 |
+
}
|
1287 |
+
}
|
1288 |
+
}
|
1289 |
+
|
1290 |
+
if ($current_string) {
|
1291 |
+
$strings[] = $current_string;
|
1292 |
+
}
|
1293 |
+
|
1294 |
+
return $strings;
|
1295 |
+
}
|
1296 |
+
}
|
libs/CSSTidy/class.csstidy_optimise.php
ADDED
@@ -0,0 +1,963 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* CSSTidy - CSS Parser and Optimiser
|
5 |
+
*
|
6 |
+
* CSS Optimising Class
|
7 |
+
* This class optimises CSS data generated by csstidy.
|
8 |
+
*
|
9 |
+
* Copyright 2005, 2006, 2007 Florian Schmitz
|
10 |
+
*
|
11 |
+
* This file is part of CSSTidy.
|
12 |
+
*
|
13 |
+
* CSSTidy is free software; you can redistribute it and/or modify
|
14 |
+
* it under the terms of the GNU Lesser General Public License as published by
|
15 |
+
* the Free Software Foundation; either version 2.1 of the License, or
|
16 |
+
* (at your option) any later version.
|
17 |
+
*
|
18 |
+
* CSSTidy is distributed in the hope that it will be useful,
|
19 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
21 |
+
* GNU Lesser General Public License for more details.
|
22 |
+
*
|
23 |
+
* You should have received a copy of the GNU Lesser General Public License
|
24 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
25 |
+
*
|
26 |
+
* @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
|
27 |
+
* @package csstidy
|
28 |
+
* @author Florian Schmitz (floele at gmail dot com) 2005-2007
|
29 |
+
* @author Brett Zamir (brettz9 at yahoo dot com) 2007
|
30 |
+
* @author Nikolay Matsievsky (speed at webo dot name) 2009-2010
|
31 |
+
* @author Cedric Morin (cedric at yterium dot com) 2010-2012
|
32 |
+
*/
|
33 |
+
|
34 |
+
/**
|
35 |
+
* CSS Optimising Class
|
36 |
+
*
|
37 |
+
* This class optimises CSS data generated by csstidy.
|
38 |
+
*
|
39 |
+
* @package csstidy
|
40 |
+
* @author Florian Schmitz (floele at gmail dot com) 2005-2006
|
41 |
+
* @version 1.0
|
42 |
+
*/
|
43 |
+
class csstidy_optimise {
|
44 |
+
|
45 |
+
/**
|
46 |
+
* csstidy object
|
47 |
+
* @var object
|
48 |
+
*/
|
49 |
+
public $parser;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Constructor
|
53 |
+
* @param array $css contains the class csstidy
|
54 |
+
* @access private
|
55 |
+
* @version 1.0
|
56 |
+
*/
|
57 |
+
public function __construct($css) {
|
58 |
+
$this->parser = $css;
|
59 |
+
$this->css = & $css->css;
|
60 |
+
$this->sub_value = & $css->sub_value;
|
61 |
+
$this->at = & $css->at;
|
62 |
+
$this->selector = & $css->selector;
|
63 |
+
$this->property = & $css->property;
|
64 |
+
$this->value = & $css->value;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Optimises $css after parsing
|
69 |
+
* @access public
|
70 |
+
* @version 1.0
|
71 |
+
*/
|
72 |
+
public function postparse() {
|
73 |
+
if ($this->parser->get_cfg('preserve_css')) {
|
74 |
+
return;
|
75 |
+
}
|
76 |
+
|
77 |
+
if ((int)$this->parser->get_cfg('merge_selectors') === 2) {
|
78 |
+
foreach ($this->css as $medium => $value) {
|
79 |
+
$this->merge_selectors($this->css[$medium]);
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
if ($this->parser->get_cfg('discard_invalid_selectors')) {
|
84 |
+
foreach ($this->css as $medium => $value) {
|
85 |
+
$this->discard_invalid_selectors($this->css[$medium]);
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
if ($this->parser->get_cfg('optimise_shorthands') > 0) {
|
90 |
+
foreach ($this->css as $medium => $value) {
|
91 |
+
foreach ($value as $selector => $value1) {
|
92 |
+
$this->css[$medium][$selector] = $this->merge_4value_shorthands($this->css[$medium][$selector]);
|
93 |
+
|
94 |
+
if ($this->parser->get_cfg('optimise_shorthands') < 2) {
|
95 |
+
continue;
|
96 |
+
}
|
97 |
+
|
98 |
+
$this->css[$medium][$selector] = $this->merge_font($this->css[$medium][$selector]);
|
99 |
+
|
100 |
+
if ($this->parser->get_cfg('optimise_shorthands') < 3) {
|
101 |
+
continue;
|
102 |
+
}
|
103 |
+
|
104 |
+
$this->css[$medium][$selector] = $this->merge_bg($this->css[$medium][$selector]);
|
105 |
+
if (empty($this->css[$medium][$selector])) {
|
106 |
+
unset($this->css[$medium][$selector]);
|
107 |
+
}
|
108 |
+
}
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Optimises values
|
115 |
+
* @access public
|
116 |
+
* @version 1.0
|
117 |
+
*/
|
118 |
+
public function value() {
|
119 |
+
$shorthands = & $this->parser->data['csstidy']['shorthands'];
|
120 |
+
|
121 |
+
// optimise shorthand properties
|
122 |
+
if (isset($shorthands[$this->property])) {
|
123 |
+
$temp = $this->shorthand($this->value); // FIXME - move
|
124 |
+
if ($temp != $this->value) {
|
125 |
+
$this->parser->log('Optimised shorthand notation (' . $this->property . '): Changed "' . $this->value . '" to "' . $temp . '"', 'Information');
|
126 |
+
}
|
127 |
+
$this->value = $temp;
|
128 |
+
}
|
129 |
+
|
130 |
+
// Remove whitespace at ! important
|
131 |
+
if ($this->value != $this->compress_important($this->value)) {
|
132 |
+
$this->parser->log('Optimised !important', 'Information');
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Optimises shorthands
|
138 |
+
* @access public
|
139 |
+
* @version 1.0
|
140 |
+
*/
|
141 |
+
public function shorthands() {
|
142 |
+
$shorthands = & $this->parser->data['csstidy']['shorthands'];
|
143 |
+
|
144 |
+
if (!$this->parser->get_cfg('optimise_shorthands') || $this->parser->get_cfg('preserve_css')) {
|
145 |
+
return;
|
146 |
+
}
|
147 |
+
|
148 |
+
if ($this->property === 'font' && $this->parser->get_cfg('optimise_shorthands') > 1) {
|
149 |
+
$this->css[$this->at][$this->selector]['font']='';
|
150 |
+
$this->parser->merge_css_blocks($this->at, $this->selector, $this->dissolve_short_font($this->value));
|
151 |
+
}
|
152 |
+
if ($this->property === 'background' && $this->parser->get_cfg('optimise_shorthands') > 2) {
|
153 |
+
$this->css[$this->at][$this->selector]['background']='';
|
154 |
+
$this->parser->merge_css_blocks($this->at, $this->selector, $this->dissolve_short_bg($this->value));
|
155 |
+
}
|
156 |
+
if (isset($shorthands[$this->property])) {
|
157 |
+
$this->parser->merge_css_blocks($this->at, $this->selector, $this->dissolve_4value_shorthands($this->property, $this->value));
|
158 |
+
if (is_array($shorthands[$this->property])) {
|
159 |
+
$this->css[$this->at][$this->selector][$this->property] = '';
|
160 |
+
}
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Optimises a sub-value
|
166 |
+
* @access public
|
167 |
+
* @version 1.0
|
168 |
+
*/
|
169 |
+
public function subvalue() {
|
170 |
+
$replace_colors = & $this->parser->data['csstidy']['replace_colors'];
|
171 |
+
|
172 |
+
$this->sub_value = trim($this->sub_value);
|
173 |
+
if ($this->sub_value == '') { // caution : '0'
|
174 |
+
return;
|
175 |
+
}
|
176 |
+
|
177 |
+
$important = '';
|
178 |
+
if ($this->parser->is_important($this->sub_value)) {
|
179 |
+
$important = '!important';
|
180 |
+
}
|
181 |
+
$this->sub_value = $this->parser->gvw_important($this->sub_value);
|
182 |
+
|
183 |
+
// Compress font-weight
|
184 |
+
if ($this->property === 'font-weight' && $this->parser->get_cfg('compress_font-weight')) {
|
185 |
+
if ($this->sub_value === 'bold') {
|
186 |
+
$this->sub_value = '700';
|
187 |
+
$this->parser->log('Optimised font-weight: Changed "bold" to "700"', 'Information');
|
188 |
+
} elseif ($this->sub_value === 'normal') {
|
189 |
+
$this->sub_value = '400';
|
190 |
+
$this->parser->log('Optimised font-weight: Changed "normal" to "400"', 'Information');
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
$temp = $this->compress_numbers($this->sub_value);
|
195 |
+
if (strcasecmp($temp, $this->sub_value) !== 0) {
|
196 |
+
if (strlen($temp) > strlen($this->sub_value)) {
|
197 |
+
$this->parser->log('Fixed invalid number: Changed "' . $this->sub_value . '" to "' . $temp . '"', 'Warning');
|
198 |
+
} else {
|
199 |
+
$this->parser->log('Optimised number: Changed "' . $this->sub_value . '" to "' . $temp . '"', 'Information');
|
200 |
+
}
|
201 |
+
$this->sub_value = $temp;
|
202 |
+
}
|
203 |
+
if ($this->parser->get_cfg('compress_colors')) {
|
204 |
+
$temp = $this->cut_color($this->sub_value);
|
205 |
+
if ($temp !== $this->sub_value) {
|
206 |
+
if (isset($replace_colors[$this->sub_value])) {
|
207 |
+
$this->parser->log('Fixed invalid color name: Changed "' . $this->sub_value . '" to "' . $temp . '"', 'Warning');
|
208 |
+
} else {
|
209 |
+
$this->parser->log('Optimised color: Changed "' . $this->sub_value . '" to "' . $temp . '"', 'Information');
|
210 |
+
}
|
211 |
+
$this->sub_value = $temp;
|
212 |
+
}
|
213 |
+
}
|
214 |
+
$this->sub_value .= $important;
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Compresses shorthand values. Example: margin:1px 1px 1px 1px -> margin:1px
|
219 |
+
* @param string $value
|
220 |
+
* @access public
|
221 |
+
* @return string
|
222 |
+
* @version 1.0
|
223 |
+
*/
|
224 |
+
public function shorthand($value) {
|
225 |
+
$important = '';
|
226 |
+
if ($this->parser->is_important($value)) {
|
227 |
+
$values = $this->parser->gvw_important($value);
|
228 |
+
$important = '!important';
|
229 |
+
}
|
230 |
+
else
|
231 |
+
$values = $value;
|
232 |
+
|
233 |
+
$values = explode(' ', $values);
|
234 |
+
switch (count($values)) {
|
235 |
+
case 4:
|
236 |
+
if ($values[0] == $values[1] && $values[0] == $values[2] && $values[0] == $values[3]) {
|
237 |
+
return $values[0] . $important;
|
238 |
+
} elseif ($values[1] == $values[3] && $values[0] == $values[2]) {
|
239 |
+
return $values[0] . ' ' . $values[1] . $important;
|
240 |
+
} elseif ($values[1] == $values[3]) {
|
241 |
+
return $values[0] . ' ' . $values[1] . ' ' . $values[2] . $important;
|
242 |
+
}
|
243 |
+
break;
|
244 |
+
|
245 |
+
case 3:
|
246 |
+
if ($values[0] == $values[1] && $values[0] == $values[2]) {
|
247 |
+
return $values[0] . $important;
|
248 |
+
} elseif ($values[0] == $values[2]) {
|
249 |
+
return $values[0] . ' ' . $values[1] . $important;
|
250 |
+
}
|
251 |
+
break;
|
252 |
+
|
253 |
+
case 2:
|
254 |
+
if ($values[0] == $values[1]) {
|
255 |
+
return $values[0] . $important;
|
256 |
+
}
|
257 |
+
break;
|
258 |
+
}
|
259 |
+
|
260 |
+
return $value;
|
261 |
+
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Removes unnecessary whitespace in ! important
|
265 |
+
* @param string $string
|
266 |
+
* @return string
|
267 |
+
* @access public
|
268 |
+
* @version 1.1
|
269 |
+
*/
|
270 |
+
public function compress_important(&$string) {
|
271 |
+
if ($this->parser->is_important($string)) {
|
272 |
+
$important = $this->parser->get_cfg('space_before_important') ? ' !important' : '!important';
|
273 |
+
$string = $this->parser->gvw_important($string) . $important;
|
274 |
+
}
|
275 |
+
return $string;
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Color compression function. Converts all rgb() values to #-values and uses the short-form if possible. Also replaces 4 color names by #-values.
|
280 |
+
* @param string $color
|
281 |
+
* @return string
|
282 |
+
* @version 1.1
|
283 |
+
*/
|
284 |
+
public function cut_color($color) {
|
285 |
+
$replace_colors = & $this->parser->data['csstidy']['replace_colors'];
|
286 |
+
|
287 |
+
// if it's a string, don't touch !
|
288 |
+
if (strncmp($color, "'", 1) == 0 || strncmp($color, '"', 1) == 0)
|
289 |
+
return $color;
|
290 |
+
|
291 |
+
/* expressions complexes de type gradient */
|
292 |
+
if (strpos($color, '(') !== false && strncmp($color, 'rgb(' ,4) != 0) {
|
293 |
+
// on ne touche pas aux couleurs dans les expression ms, c'est trop sensible
|
294 |
+
if (stripos($color, 'progid:') !== false)
|
295 |
+
return $color;
|
296 |
+
preg_match_all(",rgb\([^)]+\),i", $color, $matches, PREG_SET_ORDER);
|
297 |
+
if (count($matches)) {
|
298 |
+
foreach ($matches as $m) {
|
299 |
+
$color = str_replace($m[0], $this->cut_color($m[0]), $color);
|
300 |
+
}
|
301 |
+
}
|
302 |
+
preg_match_all(",#[0-9a-f]{6}(?=[^0-9a-f]),i", $color, $matches, PREG_SET_ORDER);
|
303 |
+
if (count($matches)) {
|
304 |
+
foreach ($matches as $m) {
|
305 |
+
$color = str_replace($m[0],$this->cut_color($m[0]), $color);
|
306 |
+
}
|
307 |
+
}
|
308 |
+
return $color;
|
309 |
+
}
|
310 |
+
|
311 |
+
// rgb(0,0,0) -> #000000 (or #000 in this case later)
|
312 |
+
if (strncasecmp($color, 'rgb(', 4)==0) {
|
313 |
+
$color_tmp = substr($color, 4, strlen($color) - 5);
|
314 |
+
$color_tmp = explode(',', $color_tmp);
|
315 |
+
for ($i = 0; $i < count($color_tmp); $i++) {
|
316 |
+
$color_tmp[$i] = trim($color_tmp[$i]);
|
317 |
+
if (substr($color_tmp[$i], -1) === '%') {
|
318 |
+
$color_tmp[$i] = round((255 * $color_tmp[$i]) / 100);
|
319 |
+
}
|
320 |
+
if ($color_tmp[$i] > 255)
|
321 |
+
$color_tmp[$i] = 255;
|
322 |
+
}
|
323 |
+
$color = '#';
|
324 |
+
for ($i = 0; $i < 3; $i++) {
|
325 |
+
if ($color_tmp[$i] < 16) {
|
326 |
+
$color .= '0' . dechex($color_tmp[$i]);
|
327 |
+
} else {
|
328 |
+
$color .= dechex($color_tmp[$i]);
|
329 |
+
}
|
330 |
+
}
|
331 |
+
}
|
332 |
+
|
333 |
+
// Fix bad color names
|
334 |
+
if (isset($replace_colors[strtolower($color)])) {
|
335 |
+
$color = $replace_colors[strtolower($color)];
|
336 |
+
}
|
337 |
+
|
338 |
+
// #aabbcc -> #abc
|
339 |
+
if (strlen($color) == 7) {
|
340 |
+
$color_temp = strtolower($color);
|
341 |
+
if ($color_temp{0} === '#' && $color_temp{1} == $color_temp{2} && $color_temp{3} == $color_temp{4} && $color_temp{5} == $color_temp{6}) {
|
342 |
+
$color = '#' . $color{1} . $color{3} . $color{5};
|
343 |
+
}
|
344 |
+
}
|
345 |
+
|
346 |
+
switch (strtolower($color)) {
|
347 |
+
/* color name -> hex code */
|
348 |
+
case 'black': return '#000';
|
349 |
+
case 'fuchsia': return '#f0f';
|
350 |
+
case 'white': return '#fff';
|
351 |
+
case 'yellow': return '#ff0';
|
352 |
+
|
353 |
+
/* hex code -> color name */
|
354 |
+
case '#800000': return 'maroon';
|
355 |
+
case '#ffa500': return 'orange';
|
356 |
+
case '#808000': return 'olive';
|
357 |
+
case '#800080': return 'purple';
|
358 |
+
case '#008000': return 'green';
|
359 |
+
case '#000080': return 'navy';
|
360 |
+
case '#008080': return 'teal';
|
361 |
+
case '#c0c0c0': return 'silver';
|
362 |
+
case '#808080': return 'gray';
|
363 |
+
case '#f00': return 'red';
|
364 |
+
}
|
365 |
+
|
366 |
+
return $color;
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* Compresses numbers (ie. 1.0 becomes 1 or 1.100 becomes 1.1 )
|
371 |
+
* @param string $subvalue
|
372 |
+
* @return string
|
373 |
+
* @version 1.2
|
374 |
+
*/
|
375 |
+
public function compress_numbers($subvalue) {
|
376 |
+
$unit_values = & $this->parser->data['csstidy']['unit_values'];
|
377 |
+
$color_values = & $this->parser->data['csstidy']['color_values'];
|
378 |
+
|
379 |
+
// for font:1em/1em sans-serif...;
|
380 |
+
if ($this->property === 'font') {
|
381 |
+
$temp = explode('/', $subvalue);
|
382 |
+
} else {
|
383 |
+
$temp = array($subvalue);
|
384 |
+
}
|
385 |
+
|
386 |
+
for ($l = 0; $l < count($temp); $l++) {
|
387 |
+
// if we are not dealing with a number at this point, do not optimise anything
|
388 |
+
$number = $this->AnalyseCssNumber($temp[$l]);
|
389 |
+
if ($number === false) {
|
390 |
+
return $subvalue;
|
391 |
+
}
|
392 |
+
|
393 |
+
// Fix bad colors
|
394 |
+
if (in_array($this->property, $color_values)) {
|
395 |
+
$temp[$l] = '#' . $temp[$l];
|
396 |
+
continue;
|
397 |
+
}
|
398 |
+
|
399 |
+
if (abs($number[0]) > 0) {
|
400 |
+
if ($number[1] == '' && in_array($this->property, $unit_values, true)) {
|
401 |
+
$number[1] = 'px';
|
402 |
+
}
|
403 |
+
} elseif ($number[1] != 's' && $number[1] != 'ms') {
|
404 |
+
$number[1] = '';
|
405 |
+
}
|
406 |
+
|
407 |
+
$temp[$l] = $number[0] . $number[1];
|
408 |
+
}
|
409 |
+
|
410 |
+
return ((count($temp) > 1) ? $temp[0] . '/' . $temp[1] : $temp[0]);
|
411 |
+
}
|
412 |
+
|
413 |
+
/**
|
414 |
+
* Checks if a given string is a CSS valid number. If it is,
|
415 |
+
* an array containing the value and unit is returned
|
416 |
+
* @param string $string
|
417 |
+
* @return array ('unit' if unit is found or '' if no unit exists, number value) or false if no number
|
418 |
+
*/
|
419 |
+
public function AnalyseCssNumber($string) {
|
420 |
+
// most simple checks first
|
421 |
+
if (strlen($string) == 0 || ctype_alpha($string{0})) {
|
422 |
+
return false;
|
423 |
+
}
|
424 |
+
|
425 |
+
$units = & $this->parser->data['csstidy']['units'];
|
426 |
+
$return = array(0, '');
|
427 |
+
|
428 |
+
$return[0] = floatval($string);
|
429 |
+
if (abs($return[0]) > 0 && abs($return[0]) < 1) {
|
430 |
+
if ($return[0] < 0) {
|
431 |
+
$return[0] = '-' . ltrim(substr($return[0], 1), '0');
|
432 |
+
} else {
|
433 |
+
$return[0] = ltrim($return[0], '0');
|
434 |
+
}
|
435 |
+
}
|
436 |
+
|
437 |
+
// Look for unit and split from value if exists
|
438 |
+
foreach ($units as $unit) {
|
439 |
+
$expectUnitAt = strlen($string) - strlen($unit);
|
440 |
+
if (!($unitInString = stristr($string, $unit))) { // mb_strpos() fails with "false"
|
441 |
+
continue;
|
442 |
+
}
|
443 |
+
$actualPosition = strpos($string, $unitInString);
|
444 |
+
if ($expectUnitAt === $actualPosition) {
|
445 |
+
$return[1] = $unit;
|
446 |
+
$string = substr($string, 0, - strlen($unit));
|
447 |
+
break;
|
448 |
+
}
|
449 |
+
}
|
450 |
+
if (!is_numeric($string)) {
|
451 |
+
return false;
|
452 |
+
}
|
453 |
+
return $return;
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Merges selectors with same properties. Example: a{color:red} b{color:red} -> a,b{color:red}
|
458 |
+
* Very basic and has at least one bug. Hopefully there is a replacement soon.
|
459 |
+
* @param array $array
|
460 |
+
* @return array
|
461 |
+
* @access public
|
462 |
+
* @version 1.2
|
463 |
+
*/
|
464 |
+
public function merge_selectors(&$array) {
|
465 |
+
$css = $array;
|
466 |
+
foreach ($css as $key => $value) {
|
467 |
+
if (!isset($css[$key])) {
|
468 |
+
continue;
|
469 |
+
}
|
470 |
+
$newsel = '';
|
471 |
+
|
472 |
+
// Check if properties also exist in another selector
|
473 |
+
$keys = array();
|
474 |
+
// PHP bug (?) without $css = $array; here
|
475 |
+
foreach ($css as $selector => $vali) {
|
476 |
+
if ($selector == $key) {
|
477 |
+
continue;
|
478 |
+
}
|
479 |
+
|
480 |
+
if ($css[$key] === $vali) {
|
481 |
+
$keys[] = $selector;
|
482 |
+
}
|
483 |
+
}
|
484 |
+
|
485 |
+
if (!empty($keys)) {
|
486 |
+
$newsel = $key;
|
487 |
+
unset($css[$key]);
|
488 |
+
foreach ($keys as $selector) {
|
489 |
+
unset($css[$selector]);
|
490 |
+
$newsel .= ',' . $selector;
|
491 |
+
}
|
492 |
+
$css[$newsel] = $value;
|
493 |
+
}
|
494 |
+
}
|
495 |
+
$array = $css;
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Removes invalid selectors and their corresponding rule-sets as
|
500 |
+
* defined by 4.1.7 in REC-CSS2. This is a very rudimentary check
|
501 |
+
* and should be replaced by a full-blown parsing algorithm or
|
502 |
+
* regular expression
|
503 |
+
* @version 1.4
|
504 |
+
*/
|
505 |
+
public function discard_invalid_selectors(&$array) {
|
506 |
+
$invalid = array('+' => true, '~' => true, ',' => true, '>' => true);
|
507 |
+
foreach ($array as $selector => $decls) {
|
508 |
+
$ok = true;
|
509 |
+
$selectors = array_map('trim', explode(',', $selector));
|
510 |
+
foreach ($selectors as $s) {
|
511 |
+
$simple_selectors = preg_split('/\s*[+>~\s]\s*/', $s);
|
512 |
+
foreach ($simple_selectors as $ss) {
|
513 |
+
if ($ss === '')
|
514 |
+
$ok = false;
|
515 |
+
// could also check $ss for internal structure,
|
516 |
+
// but that probably would be too slow
|
517 |
+
}
|
518 |
+
}
|
519 |
+
if (!$ok)
|
520 |
+
unset($array[$selector]);
|
521 |
+
}
|
522 |
+
}
|
523 |
+
|
524 |
+
/**
|
525 |
+
* Dissolves properties like padding:10px 10px 10px to padding-top:10px;padding-bottom:10px;...
|
526 |
+
* @param string $property
|
527 |
+
* @param string $value
|
528 |
+
* @return array
|
529 |
+
* @version 1.0
|
530 |
+
* @see merge_4value_shorthands()
|
531 |
+
*/
|
532 |
+
public function dissolve_4value_shorthands($property, $value) {
|
533 |
+
$shorthands = & $this->parser->data['csstidy']['shorthands'];
|
534 |
+
if (!is_array($shorthands[$property])) {
|
535 |
+
$return[$property] = $value;
|
536 |
+
return $return;
|
537 |
+
}
|
538 |
+
|
539 |
+
$important = '';
|
540 |
+
if ($this->parser->is_important($value)) {
|
541 |
+
$value = $this->parser->gvw_important($value);
|
542 |
+
$important = '!important';
|
543 |
+
}
|
544 |
+
$values = explode(' ', $value);
|
545 |
+
|
546 |
+
|
547 |
+
$return = array();
|
548 |
+
if (count($values) == 4) {
|
549 |
+
for ($i = 0; $i < 4; $i++) {
|
550 |
+
$return[$shorthands[$property][$i]] = $values[$i] . $important;
|
551 |
+
}
|
552 |
+
} elseif (count($values) == 3) {
|
553 |
+
$return[$shorthands[$property][0]] = $values[0] . $important;
|
554 |
+
$return[$shorthands[$property][1]] = $values[1] . $important;
|
555 |
+
$return[$shorthands[$property][3]] = $values[1] . $important;
|
556 |
+
$return[$shorthands[$property][2]] = $values[2] . $important;
|
557 |
+
} elseif (count($values) == 2) {
|
558 |
+
for ($i = 0; $i < 4; $i++) {
|
559 |
+
$return[$shorthands[$property][$i]] = (($i % 2 != 0)) ? $values[1] . $important : $values[0] . $important;
|
560 |
+
}
|
561 |
+
} else {
|
562 |
+
for ($i = 0; $i < 4; $i++) {
|
563 |
+
$return[$shorthands[$property][$i]] = $values[0] . $important;
|
564 |
+
}
|
565 |
+
}
|
566 |
+
|
567 |
+
return $return;
|
568 |
+
}
|
569 |
+
|
570 |
+
/**
|
571 |
+
* Explodes a string as explode() does, however, not if $sep is escaped or within a string.
|
572 |
+
* @param string $sep seperator
|
573 |
+
* @param string $string
|
574 |
+
* @return array
|
575 |
+
* @version 1.0
|
576 |
+
*/
|
577 |
+
public function explode_ws($sep, $string) {
|
578 |
+
$status = 'st';
|
579 |
+
$to = '';
|
580 |
+
|
581 |
+
$output = array();
|
582 |
+
$num = 0;
|
583 |
+
for ($i = 0, $len = strlen($string); $i < $len; $i++) {
|
584 |
+
switch ($status) {
|
585 |
+
case 'st':
|
586 |
+
if ($string{$i} == $sep && !$this->parser->escaped($string, $i)) {
|
587 |
+
++$num;
|
588 |
+
} elseif ($string{$i} === '"' || $string{$i} === '\'' || $string{$i} === '(' && !$this->parser->escaped($string, $i)) {
|
589 |
+
$status = 'str';
|
590 |
+
$to = ($string{$i} === '(') ? ')' : $string{$i};
|
591 |
+
(isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
|
592 |
+
} else {
|
593 |
+
(isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
|
594 |
+
}
|
595 |
+
break;
|
596 |
+
|
597 |
+
case 'str':
|
598 |
+
if ($string{$i} == $to && !$this->parser->escaped($string, $i)) {
|
599 |
+
$status = 'st';
|
600 |
+
}
|
601 |
+
(isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
|
602 |
+
break;
|
603 |
+
}
|
604 |
+
}
|
605 |
+
|
606 |
+
if (isset($output[0])) {
|
607 |
+
return $output;
|
608 |
+
} else {
|
609 |
+
return array($output);
|
610 |
+
}
|
611 |
+
}
|
612 |
+
|
613 |
+
/**
|
614 |
+
* Merges Shorthand properties again, the opposite of dissolve_4value_shorthands()
|
615 |
+
* @param array $array
|
616 |
+
* @return array
|
617 |
+
* @version 1.2
|
618 |
+
* @see dissolve_4value_shorthands()
|
619 |
+
*/
|
620 |
+
public function merge_4value_shorthands($array) {
|
621 |
+
$return = $array;
|
622 |
+
$shorthands = & $this->parser->data['csstidy']['shorthands'];
|
623 |
+
|
624 |
+
foreach ($shorthands as $key => $value) {
|
625 |
+
if (isset($array[$value[0]]) && isset($array[$value[1]])
|
626 |
+
&& isset($array[$value[2]]) && isset($array[$value[3]]) && $value !== 0) {
|
627 |
+
$return[$key] = '';
|
628 |
+
|
629 |
+
$important = '';
|
630 |
+
for ($i = 0; $i < 4; $i++) {
|
631 |
+
$val = $array[$value[$i]];
|
632 |
+
if ($this->parser->is_important($val)) {
|
633 |
+
$important = '!important';
|
634 |
+
$return[$key] .= $this->parser->gvw_important($val) . ' ';
|
635 |
+
} else {
|
636 |
+
$return[$key] .= $val . ' ';
|
637 |
+
}
|
638 |
+
unset($return[$value[$i]]);
|
639 |
+
}
|
640 |
+
$return[$key] = $this->shorthand(trim($return[$key] . $important));
|
641 |
+
}
|
642 |
+
}
|
643 |
+
return $return;
|
644 |
+
}
|
645 |
+
|
646 |
+
/**
|
647 |
+
* Dissolve background property
|
648 |
+
* @param string $str_value
|
649 |
+
* @return array
|
650 |
+
* @version 1.0
|
651 |
+
* @see merge_bg()
|
652 |
+
* @todo full CSS 3 compliance
|
653 |
+
*/
|
654 |
+
public function dissolve_short_bg($str_value) {
|
655 |
+
// don't try to explose background gradient !
|
656 |
+
if (stripos($str_value, 'gradient(')!== false)
|
657 |
+
return array('background'=>$str_value);
|
658 |
+
|
659 |
+
$background_prop_default = & $this->parser->data['csstidy']['background_prop_default'];
|
660 |
+
$repeat = array('repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'space');
|
661 |
+
$attachment = array('scroll', 'fixed', 'local');
|
662 |
+
$clip = array('border', 'padding');
|
663 |
+
$origin = array('border', 'padding', 'content');
|
664 |
+
$pos = array('top', 'center', 'bottom', 'left', 'right');
|
665 |
+
$important = '';
|
666 |
+
$return = array('background-image' => null, 'background-size' => null, 'background-repeat' => null, 'background-position' => null, 'background-attachment' => null, 'background-clip' => null, 'background-origin' => null, 'background-color' => null);
|
667 |
+
|
668 |
+
if ($this->parser->is_important($str_value)) {
|
669 |
+
$important = ' !important';
|
670 |
+
$str_value = $this->parser->gvw_important($str_value);
|
671 |
+
}
|
672 |
+
|
673 |
+
$str_value = $this->explode_ws(',', $str_value);
|
674 |
+
for ($i = 0; $i < count($str_value); $i++) {
|
675 |
+
$have['clip'] = false;
|
676 |
+
$have['pos'] = false;
|
677 |
+
$have['color'] = false;
|
678 |
+
$have['bg'] = false;
|
679 |
+
|
680 |
+
if (is_array($str_value[$i])) {
|
681 |
+
$str_value[$i] = $str_value[$i][0];
|
682 |
+
}
|
683 |
+
$str_value[$i] = $this->explode_ws(' ', trim($str_value[$i]));
|
684 |
+
|
685 |
+
for ($j = 0; $j < count($str_value[$i]); $j++) {
|
686 |
+
if ($have['bg'] === false && (substr($str_value[$i][$j], 0, 4) === 'url(' || $str_value[$i][$j] === 'none')) {
|
687 |
+
$return['background-image'] .= $str_value[$i][$j] . ',';
|
688 |
+
$have['bg'] = true;
|
689 |
+
} elseif (in_array($str_value[$i][$j], $repeat, true)) {
|
690 |
+
$return['background-repeat'] .= $str_value[$i][$j] . ',';
|
691 |
+
} elseif (in_array($str_value[$i][$j], $attachment, true)) {
|
692 |
+
$return['background-attachment'] .= $str_value[$i][$j] . ',';
|
693 |
+
} elseif (in_array($str_value[$i][$j], $clip, true) && !$have['clip']) {
|
694 |
+
$return['background-clip'] .= $str_value[$i][$j] . ',';
|
695 |
+
$have['clip'] = true;
|
696 |
+
} elseif (in_array($str_value[$i][$j], $origin, true)) {
|
697 |
+
$return['background-origin'] .= $str_value[$i][$j] . ',';
|
698 |
+
} elseif ($str_value[$i][$j]{0} === '(') {
|
699 |
+
$return['background-size'] .= substr($str_value[$i][$j], 1, -1) . ',';
|
700 |
+
} elseif (in_array($str_value[$i][$j], $pos, true) || is_numeric($str_value[$i][$j]{0}) || $str_value[$i][$j]{0} === null || $str_value[$i][$j]{0} === '-' || $str_value[$i][$j]{0} === '.') {
|
701 |
+
$return['background-position'] .= $str_value[$i][$j];
|
702 |
+
if (!$have['pos'])
|
703 |
+
$return['background-position'] .= ' '; else
|
704 |
+
$return['background-position'].= ',';
|
705 |
+
$have['pos'] = true;
|
706 |
+
} elseif (!$have['color']) {
|
707 |
+
$return['background-color'] .= $str_value[$i][$j] . ',';
|
708 |
+
$have['color'] = true;
|
709 |
+
}
|
710 |
+
}
|
711 |
+
}
|
712 |
+
|
713 |
+
foreach ($background_prop_default as $bg_prop => $default_value) {
|
714 |
+
if ($return[$bg_prop] !== null) {
|
715 |
+
$return[$bg_prop] = substr($return[$bg_prop], 0, -1) . $important;
|
716 |
+
}
|
717 |
+
else
|
718 |
+
$return[$bg_prop] = $default_value . $important;
|
719 |
+
}
|
720 |
+
return $return;
|
721 |
+
}
|
722 |
+
|
723 |
+
/**
|
724 |
+
* Merges all background properties
|
725 |
+
* @param array $input_css
|
726 |
+
* @return array
|
727 |
+
* @version 1.0
|
728 |
+
* @see dissolve_short_bg()
|
729 |
+
* @todo full CSS 3 compliance
|
730 |
+
*/
|
731 |
+
public function merge_bg($input_css) {
|
732 |
+
$background_prop_default = & $this->parser->data['csstidy']['background_prop_default'];
|
733 |
+
// Max number of background images. CSS3 not yet fully implemented
|
734 |
+
$number_of_values = @max(count($this->explode_ws(',', $input_css['background-image'])), count($this->explode_ws(',', $input_css['background-color'])), 1);
|
735 |
+
// Array with background images to check if BG image exists
|
736 |
+
$bg_img_array = @$this->explode_ws(',', $this->parser->gvw_important($input_css['background-image']));
|
737 |
+
$new_bg_value = '';
|
738 |
+
$important = '';
|
739 |
+
|
740 |
+
// if background properties is here and not empty, don't try anything
|
741 |
+
if (isset($input_css['background']) && $input_css['background'])
|
742 |
+
return $input_css;
|
743 |
+
|
744 |
+
for ($i = 0; $i < $number_of_values; $i++) {
|
745 |
+
foreach ($background_prop_default as $bg_property => $default_value) {
|
746 |
+
// Skip if property does not exist
|
747 |
+
if (!isset($input_css[$bg_property])) {
|
748 |
+
continue;
|
749 |
+
}
|
750 |
+
|
751 |
+
$cur_value = $input_css[$bg_property];
|
752 |
+
// skip all optimisation if gradient() somewhere
|
753 |
+
if (stripos($cur_value, 'gradient(') !== false)
|
754 |
+
return $input_css;
|
755 |
+
|
756 |
+
// Skip some properties if there is no background image
|
757 |
+
if ((!isset($bg_img_array[$i]) || $bg_img_array[$i] === 'none')
|
758 |
+
&& ($bg_property === 'background-size' || $bg_property === 'background-position'
|
759 |
+
|| $bg_property === 'background-attachment' || $bg_property === 'background-repeat')) {
|
760 |
+
continue;
|
761 |
+
}
|
762 |
+
|
763 |
+
// Remove !important
|
764 |
+
if ($this->parser->is_important($cur_value)) {
|
765 |
+
$important = ' !important';
|
766 |
+
$cur_value = $this->parser->gvw_important($cur_value);
|
767 |
+
}
|
768 |
+
|
769 |
+
// Do not add default values
|
770 |
+
if ($cur_value === $default_value) {
|
771 |
+
continue;
|
772 |
+
}
|
773 |
+
|
774 |
+
$temp = $this->explode_ws(',', $cur_value);
|
775 |
+
|
776 |
+
if (isset($temp[$i])) {
|
777 |
+
if ($bg_property === 'background-size') {
|
778 |
+
$new_bg_value .= '(' . $temp[$i] . ') ';
|
779 |
+
} else {
|
780 |
+
$new_bg_value .= $temp[$i] . ' ';
|
781 |
+
}
|
782 |
+
}
|
783 |
+
}
|
784 |
+
|
785 |
+
$new_bg_value = trim($new_bg_value);
|
786 |
+
if ($i != $number_of_values - 1)
|
787 |
+
$new_bg_value .= ',';
|
788 |
+
}
|
789 |
+
|
790 |
+
// Delete all background-properties
|
791 |
+
foreach ($background_prop_default as $bg_property => $default_value) {
|
792 |
+
unset($input_css[$bg_property]);
|
793 |
+
}
|
794 |
+
|
795 |
+
// Add new background property
|
796 |
+
if ($new_bg_value !== '')
|
797 |
+
$input_css['background'] = $new_bg_value . $important;
|
798 |
+
elseif(isset ($input_css['background']))
|
799 |
+
$input_css['background'] = 'none';
|
800 |
+
|
801 |
+
return $input_css;
|
802 |
+
}
|
803 |
+
|
804 |
+
/**
|
805 |
+
* Dissolve font property
|
806 |
+
* @param string $str_value
|
807 |
+
* @return array
|
808 |
+
* @version 1.3
|
809 |
+
* @see merge_font()
|
810 |
+
*/
|
811 |
+
public function dissolve_short_font($str_value) {
|
812 |
+
$font_prop_default = & $this->parser->data['csstidy']['font_prop_default'];
|
813 |
+
$font_weight = array('normal', 'bold', 'bolder', 'lighter', 100, 200, 300, 400, 500, 600, 700, 800, 900);
|
814 |
+
$font_variant = array('normal', 'small-caps');
|
815 |
+
$font_style = array('normal', 'italic', 'oblique');
|
816 |
+
$important = '';
|
817 |
+
$return = array('font-style' => null, 'font-variant' => null, 'font-weight' => null, 'font-size' => null, 'line-height' => null, 'font-family' => null);
|
818 |
+
|
819 |
+
if ($this->parser->is_important($str_value)) {
|
820 |
+
$important = '!important';
|
821 |
+
$str_value = $this->parser->gvw_important($str_value);
|
822 |
+
}
|
823 |
+
|
824 |
+
$have['style'] = false;
|
825 |
+
$have['variant'] = false;
|
826 |
+
$have['weight'] = false;
|
827 |
+
$have['size'] = false;
|
828 |
+
// Detects if font-family consists of several words w/o quotes
|
829 |
+
$multiwords = false;
|
830 |
+
|
831 |
+
// Workaround with multiple font-family
|
832 |
+
$str_value = $this->explode_ws(',', trim($str_value));
|
833 |
+
|
834 |
+
$str_value[0] = $this->explode_ws(' ', trim($str_value[0]));
|
835 |
+
|
836 |
+
for ($j = 0; $j < count($str_value[0]); $j++) {
|
837 |
+
if ($have['weight'] === false && in_array($str_value[0][$j], $font_weight)) {
|
838 |
+
$return['font-weight'] = $str_value[0][$j];
|
839 |
+
$have['weight'] = true;
|
840 |
+
} elseif ($have['variant'] === false && in_array($str_value[0][$j], $font_variant)) {
|
841 |
+
$return['font-variant'] = $str_value[0][$j];
|
842 |
+
$have['variant'] = true;
|
843 |
+
} elseif ($have['style'] === false && in_array($str_value[0][$j], $font_style)) {
|
844 |
+
$return['font-style'] = $str_value[0][$j];
|
845 |
+
$have['style'] = true;
|
846 |
+
} elseif ($have['size'] === false && (is_numeric($str_value[0][$j]{0}) || $str_value[0][$j]{0} === null || $str_value[0][$j]{0} === '.')) {
|
847 |
+
$size = $this->explode_ws('/', trim($str_value[0][$j]));
|
848 |
+
$return['font-size'] = $size[0];
|
849 |
+
if (isset($size[1])) {
|
850 |
+
$return['line-height'] = $size[1];
|
851 |
+
} else {
|
852 |
+
$return['line-height'] = ''; // don't add 'normal' !
|
853 |
+
}
|
854 |
+
$have['size'] = true;
|
855 |
+
} else {
|
856 |
+
if (isset($return['font-family'])) {
|
857 |
+
$return['font-family'] .= ' ' . $str_value[0][$j];
|
858 |
+
$multiwords = true;
|
859 |
+
} else {
|
860 |
+
$return['font-family'] = $str_value[0][$j];
|
861 |
+
}
|
862 |
+
}
|
863 |
+
}
|
864 |
+
// add quotes if we have several qords in font-family
|
865 |
+
if ($multiwords !== false) {
|
866 |
+
$return['font-family'] = '"' . $return['font-family'] . '"';
|
867 |
+
}
|
868 |
+
$i = 1;
|
869 |
+
while (isset($str_value[$i])) {
|
870 |
+
$return['font-family'] .= ',' . trim($str_value[$i]);
|
871 |
+
$i++;
|
872 |
+
}
|
873 |
+
|
874 |
+
// Fix for 100 and more font-size
|
875 |
+
if ($have['size'] === false && isset($return['font-weight']) &&
|
876 |
+
is_numeric($return['font-weight']{0})) {
|
877 |
+
$return['font-size'] = $return['font-weight'];
|
878 |
+
unset($return['font-weight']);
|
879 |
+
}
|
880 |
+
|
881 |
+
foreach ($font_prop_default as $font_prop => $default_value) {
|
882 |
+
if ($return[$font_prop] !== null) {
|
883 |
+
$return[$font_prop] = $return[$font_prop] . $important;
|
884 |
+
}
|
885 |
+
else
|
886 |
+
$return[$font_prop] = $default_value . $important;
|
887 |
+
}
|
888 |
+
return $return;
|
889 |
+
}
|
890 |
+
|
891 |
+
/**
|
892 |
+
* Merges all fonts properties
|
893 |
+
* @param array $input_css
|
894 |
+
* @return array
|
895 |
+
* @version 1.3
|
896 |
+
* @see dissolve_short_font()
|
897 |
+
*/
|
898 |
+
public function merge_font($input_css) {
|
899 |
+
$font_prop_default = & $this->parser->data['csstidy']['font_prop_default'];
|
900 |
+
$new_font_value = '';
|
901 |
+
$important = '';
|
902 |
+
// Skip if not font-family and font-size set
|
903 |
+
if (isset($input_css['font-family']) && isset($input_css['font-size']) && $input_css['font-family'] != 'inherit') {
|
904 |
+
// fix several words in font-family - add quotes
|
905 |
+
if (isset($input_css['font-family'])) {
|
906 |
+
$families = explode(',', $input_css['font-family']);
|
907 |
+
$result_families = array();
|
908 |
+
foreach ($families as $family) {
|
909 |
+
$family = trim($family);
|
910 |
+
$len = strlen($family);
|
911 |
+
if (strpos($family, ' ') &&
|
912 |
+
!(($family{0} === '"' && $family{$len - 1} === '"') ||
|
913 |
+
($family{0} === "'" && $family{$len - 1} === "'"))) {
|
914 |
+
$family = '"' . $family . '"';
|
915 |
+
}
|
916 |
+
$result_families[] = $family;
|
917 |
+
}
|
918 |
+
$input_css['font-family'] = implode(',', $result_families);
|
919 |
+
}
|
920 |
+
foreach ($font_prop_default as $font_property => $default_value) {
|
921 |
+
|
922 |
+
// Skip if property does not exist
|
923 |
+
if (!isset($input_css[$font_property])) {
|
924 |
+
continue;
|
925 |
+
}
|
926 |
+
|
927 |
+
$cur_value = $input_css[$font_property];
|
928 |
+
|
929 |
+
// Skip if default value is used
|
930 |
+
if ($cur_value === $default_value) {
|
931 |
+
continue;
|
932 |
+
}
|
933 |
+
|
934 |
+
// Remove !important
|
935 |
+
if ($this->parser->is_important($cur_value)) {
|
936 |
+
$important = '!important';
|
937 |
+
$cur_value = $this->parser->gvw_important($cur_value);
|
938 |
+
}
|
939 |
+
|
940 |
+
$new_font_value .= $cur_value;
|
941 |
+
// Add delimiter
|
942 |
+
$new_font_value .= ( $font_property === 'font-size' &&
|
943 |
+
isset($input_css['line-height'])) ? '/' : ' ';
|
944 |
+
}
|
945 |
+
|
946 |
+
$new_font_value = trim($new_font_value);
|
947 |
+
|
948 |
+
// Delete all font-properties
|
949 |
+
foreach ($font_prop_default as $font_property => $default_value) {
|
950 |
+
if ($font_property !== 'font' || !$new_font_value)
|
951 |
+
unset($input_css[$font_property]);
|
952 |
+
}
|
953 |
+
|
954 |
+
// Add new font property
|
955 |
+
if ($new_font_value !== '') {
|
956 |
+
$input_css['font'] = $new_font_value . $important;
|
957 |
+
}
|
958 |
+
}
|
959 |
+
|
960 |
+
return $input_css;
|
961 |
+
}
|
962 |
+
|
963 |
+
}
|
libs/CSSTidy/class.csstidy_print.php
ADDED
@@ -0,0 +1,446 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* CSSTidy - CSS Parser and Optimiser
|
5 |
+
*
|
6 |
+
* CSS Printing class
|
7 |
+
* This class prints CSS data generated by csstidy.
|
8 |
+
*
|
9 |
+
* Copyright 2005, 2006, 2007 Florian Schmitz
|
10 |
+
*
|
11 |
+
* This file is part of CSSTidy.
|
12 |
+
*
|
13 |
+
* CSSTidy is free software; you can redistribute it and/or modify
|
14 |
+
* it under the terms of the GNU Lesser General Public License as published by
|
15 |
+
* the Free Software Foundation; either version 2.1 of the License, or
|
16 |
+
* (at your option) any later version.
|
17 |
+
*
|
18 |
+
* CSSTidy is distributed in the hope that it will be useful,
|
19 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
21 |
+
* GNU Lesser General Public License for more details.
|
22 |
+
*
|
23 |
+
* You should have received a copy of the GNU Lesser General Public License
|
24 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
25 |
+
*
|
26 |
+
* @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
|
27 |
+
* @package csstidy
|
28 |
+
* @author Florian Schmitz (floele at gmail dot com) 2005-2007
|
29 |
+
* @author Brett Zamir (brettz9 at yahoo dot com) 2007
|
30 |
+
* @author Cedric Morin (cedric at yterium dot com) 2010-2012
|
31 |
+
*/
|
32 |
+
|
33 |
+
/**
|
34 |
+
* CSS Printing class
|
35 |
+
*
|
36 |
+
* This class prints CSS data generated by csstidy.
|
37 |
+
*
|
38 |
+
* @package csstidy
|
39 |
+
* @author Florian Schmitz (floele at gmail dot com) 2005-2006
|
40 |
+
* @version 1.1.0
|
41 |
+
*/
|
42 |
+
class csstidy_print {
|
43 |
+
|
44 |
+
/**
|
45 |
+
* csstidy object
|
46 |
+
* @var object
|
47 |
+
*/
|
48 |
+
public $parser;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Saves the input CSS string
|
52 |
+
* @var string
|
53 |
+
* @access private
|
54 |
+
*/
|
55 |
+
public $input_css = '';
|
56 |
+
/**
|
57 |
+
* Saves the formatted CSS string
|
58 |
+
* @var string
|
59 |
+
* @access public
|
60 |
+
*/
|
61 |
+
public $output_css = '';
|
62 |
+
/**
|
63 |
+
* Saves the formatted CSS string (plain text)
|
64 |
+
* @var string
|
65 |
+
* @access public
|
66 |
+
*/
|
67 |
+
public $output_css_plain = '';
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Constructor
|
71 |
+
* @param array $css contains the class csstidy
|
72 |
+
* @access private
|
73 |
+
* @version 1.0
|
74 |
+
*/
|
75 |
+
public function __construct($css) {
|
76 |
+
$this->parser = $css;
|
77 |
+
$this->css = & $css->css;
|
78 |
+
$this->template = & $css->template;
|
79 |
+
$this->tokens = & $css->tokens;
|
80 |
+
$this->charset = & $css->charset;
|
81 |
+
$this->import = & $css->import;
|
82 |
+
$this->namespace = & $css->namespace;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Resets output_css and output_css_plain (new css code)
|
87 |
+
* @access private
|
88 |
+
* @version 1.0
|
89 |
+
*/
|
90 |
+
public function _reset() {
|
91 |
+
$this->output_css = '';
|
92 |
+
$this->output_css_plain = '';
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Returns the CSS code as plain text
|
97 |
+
* @param string $default_media default @media to add to selectors without any @media
|
98 |
+
* @return string
|
99 |
+
* @access public
|
100 |
+
* @version 1.0
|
101 |
+
*/
|
102 |
+
public function plain($default_media='') {
|
103 |
+
$this->_print(true, $default_media);
|
104 |
+
return $this->output_css_plain;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Returns the formatted CSS code
|
109 |
+
* @param string $default_media default @media to add to selectors without any @media
|
110 |
+
* @return string
|
111 |
+
* @access public
|
112 |
+
* @version 1.0
|
113 |
+
*/
|
114 |
+
public function formatted($default_media='') {
|
115 |
+
$this->_print(false, $default_media);
|
116 |
+
return $this->output_css;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Returns the formatted CSS code to make a complete webpage
|
121 |
+
* @param string $doctype shorthand for the document type
|
122 |
+
* @param bool $externalcss indicates whether styles to be attached internally or as an external stylesheet
|
123 |
+
* @param string $title title to be added in the head of the document
|
124 |
+
* @param string $lang two-letter language code to be added to the output
|
125 |
+
* @return string
|
126 |
+
* @access public
|
127 |
+
* @version 1.4
|
128 |
+
*/
|
129 |
+
public function formatted_page($doctype='html5', $externalcss=true, $title='', $lang='en') {
|
130 |
+
switch ($doctype) {
|
131 |
+
case 'html5':
|
132 |
+
$doctype_output = '<!DOCTYPE html>';
|
133 |
+
break;
|
134 |
+
case 'xhtml1.0strict':
|
135 |
+
$doctype_output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
136 |
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
|
137 |
+
break;
|
138 |
+
case 'xhtml1.1':
|
139 |
+
default:
|
140 |
+
$doctype_output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
141 |
+
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
|
142 |
+
break;
|
143 |
+
}
|
144 |
+
|
145 |
+
$output = $cssparsed = '';
|
146 |
+
$this->output_css_plain = & $output;
|
147 |
+
|
148 |
+
$output .= $doctype_output . "\n" . '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="' . $lang . '"';
|
149 |
+
$output .= ( $doctype === 'xhtml1.1') ? '>' : ' lang="' . $lang . '">';
|
150 |
+
$output .= "\n<head>\n <title>$title</title>";
|
151 |
+
|
152 |
+
if ($externalcss) {
|
153 |
+
$output .= "\n <style type=\"text/css\">\n";
|
154 |
+
$cssparsed = file_get_contents('cssparsed.css');
|
155 |
+
$output .= $cssparsed; // Adds an invisible BOM or something, but not in css_optimised.php
|
156 |
+
$output .= "\n</style>";
|
157 |
+
} else {
|
158 |
+
$output .= "\n" . ' <link rel="stylesheet" type="text/css" href="cssparsed.css" />';
|
159 |
+
}
|
160 |
+
$output .= "\n</head>\n<body><code id=\"copytext\">";
|
161 |
+
$output .= $this->formatted();
|
162 |
+
$output .= '</code>' . "\n" . '</body></html>';
|
163 |
+
return $this->output_css_plain;
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Returns the formatted CSS Code and saves it into $this->output_css and $this->output_css_plain
|
168 |
+
* @param bool $plain plain text or not
|
169 |
+
* @param string $default_media default @media to add to selectors without any @media
|
170 |
+
* @access private
|
171 |
+
* @version 2.0
|
172 |
+
*/
|
173 |
+
public function _print($plain = false, $default_media='') {
|
174 |
+
if ($this->output_css && $this->output_css_plain) {
|
175 |
+
return;
|
176 |
+
}
|
177 |
+
|
178 |
+
$output = '';
|
179 |
+
if (!$this->parser->get_cfg('preserve_css')) {
|
180 |
+
$this->_convert_raw_css($default_media);
|
181 |
+
}
|
182 |
+
|
183 |
+
$template = & $this->template;
|
184 |
+
|
185 |
+
if ($plain) {
|
186 |
+
$template = array_map('strip_tags', $template);
|
187 |
+
}
|
188 |
+
|
189 |
+
if ($this->parser->get_cfg('timestamp')) {
|
190 |
+
array_unshift($this->tokens, array(COMMENT, ' CSSTidy ' . $this->parser->version . ': ' . date('r') . ' '));
|
191 |
+
}
|
192 |
+
|
193 |
+
if (!empty($this->charset)) {
|
194 |
+
$output .= $template[0] . '@charset ' . $template[5] . $this->charset . $template[6] . $template[13];
|
195 |
+
}
|
196 |
+
|
197 |
+
if (!empty($this->import)) {
|
198 |
+
for ($i = 0, $size = count($this->import); $i < $size; $i++) {
|
199 |
+
if (substr($this->import[$i], 0, 4) === 'url(' && substr($this->import[$i], -1, 1) === ')') {
|
200 |
+
$this->import[$i] = '"' . substr($this->import[$i], 4, -1) . '"';
|
201 |
+
$this->parser->log('Optimised @import : Removed "url("', 'Information');
|
202 |
+
}
|
203 |
+
else if (!preg_match('/^".+"$/',$this->import[$i])) {
|
204 |
+
// fixes a bug for @import ".." instead of the expected @import url("..")
|
205 |
+
// If it comes in due to @import ".." the "" will be missing and the output will become @import .. (which is an error)
|
206 |
+
$this->import[$i] = '"' . $this->import[$i] . '"';
|
207 |
+
}
|
208 |
+
|
209 |
+
$output .= $template[0] . '@import ' . $template[5] . $this->import[$i] . $template[6] . $template[13];
|
210 |
+
}
|
211 |
+
}
|
212 |
+
|
213 |
+
if (!empty($this->namespace)) {
|
214 |
+
if (($p=strpos($this->namespace,"url("))!==false && substr($this->namespace, -1, 1) === ')') {
|
215 |
+
$this->namespace = substr_replace($this->namespace,'"',$p,4);
|
216 |
+
$this->namespace = substr($this->namespace, 0, -1) . '"';
|
217 |
+
$this->parser->log('Optimised @namespace : Removed "url("', 'Information');
|
218 |
+
}
|
219 |
+
$output .= $template[0] . '@namespace ' . $template[5] . $this->namespace . $template[6] . $template[13];
|
220 |
+
}
|
221 |
+
|
222 |
+
$in_at_out = '';
|
223 |
+
$out = & $output;
|
224 |
+
|
225 |
+
foreach ($this->tokens as $key => $token) {
|
226 |
+
switch ($token[0]) {
|
227 |
+
case AT_START:
|
228 |
+
$out .= $template[0] . $this->_htmlsp($token[1], $plain) . $template[1];
|
229 |
+
$out = & $in_at_out;
|
230 |
+
break;
|
231 |
+
|
232 |
+
case SEL_START:
|
233 |
+
if ($this->parser->get_cfg('lowercase_s'))
|
234 |
+
$token[1] = strtolower($token[1]);
|
235 |
+
$out .= ( $token[1]{0} !== '@') ? $template[2] . $this->_htmlsp($token[1], $plain) : $template[0] . $this->_htmlsp($token[1], $plain);
|
236 |
+
$out .= $template[3];
|
237 |
+
break;
|
238 |
+
|
239 |
+
case PROPERTY:
|
240 |
+
if ($this->parser->get_cfg('case_properties') === 2) {
|
241 |
+
$token[1] = strtoupper($token[1]);
|
242 |
+
} elseif ($this->parser->get_cfg('case_properties') === 1) {
|
243 |
+
$token[1] = strtolower($token[1]);
|
244 |
+
}
|
245 |
+
$out .= $template[4] . $this->_htmlsp($token[1], $plain) . ':' . $template[5];
|
246 |
+
break;
|
247 |
+
|
248 |
+
case VALUE:
|
249 |
+
$out .= $this->_htmlsp($token[1], $plain);
|
250 |
+
if ($this->_seeknocomment($key, 1) == SEL_END && $this->parser->get_cfg('remove_last_;')) {
|
251 |
+
$out .= str_replace(';', '', $template[6]);
|
252 |
+
} else {
|
253 |
+
$out .= $template[6];
|
254 |
+
}
|
255 |
+
break;
|
256 |
+
|
257 |
+
case SEL_END:
|
258 |
+
$out .= $template[7];
|
259 |
+
if ($this->_seeknocomment($key, 1) != AT_END)
|
260 |
+
$out .= $template[8];
|
261 |
+
break;
|
262 |
+
|
263 |
+
case AT_END:
|
264 |
+
$out = & $output;
|
265 |
+
$in_at_out = str_replace("\n\n", "\r\n", $in_at_out); // don't fill empty lines
|
266 |
+
$in_at_out = str_replace("\n", "\n" . $template[10], $in_at_out);
|
267 |
+
$in_at_out = str_replace("\r\n", "\n\n", $in_at_out);
|
268 |
+
$out .= $template[10] . $in_at_out . $template[9];
|
269 |
+
$in_at_out = '';
|
270 |
+
break;
|
271 |
+
|
272 |
+
case COMMENT:
|
273 |
+
$out .= $template[11] . '/*' . $this->_htmlsp($token[1], $plain) . '*/' . $template[12];
|
274 |
+
break;
|
275 |
+
}
|
276 |
+
}
|
277 |
+
|
278 |
+
$output = trim($output);
|
279 |
+
|
280 |
+
if (!$plain) {
|
281 |
+
$this->output_css = $output;
|
282 |
+
$this->_print(true);
|
283 |
+
} else {
|
284 |
+
// If using spaces in the template, don't want these to appear in the plain output
|
285 |
+
$this->output_css_plain = str_replace(' ', '', $output);
|
286 |
+
}
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Gets the next token type which is $move away from $key, excluding comments
|
291 |
+
* @param integer $key current position
|
292 |
+
* @param integer $move move this far
|
293 |
+
* @return mixed a token type
|
294 |
+
* @access private
|
295 |
+
* @version 1.0
|
296 |
+
*/
|
297 |
+
public function _seeknocomment($key, $move) {
|
298 |
+
$go = ($move > 0) ? 1 : -1;
|
299 |
+
for ($i = $key + 1; abs($key - $i) - 1 < abs($move); $i += $go) {
|
300 |
+
if (!isset($this->tokens[$i])) {
|
301 |
+
return;
|
302 |
+
}
|
303 |
+
if ($this->tokens[$i][0] == COMMENT) {
|
304 |
+
$move += 1;
|
305 |
+
continue;
|
306 |
+
}
|
307 |
+
return $this->tokens[$i][0];
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Converts $this->css array to a raw array ($this->tokens)
|
313 |
+
* @param string $default_media default @media to add to selectors without any @media
|
314 |
+
* @access private
|
315 |
+
* @version 1.0
|
316 |
+
*/
|
317 |
+
public function _convert_raw_css($default_media='') {
|
318 |
+
$this->tokens = array();
|
319 |
+
$sort_selectors = $this->parser->get_cfg('sort_selectors');
|
320 |
+
$sort_properties = $this->parser->get_cfg('sort_properties');
|
321 |
+
|
322 |
+
foreach ($this->css as $medium => $val) {
|
323 |
+
if ($sort_selectors)
|
324 |
+
ksort($val);
|
325 |
+
if (intval($medium) < DEFAULT_AT) {
|
326 |
+
// un medium vide (contenant @font-face ou autre @) ne produit aucun conteneur
|
327 |
+
if (strlen(trim($medium))) {
|
328 |
+
$this->parser->_add_token(AT_START, $medium, true);
|
329 |
+
}
|
330 |
+
} elseif ($default_media) {
|
331 |
+
$this->parser->_add_token(AT_START, $default_media, true);
|
332 |
+
}
|
333 |
+
|
334 |
+
foreach ($val as $selector => $vali) {
|
335 |
+
if ($sort_properties)
|
336 |
+
ksort($vali);
|
337 |
+
$this->parser->_add_token(SEL_START, $selector, true);
|
338 |
+
|
339 |
+
$invalid = array(
|
340 |
+
'*' => array(), // IE7 hacks first
|
341 |
+
'_' => array(), // IE6 hacks
|
342 |
+
'/' => array(), // IE6 hacks
|
343 |
+
'-' => array() // IE6 hacks
|
344 |
+
);
|
345 |
+
foreach ($vali as $property => $valj) {
|
346 |
+
if (strncmp($property,"//",2)!==0) {
|
347 |
+
$matches = array();
|
348 |
+
if ($sort_properties && preg_match('/^(\*|_|\/|-)(?!(ms|moz|o\b|xv|atsc|wap|khtml|webkit|ah|hp|ro|rim|tc)-)/', $property, $matches)) {
|
349 |
+
$invalid[$matches[1]][$property] = $valj;
|
350 |
+
} else {
|
351 |
+
$this->parser->_add_token(PROPERTY, $property, true);
|
352 |
+
$this->parser->_add_token(VALUE, $valj, true);
|
353 |
+
}
|
354 |
+
}
|
355 |
+
}
|
356 |
+
foreach ($invalid as $prefix => $props) {
|
357 |
+
foreach ($props as $property => $valj) {
|
358 |
+
$this->parser->_add_token(PROPERTY, $property, true);
|
359 |
+
$this->parser->_add_token(VALUE, $valj, true);
|
360 |
+
}
|
361 |
+
}
|
362 |
+
$this->parser->_add_token(SEL_END, $selector, true);
|
363 |
+
}
|
364 |
+
|
365 |
+
if (intval($medium) < DEFAULT_AT) {
|
366 |
+
// un medium vide (contenant @font-face ou autre @) ne produit aucun conteneur
|
367 |
+
if (strlen(trim($medium))) {
|
368 |
+
$this->parser->_add_token(AT_END, $medium, true);
|
369 |
+
}
|
370 |
+
} elseif ($default_media) {
|
371 |
+
$this->parser->_add_token(AT_END, $default_media, true);
|
372 |
+
}
|
373 |
+
}
|
374 |
+
}
|
375 |
+
|
376 |
+
/**
|
377 |
+
* Same as htmlspecialchars, only that chars are not replaced if $plain !== true. This makes print_code() cleaner.
|
378 |
+
* @param string $string
|
379 |
+
* @param bool $plain
|
380 |
+
* @return string
|
381 |
+
* @see csstidy_print::_print()
|
382 |
+
* @access private
|
383 |
+
* @version 1.0
|
384 |
+
*/
|
385 |
+
public function _htmlsp($string, $plain) {
|
386 |
+
if (!$plain) {
|
387 |
+
return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
|
388 |
+
}
|
389 |
+
return $string;
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
* Get compression ratio
|
394 |
+
* @access public
|
395 |
+
* @return float
|
396 |
+
* @version 1.2
|
397 |
+
*/
|
398 |
+
public function get_ratio() {
|
399 |
+
if (!$this->output_css_plain) {
|
400 |
+
$this->formatted();
|
401 |
+
}
|
402 |
+
return round((strlen($this->input_css) - strlen($this->output_css_plain)) / strlen($this->input_css), 3) * 100;
|
403 |
+
}
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Get difference between the old and new code in bytes and prints the code if necessary.
|
407 |
+
* @access public
|
408 |
+
* @return string
|
409 |
+
* @version 1.1
|
410 |
+
*/
|
411 |
+
public function get_diff() {
|
412 |
+
if (!$this->output_css_plain) {
|
413 |
+
$this->formatted();
|
414 |
+
}
|
415 |
+
|
416 |
+
$diff = strlen($this->output_css_plain) - strlen($this->input_css);
|
417 |
+
|
418 |
+
if ($diff > 0) {
|
419 |
+
return '+' . $diff;
|
420 |
+
} elseif ($diff == 0) {
|
421 |
+
return '+-' . $diff;
|
422 |
+
}
|
423 |
+
|
424 |
+
return $diff;
|
425 |
+
}
|
426 |
+
|
427 |
+
/**
|
428 |
+
* Get the size of either input or output CSS in KB
|
429 |
+
* @param string $loc default is "output"
|
430 |
+
* @access public
|
431 |
+
* @return integer
|
432 |
+
* @version 1.0
|
433 |
+
*/
|
434 |
+
public function size($loc = 'output') {
|
435 |
+
if ($loc === 'output' && !$this->output_css) {
|
436 |
+
$this->formatted();
|
437 |
+
}
|
438 |
+
|
439 |
+
if ($loc === 'input') {
|
440 |
+
return (strlen($this->input_css) / 1000);
|
441 |
+
} else {
|
442 |
+
return (strlen($this->output_css_plain) / 1000);
|
443 |
+
}
|
444 |
+
}
|
445 |
+
|
446 |
+
}
|
libs/CSSTidy/data.inc.php
ADDED
@@ -0,0 +1,646 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Various CSS Data for CSSTidy
|
4 |
+
*
|
5 |
+
* This file is part of CSSTidy.
|
6 |
+
*
|
7 |
+
* CSSTidy is free software; you can redistribute it and/or modify
|
8 |
+
* it under the terms of the GNU General Public License as published by
|
9 |
+
* the Free Software Foundation; either version 2 of the License, or
|
10 |
+
* (at your option) any later version.
|
11 |
+
*
|
12 |
+
* CSSTidy is distributed in the hope that it will be useful,
|
13 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15 |
+
* GNU General Public License for more details.
|
16 |
+
*
|
17 |
+
* You should have received a copy of the GNU General Public License
|
18 |
+
* along with CSSTidy; if not, write to the Free Software
|
19 |
+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
20 |
+
*
|
21 |
+
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
22 |
+
* @package csstidy
|
23 |
+
* @author Florian Schmitz (floele at gmail dot com) 2005
|
24 |
+
* @author Nikolay Matsievsky (speed at webo dot name) 2010
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* All whitespace allowed in CSS
|
29 |
+
*
|
30 |
+
* @global array $data['csstidy']['whitespace']
|
31 |
+
* @version 1.0
|
32 |
+
*/
|
33 |
+
$data['csstidy']['whitespace'] = array(' ',"\n","\t","\r","\x0B");
|
34 |
+
|
35 |
+
/**
|
36 |
+
* All CSS tokens used by csstidy
|
37 |
+
*
|
38 |
+
* @global string $data['csstidy']['tokens']
|
39 |
+
* @version 1.0
|
40 |
+
*/
|
41 |
+
$data['csstidy']['tokens'] = '/@}{;:=\'"(,\\!$%&)*+.<>?[]^`|~';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* All CSS units (CSS 3 units included)
|
45 |
+
*
|
46 |
+
* @see compress_numbers()
|
47 |
+
* @global array $data['csstidy']['units']
|
48 |
+
* @version 1.0
|
49 |
+
*/
|
50 |
+
$data['csstidy']['units'] = array('in','cm','mm','pt','pc','px','rem','em','%','ex','gd','vw','vh','vm','deg','grad','rad','turn','ms','s','khz','hz','ch','vmin','vmax','dpi','dpcm','dppx');
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Available at-rules
|
54 |
+
*
|
55 |
+
* @global array $data['csstidy']['at_rules']
|
56 |
+
* @version 1.1
|
57 |
+
*/
|
58 |
+
$data['csstidy']['at_rules'] = array('page' => 'is','font-face' => 'atis','charset' => 'iv', 'import' => 'iv','namespace' => 'iv','media' => 'at','keyframes' => 'at','-moz-keyframes' => 'at','-o-keyframes' => 'at','-webkit-keyframes' => 'at','-ms-keyframes' => 'at');
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Properties that need a value with unit
|
62 |
+
*
|
63 |
+
* @todo CSS3 properties
|
64 |
+
* @see compress_numbers();
|
65 |
+
* @global array $data['csstidy']['unit_values']
|
66 |
+
* @version 1.2
|
67 |
+
*/
|
68 |
+
$data['csstidy']['unit_values'] = array ('background', 'background-position', 'background-size', 'border', 'border-top', 'border-right', 'border-bottom', 'border-left', 'border-width',
|
69 |
+
'border-top-width', 'border-right-width', 'border-left-width', 'border-bottom-width', 'bottom', 'border-spacing', 'column-gap', 'column-width',
|
70 |
+
'font-size', 'height', 'left', 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', 'max-height',
|
71 |
+
'max-width', 'min-height', 'min-width', 'outline', 'outline-width', 'padding', 'padding-top', 'padding-right',
|
72 |
+
'padding-bottom', 'padding-left', 'perspective', 'right', 'top', 'text-indent', 'letter-spacing', 'word-spacing', 'width');
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Properties that allow <color> as value
|
76 |
+
*
|
77 |
+
* @todo CSS3 properties
|
78 |
+
* @see compress_numbers();
|
79 |
+
* @global array $data['csstidy']['color_values']
|
80 |
+
* @version 1.0
|
81 |
+
*/
|
82 |
+
$data['csstidy']['color_values'] = array();
|
83 |
+
$data['csstidy']['color_values'][] = 'background-color';
|
84 |
+
$data['csstidy']['color_values'][] = 'border-color';
|
85 |
+
$data['csstidy']['color_values'][] = 'border-top-color';
|
86 |
+
$data['csstidy']['color_values'][] = 'border-right-color';
|
87 |
+
$data['csstidy']['color_values'][] = 'border-bottom-color';
|
88 |
+
$data['csstidy']['color_values'][] = 'border-left-color';
|
89 |
+
$data['csstidy']['color_values'][] = 'color';
|
90 |
+
$data['csstidy']['color_values'][] = 'outline-color';
|
91 |
+
$data['csstidy']['color_values'][] = 'column-rule-color';
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Default values for the background properties
|
95 |
+
*
|
96 |
+
* @todo Possibly property names will change during CSS3 development
|
97 |
+
* @global array $data['csstidy']['background_prop_default']
|
98 |
+
* @see dissolve_short_bg()
|
99 |
+
* @see merge_bg()
|
100 |
+
* @version 1.0
|
101 |
+
*/
|
102 |
+
$data['csstidy']['background_prop_default'] = array();
|
103 |
+
$data['csstidy']['background_prop_default']['background-image'] = 'none';
|
104 |
+
$data['csstidy']['background_prop_default']['background-size'] = 'auto';
|
105 |
+
$data['csstidy']['background_prop_default']['background-repeat'] = 'repeat';
|
106 |
+
$data['csstidy']['background_prop_default']['background-position'] = '0 0';
|
107 |
+
$data['csstidy']['background_prop_default']['background-attachment'] = 'scroll';
|
108 |
+
$data['csstidy']['background_prop_default']['background-clip'] = 'border';
|
109 |
+
$data['csstidy']['background_prop_default']['background-origin'] = 'padding';
|
110 |
+
$data['csstidy']['background_prop_default']['background-color'] = 'transparent';
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Default values for the font properties
|
114 |
+
*
|
115 |
+
* @global array $data['csstidy']['font_prop_default']
|
116 |
+
* @see merge_fonts()
|
117 |
+
* @version 1.3
|
118 |
+
*/
|
119 |
+
$data['csstidy']['font_prop_default'] = array();
|
120 |
+
$data['csstidy']['font_prop_default']['font-style'] = 'normal';
|
121 |
+
$data['csstidy']['font_prop_default']['font-variant'] = 'normal';
|
122 |
+
$data['csstidy']['font_prop_default']['font-weight'] = 'normal';
|
123 |
+
$data['csstidy']['font_prop_default']['font-size'] = '';
|
124 |
+
$data['csstidy']['font_prop_default']['line-height'] = '';
|
125 |
+
$data['csstidy']['font_prop_default']['font-family'] = '';
|
126 |
+
|
127 |
+
/**
|
128 |
+
* A list of non-W3C color names which get replaced by their hex-codes
|
129 |
+
*
|
130 |
+
* @global array $data['csstidy']['replace_colors']
|
131 |
+
* @see cut_color()
|
132 |
+
* @version 1.0
|
133 |
+
*/
|
134 |
+
$data['csstidy']['replace_colors'] = array();
|
135 |
+
$data['csstidy']['replace_colors']['aliceblue'] = '#f0f8ff';
|
136 |
+
$data['csstidy']['replace_colors']['antiquewhite'] = '#faebd7';
|
137 |
+
$data['csstidy']['replace_colors']['aquamarine'] = '#7fffd4';
|
138 |
+
$data['csstidy']['replace_colors']['azure'] = '#f0ffff';
|
139 |
+
$data['csstidy']['replace_colors']['beige'] = '#f5f5dc';
|
140 |
+
$data['csstidy']['replace_colors']['bisque'] = '#ffe4c4';
|
141 |
+
$data['csstidy']['replace_colors']['blanchedalmond'] = '#ffebcd';
|
142 |
+
$data['csstidy']['replace_colors']['blueviolet'] = '#8a2be2';
|
143 |
+
$data['csstidy']['replace_colors']['brown'] = '#a52a2a';
|
144 |
+
$data['csstidy']['replace_colors']['burlywood'] = '#deb887';
|
145 |
+
$data['csstidy']['replace_colors']['cadetblue'] = '#5f9ea0';
|
146 |
+
$data['csstidy']['replace_colors']['chartreuse'] = '#7fff00';
|
147 |
+
$data['csstidy']['replace_colors']['chocolate'] = '#d2691e';
|
148 |
+
$data['csstidy']['replace_colors']['coral'] = '#ff7f50';
|
149 |
+
$data['csstidy']['replace_colors']['cornflowerblue'] = '#6495ed';
|
150 |
+
$data['csstidy']['replace_colors']['cornsilk'] = '#fff8dc';
|
151 |
+
$data['csstidy']['replace_colors']['crimson'] = '#dc143c';
|
152 |
+
$data['csstidy']['replace_colors']['cyan'] = '#00ffff';
|
153 |
+
$data['csstidy']['replace_colors']['darkblue'] = '#00008b';
|
154 |
+
$data['csstidy']['replace_colors']['darkcyan'] = '#008b8b';
|
155 |
+
$data['csstidy']['replace_colors']['darkgoldenrod'] = '#b8860b';
|
156 |
+
$data['csstidy']['replace_colors']['darkgray'] = '#a9a9a9';
|
157 |
+
$data['csstidy']['replace_colors']['darkgreen'] = '#006400';
|
158 |
+
$data['csstidy']['replace_colors']['darkkhaki'] = '#bdb76b';
|
159 |
+
$data['csstidy']['replace_colors']['darkmagenta'] = '#8b008b';
|
160 |
+
$data['csstidy']['replace_colors']['darkolivegreen'] = '#556b2f';
|
161 |
+
$data['csstidy']['replace_colors']['darkorange'] = '#ff8c00';
|
162 |
+
$data['csstidy']['replace_colors']['darkorchid'] = '#9932cc';
|
163 |
+
$data['csstidy']['replace_colors']['darkred'] = '#8b0000';
|
164 |
+
$data['csstidy']['replace_colors']['darksalmon'] = '#e9967a';
|
165 |
+
$data['csstidy']['replace_colors']['darkseagreen'] = '#8fbc8f';
|
166 |
+
$data['csstidy']['replace_colors']['darkslateblue'] = '#483d8b';
|
167 |
+
$data['csstidy']['replace_colors']['darkslategray'] = '#2f4f4f';
|
168 |
+
$data['csstidy']['replace_colors']['darkturquoise'] = '#00ced1';
|
169 |
+
$data['csstidy']['replace_colors']['darkviolet'] = '#9400d3';
|
170 |
+
$data['csstidy']['replace_colors']['deeppink'] = '#ff1493';
|
171 |
+
$data['csstidy']['replace_colors']['deepskyblue'] = '#00bfff';
|
172 |
+
$data['csstidy']['replace_colors']['dimgray'] = '#696969';
|
173 |
+
$data['csstidy']['replace_colors']['dodgerblue'] = '#1e90ff';
|
174 |
+
$data['csstidy']['replace_colors']['feldspar'] = '#d19275';
|
175 |
+
$data['csstidy']['replace_colors']['firebrick'] = '#b22222';
|
176 |
+
$data['csstidy']['replace_colors']['floralwhite'] = '#fffaf0';
|
177 |
+
$data['csstidy']['replace_colors']['forestgreen'] = '#228b22';
|
178 |
+
$data['csstidy']['replace_colors']['gainsboro'] = '#dcdcdc';
|
179 |
+
$data['csstidy']['replace_colors']['ghostwhite'] = '#f8f8ff';
|
180 |
+
$data['csstidy']['replace_colors']['gold'] = '#ffd700';
|
181 |
+
$data['csstidy']['replace_colors']['goldenrod'] = '#daa520';
|
182 |
+
$data['csstidy']['replace_colors']['greenyellow'] = '#adff2f';
|
183 |
+
$data['csstidy']['replace_colors']['honeydew'] = '#f0fff0';
|
184 |
+
$data['csstidy']['replace_colors']['hotpink'] = '#ff69b4';
|
185 |
+
$data['csstidy']['replace_colors']['indianred'] = '#cd5c5c';
|
186 |
+
$data['csstidy']['replace_colors']['indigo'] = '#4b0082';
|
187 |
+
$data['csstidy']['replace_colors']['ivory'] = '#fffff0';
|
188 |
+
$data['csstidy']['replace_colors']['khaki'] = '#f0e68c';
|
189 |
+
$data['csstidy']['replace_colors']['lavender'] = '#e6e6fa';
|
190 |
+
$data['csstidy']['replace_colors']['lavenderblush'] = '#fff0f5';
|
191 |
+
$data['csstidy']['replace_colors']['lawngreen'] = '#7cfc00';
|
192 |
+
$data['csstidy']['replace_colors']['lemonchiffon'] = '#fffacd';
|
193 |
+
$data['csstidy']['replace_colors']['lightblue'] = '#add8e6';
|
194 |
+
$data['csstidy']['replace_colors']['lightcoral'] = '#f08080';
|
195 |
+
$data['csstidy']['replace_colors']['lightcyan'] = '#e0ffff';
|
196 |
+
$data['csstidy']['replace_colors']['lightgoldenrodyellow'] = '#fafad2';
|
197 |
+
$data['csstidy']['replace_colors']['lightgrey'] = '#d3d3d3';
|
198 |
+
$data['csstidy']['replace_colors']['lightgreen'] = '#90ee90';
|
199 |
+
$data['csstidy']['replace_colors']['lightpink'] = '#ffb6c1';
|
200 |
+
$data['csstidy']['replace_colors']['lightsalmon'] = '#ffa07a';
|
201 |
+
$data['csstidy']['replace_colors']['lightseagreen'] = '#20b2aa';
|
202 |
+
$data['csstidy']['replace_colors']['lightskyblue'] = '#87cefa';
|
203 |
+
$data['csstidy']['replace_colors']['lightslateblue'] = '#8470ff';
|
204 |
+
$data['csstidy']['replace_colors']['lightslategray'] = '#778899';
|
205 |
+
$data['csstidy']['replace_colors']['lightsteelblue'] = '#b0c4de';
|
206 |
+
$data['csstidy']['replace_colors']['lightyellow'] = '#ffffe0';
|
207 |
+
$data['csstidy']['replace_colors']['limegreen'] = '#32cd32';
|
208 |
+
$data['csstidy']['replace_colors']['linen'] = '#faf0e6';
|
209 |
+
$data['csstidy']['replace_colors']['magenta'] = '#ff00ff';
|
210 |
+
$data['csstidy']['replace_colors']['mediumaquamarine'] = '#66cdaa';
|
211 |
+
$data['csstidy']['replace_colors']['mediumblue'] = '#0000cd';
|
212 |
+
$data['csstidy']['replace_colors']['mediumorchid'] = '#ba55d3';
|
213 |
+
$data['csstidy']['replace_colors']['mediumpurple'] = '#9370d8';
|
214 |
+
$data['csstidy']['replace_colors']['mediumseagreen'] = '#3cb371';
|
215 |
+
$data['csstidy']['replace_colors']['mediumslateblue'] = '#7b68ee';
|
216 |
+
$data['csstidy']['replace_colors']['mediumspringgreen'] = '#00fa9a';
|
217 |
+
$data['csstidy']['replace_colors']['mediumturquoise'] = '#48d1cc';
|
218 |
+
$data['csstidy']['replace_colors']['mediumvioletred'] = '#c71585';
|
219 |
+
$data['csstidy']['replace_colors']['midnightblue'] = '#191970';
|
220 |
+
$data['csstidy']['replace_colors']['mintcream'] = '#f5fffa';
|
221 |
+
$data['csstidy']['replace_colors']['mistyrose'] = '#ffe4e1';
|
222 |
+
$data['csstidy']['replace_colors']['moccasin'] = '#ffe4b5';
|
223 |
+
$data['csstidy']['replace_colors']['navajowhite'] = '#ffdead';
|
224 |
+
$data['csstidy']['replace_colors']['oldlace'] = '#fdf5e6';
|
225 |
+
$data['csstidy']['replace_colors']['olivedrab'] = '#6b8e23';
|
226 |
+
$data['csstidy']['replace_colors']['orangered'] = '#ff4500';
|
227 |
+
$data['csstidy']['replace_colors']['orchid'] = '#da70d6';
|
228 |
+
$data['csstidy']['replace_colors']['palegoldenrod'] = '#eee8aa';
|
229 |
+
$data['csstidy']['replace_colors']['palegreen'] = '#98fb98';
|
230 |
+
$data['csstidy']['replace_colors']['paleturquoise'] = '#afeeee';
|
231 |
+
$data['csstidy']['replace_colors']['palevioletred'] = '#d87093';
|
232 |
+
$data['csstidy']['replace_colors']['papayawhip'] = '#ffefd5';
|
233 |
+
$data['csstidy']['replace_colors']['peachpuff'] = '#ffdab9';
|
234 |
+
$data['csstidy']['replace_colors']['peru'] = '#cd853f';
|
235 |
+
$data['csstidy']['replace_colors']['pink'] = '#ffc0cb';
|
236 |
+
$data['csstidy']['replace_colors']['plum'] = '#dda0dd';
|
237 |
+
$data['csstidy']['replace_colors']['powderblue'] = '#b0e0e6';
|
238 |
+
$data['csstidy']['replace_colors']['rosybrown'] = '#bc8f8f';
|
239 |
+
$data['csstidy']['replace_colors']['royalblue'] = '#4169e1';
|
240 |
+
$data['csstidy']['replace_colors']['saddlebrown'] = '#8b4513';
|
241 |
+
$data['csstidy']['replace_colors']['salmon'] = '#fa8072';
|
242 |
+
$data['csstidy']['replace_colors']['sandybrown'] = '#f4a460';
|
243 |
+
$data['csstidy']['replace_colors']['seagreen'] = '#2e8b57';
|
244 |
+
$data['csstidy']['replace_colors']['seashell'] = '#fff5ee';
|
245 |
+
$data['csstidy']['replace_colors']['sienna'] = '#a0522d';
|
246 |
+
$data['csstidy']['replace_colors']['skyblue'] = '#87ceeb';
|
247 |
+
$data['csstidy']['replace_colors']['slateblue'] = '#6a5acd';
|
248 |
+
$data['csstidy']['replace_colors']['slategray'] = '#708090';
|
249 |
+
$data['csstidy']['replace_colors']['snow'] = '#fffafa';
|
250 |
+
$data['csstidy']['replace_colors']['springgreen'] = '#00ff7f';
|
251 |
+
$data['csstidy']['replace_colors']['steelblue'] = '#4682b4';
|
252 |
+
$data['csstidy']['replace_colors']['tan'] = '#d2b48c';
|
253 |
+
$data['csstidy']['replace_colors']['thistle'] = '#d8bfd8';
|
254 |
+
$data['csstidy']['replace_colors']['tomato'] = '#ff6347';
|
255 |
+
$data['csstidy']['replace_colors']['turquoise'] = '#40e0d0';
|
256 |
+
$data['csstidy']['replace_colors']['violet'] = '#ee82ee';
|
257 |
+
$data['csstidy']['replace_colors']['violetred'] = '#d02090';
|
258 |
+
$data['csstidy']['replace_colors']['wheat'] = '#f5deb3';
|
259 |
+
$data['csstidy']['replace_colors']['whitesmoke'] = '#f5f5f5';
|
260 |
+
$data['csstidy']['replace_colors']['yellowgreen'] = '#9acd32';
|
261 |
+
|
262 |
+
/**
|
263 |
+
* A list of all shorthand properties that are devided into four properties and/or have four subvalues
|
264 |
+
*
|
265 |
+
* @global array $data['csstidy']['shorthands']
|
266 |
+
* @todo Are there new ones in CSS3?
|
267 |
+
* @see dissolve_4value_shorthands()
|
268 |
+
* @see merge_4value_shorthands()
|
269 |
+
* @version 1.0
|
270 |
+
*/
|
271 |
+
$data['csstidy']['shorthands'] = array();
|
272 |
+
$data['csstidy']['shorthands']['border-color'] = array('border-top-color','border-right-color','border-bottom-color','border-left-color');
|
273 |
+
$data['csstidy']['shorthands']['border-style'] = array('border-top-style','border-right-style','border-bottom-style','border-left-style');
|
274 |
+
$data['csstidy']['shorthands']['border-width'] = array('border-top-width','border-right-width','border-bottom-width','border-left-width');
|
275 |
+
$data['csstidy']['shorthands']['margin'] = array('margin-top','margin-right','margin-bottom','margin-left');
|
276 |
+
$data['csstidy']['shorthands']['padding'] = array('padding-top','padding-right','padding-bottom','padding-left');
|
277 |
+
$data['csstidy']['shorthands']['-moz-border-radius'] = 0;
|
278 |
+
|
279 |
+
/**
|
280 |
+
* All CSS Properties. Needed for csstidy::property_is_next()
|
281 |
+
*
|
282 |
+
* @global array $data['csstidy']['all_properties']
|
283 |
+
* @version 1.1
|
284 |
+
* @see csstidy::property_is_next()
|
285 |
+
*/
|
286 |
+
$data['csstidy']['all_properties']['alignment-adjust'] = 'CSS3.0';
|
287 |
+
$data['csstidy']['all_properties']['alignment-baseline'] = 'CSS3.0';
|
288 |
+
$data['csstidy']['all_properties']['animation'] = 'CSS3.0';
|
289 |
+
$data['csstidy']['all_properties']['animation-delay'] = 'CSS3.0';
|
290 |
+
$data['csstidy']['all_properties']['animation-direction'] = 'CSS3.0';
|
291 |
+
$data['csstidy']['all_properties']['animation-duration'] = 'CSS3.0';
|
292 |
+
$data['csstidy']['all_properties']['animation-iteration-count'] = 'CSS3.0';
|
293 |
+
$data['csstidy']['all_properties']['animation-name'] = 'CSS3.0';
|
294 |
+
$data['csstidy']['all_properties']['animation-play-state'] = 'CSS3.0';
|
295 |
+
$data['csstidy']['all_properties']['animation-timing-function'] = 'CSS3.0';
|
296 |
+
$data['csstidy']['all_properties']['appearance'] = 'CSS3.0';
|
297 |
+
$data['csstidy']['all_properties']['azimuth'] = 'CSS2.0,CSS2.1,CSS3.0';
|
298 |
+
$data['csstidy']['all_properties']['backface-visibility'] = 'CSS3.0';
|
299 |
+
$data['csstidy']['all_properties']['background'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
300 |
+
$data['csstidy']['all_properties']['background-attachment'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
301 |
+
$data['csstidy']['all_properties']['background-clip'] = 'CSS3.0';
|
302 |
+
$data['csstidy']['all_properties']['background-color'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
303 |
+
$data['csstidy']['all_properties']['background-image'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
304 |
+
$data['csstidy']['all_properties']['background-origin'] = 'CSS3.0';
|
305 |
+
$data['csstidy']['all_properties']['background-position'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
306 |
+
$data['csstidy']['all_properties']['background-repeat'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
307 |
+
$data['csstidy']['all_properties']['background-size'] = 'CSS3.0';
|
308 |
+
$data['csstidy']['all_properties']['baseline-shift'] = 'CSS3.0';
|
309 |
+
$data['csstidy']['all_properties']['binding'] = 'CSS3.0';
|
310 |
+
$data['csstidy']['all_properties']['bleed'] = 'CSS3.0';
|
311 |
+
$data['csstidy']['all_properties']['bookmark-label'] = 'CSS3.0';
|
312 |
+
$data['csstidy']['all_properties']['bookmark-level'] = 'CSS3.0';
|
313 |
+
$data['csstidy']['all_properties']['bookmark-state'] = 'CSS3.0';
|
314 |
+
$data['csstidy']['all_properties']['bookmark-target'] = 'CSS3.0';
|
315 |
+
$data['csstidy']['all_properties']['border'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
316 |
+
$data['csstidy']['all_properties']['border-bottom'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
317 |
+
$data['csstidy']['all_properties']['border-bottom-color'] = 'CSS2.0,CSS2.1,CSS3.0';
|
318 |
+
$data['csstidy']['all_properties']['border-bottom-left-radius'] = 'CSS3.0';
|
319 |
+
$data['csstidy']['all_properties']['border-bottom-right-radius'] = 'CSS3.0';
|
320 |
+
$data['csstidy']['all_properties']['border-bottom-style'] = 'CSS2.0,CSS2.1,CSS3.0';
|
321 |
+
$data['csstidy']['all_properties']['border-bottom-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
322 |
+
$data['csstidy']['all_properties']['border-collapse'] = 'CSS2.0,CSS2.1,CSS3.0';
|
323 |
+
$data['csstidy']['all_properties']['border-color'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
324 |
+
$data['csstidy']['all_properties']['border-image'] = 'CSS3.0';
|
325 |
+
$data['csstidy']['all_properties']['border-image-outset'] = 'CSS3.0';
|
326 |
+
$data['csstidy']['all_properties']['border-image-repeat'] = 'CSS3.0';
|
327 |
+
$data['csstidy']['all_properties']['border-image-slice'] = 'CSS3.0';
|
328 |
+
$data['csstidy']['all_properties']['border-image-source'] = 'CSS3.0';
|
329 |
+
$data['csstidy']['all_properties']['border-image-width'] = 'CSS3.0';
|
330 |
+
$data['csstidy']['all_properties']['border-left'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
331 |
+
$data['csstidy']['all_properties']['border-left-color'] = 'CSS2.0,CSS2.1,CSS3.0';
|
332 |
+
$data['csstidy']['all_properties']['border-left-style'] = 'CSS2.0,CSS2.1,CSS3.0';
|
333 |
+
$data['csstidy']['all_properties']['border-left-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
334 |
+
$data['csstidy']['all_properties']['border-radius'] = 'CSS3.0';
|
335 |
+
$data['csstidy']['all_properties']['border-right'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
336 |
+
$data['csstidy']['all_properties']['border-right-color'] = 'CSS2.0,CSS2.1,CSS3.0';
|
337 |
+
$data['csstidy']['all_properties']['border-right-style'] = 'CSS2.0,CSS2.1,CSS3.0';
|
338 |
+
$data['csstidy']['all_properties']['border-right-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
339 |
+
$data['csstidy']['all_properties']['border-spacing'] = 'CSS2.0,CSS2.1,CSS3.0';
|
340 |
+
$data['csstidy']['all_properties']['border-style'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
341 |
+
$data['csstidy']['all_properties']['border-top'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
342 |
+
$data['csstidy']['all_properties']['border-top-color'] = 'CSS2.0,CSS2.1,CSS3.0';
|
343 |
+
$data['csstidy']['all_properties']['border-top-left-radius'] = 'CSS3.0';
|
344 |
+
$data['csstidy']['all_properties']['border-top-right-radius'] = 'CSS3.0';
|
345 |
+
$data['csstidy']['all_properties']['border-top-style'] = 'CSS2.0,CSS2.1,CSS3.0';
|
346 |
+
$data['csstidy']['all_properties']['border-top-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
347 |
+
$data['csstidy']['all_properties']['border-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
348 |
+
$data['csstidy']['all_properties']['bottom'] = 'CSS2.0,CSS2.1,CSS3.0';
|
349 |
+
$data['csstidy']['all_properties']['box-decoration-break'] = 'CSS3.0';
|
350 |
+
$data['csstidy']['all_properties']['box-shadow'] = 'CSS3.0';
|
351 |
+
$data['csstidy']['all_properties']['box-sizing'] = 'CSS3.0';
|
352 |
+
$data['csstidy']['all_properties']['break-after'] = 'CSS3.0';
|
353 |
+
$data['csstidy']['all_properties']['break-before'] = 'CSS3.0';
|
354 |
+
$data['csstidy']['all_properties']['break-inside'] = 'CSS3.0';
|
355 |
+
$data['csstidy']['all_properties']['caption-side'] = 'CSS2.0,CSS2.1,CSS3.0';
|
356 |
+
$data['csstidy']['all_properties']['clear'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
357 |
+
$data['csstidy']['all_properties']['clip'] = 'CSS2.0,CSS2.1,CSS3.0';
|
358 |
+
$data['csstidy']['all_properties']['color'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
359 |
+
$data['csstidy']['all_properties']['color-profile'] = 'CSS3.0';
|
360 |
+
$data['csstidy']['all_properties']['column-count'] = 'CSS3.0';
|
361 |
+
$data['csstidy']['all_properties']['column-fill'] = 'CSS3.0';
|
362 |
+
$data['csstidy']['all_properties']['column-gap'] = 'CSS3.0';
|
363 |
+
$data['csstidy']['all_properties']['column-rule'] = 'CSS3.0';
|
364 |
+
$data['csstidy']['all_properties']['column-rule-color'] = 'CSS3.0';
|
365 |
+
$data['csstidy']['all_properties']['column-rule-style'] = 'CSS3.0';
|
366 |
+
$data['csstidy']['all_properties']['column-rule-width'] = 'CSS3.0';
|
367 |
+
$data['csstidy']['all_properties']['column-span'] = 'CSS3.0';
|
368 |
+
$data['csstidy']['all_properties']['column-width'] = 'CSS3.0';
|
369 |
+
$data['csstidy']['all_properties']['columns'] = 'CSS3.0';
|
370 |
+
$data['csstidy']['all_properties']['content'] = 'CSS2.0,CSS2.1,CSS3.0';
|
371 |
+
$data['csstidy']['all_properties']['counter-increment'] = 'CSS2.0,CSS2.1,CSS3.0';
|
372 |
+
$data['csstidy']['all_properties']['counter-reset'] = 'CSS2.0,CSS2.1,CSS3.0';
|
373 |
+
$data['csstidy']['all_properties']['crop'] = 'CSS3.0';
|
374 |
+
$data['csstidy']['all_properties']['cue'] = 'CSS2.0,CSS2.1,CSS3.0';
|
375 |
+
$data['csstidy']['all_properties']['cue-after'] = 'CSS2.0,CSS2.1,CSS3.0';
|
376 |
+
$data['csstidy']['all_properties']['cue-before'] = 'CSS2.0,CSS2.1,CSS3.0';
|
377 |
+
$data['csstidy']['all_properties']['cursor'] = 'CSS2.0,CSS2.1,CSS3.0';
|
378 |
+
$data['csstidy']['all_properties']['direction'] = 'CSS2.0,CSS2.1,CSS3.0';
|
379 |
+
$data['csstidy']['all_properties']['display'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
380 |
+
$data['csstidy']['all_properties']['dominant-baseline'] = 'CSS3.0';
|
381 |
+
$data['csstidy']['all_properties']['drop-initial-after-adjust'] = 'CSS3.0';
|
382 |
+
$data['csstidy']['all_properties']['drop-initial-after-align'] = 'CSS3.0';
|
383 |
+
$data['csstidy']['all_properties']['drop-initial-before-adjust'] = 'CSS3.0';
|
384 |
+
$data['csstidy']['all_properties']['drop-initial-before-align'] = 'CSS3.0';
|
385 |
+
$data['csstidy']['all_properties']['drop-initial-size'] = 'CSS3.0';
|
386 |
+
$data['csstidy']['all_properties']['drop-initial-value'] = 'CSS3.0';
|
387 |
+
$data['csstidy']['all_properties']['elevation'] = 'CSS2.0,CSS2.1,CSS3.0';
|
388 |
+
$data['csstidy']['all_properties']['empty-cells'] = 'CSS2.0,CSS2.1,CSS3.0';
|
389 |
+
$data['csstidy']['all_properties']['fit'] = 'CSS3.0';
|
390 |
+
$data['csstidy']['all_properties']['fit-position'] = 'CSS3.0';
|
391 |
+
$data['csstidy']['all_properties']['flex-align'] = 'CSS3.0';
|
392 |
+
$data['csstidy']['all_properties']['flex-flow'] = 'CSS3.0';
|
393 |
+
$data['csstidy']['all_properties']['flex-line-pack'] = 'CSS3.0';
|
394 |
+
$data['csstidy']['all_properties']['flex-order'] = 'CSS3.0';
|
395 |
+
$data['csstidy']['all_properties']['flex-pack'] = 'CSS3.0';
|
396 |
+
$data['csstidy']['all_properties']['float'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
397 |
+
$data['csstidy']['all_properties']['float-offset'] = 'CSS3.0';
|
398 |
+
$data['csstidy']['all_properties']['font'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
399 |
+
$data['csstidy']['all_properties']['font-family'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
400 |
+
$data['csstidy']['all_properties']['font-size'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
401 |
+
$data['csstidy']['all_properties']['font-size-adjust'] = 'CSS2.0,CSS3.0';
|
402 |
+
$data['csstidy']['all_properties']['font-stretch'] = 'CSS2.0,CSS3.0';
|
403 |
+
$data['csstidy']['all_properties']['font-style'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
404 |
+
$data['csstidy']['all_properties']['font-variant'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
405 |
+
$data['csstidy']['all_properties']['font-weight'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
406 |
+
$data['csstidy']['all_properties']['grid-columns'] = 'CSS3.0';
|
407 |
+
$data['csstidy']['all_properties']['grid-rows'] = 'CSS3.0';
|
408 |
+
$data['csstidy']['all_properties']['hanging-punctuation'] = 'CSS3.0';
|
409 |
+
$data['csstidy']['all_properties']['height'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
410 |
+
$data['csstidy']['all_properties']['hyphenate-after'] = 'CSS3.0';
|
411 |
+
$data['csstidy']['all_properties']['hyphenate-before'] = 'CSS3.0';
|
412 |
+
$data['csstidy']['all_properties']['hyphenate-character'] = 'CSS3.0';
|
413 |
+
$data['csstidy']['all_properties']['hyphenate-lines'] = 'CSS3.0';
|
414 |
+
$data['csstidy']['all_properties']['hyphenate-resource'] = 'CSS3.0';
|
415 |
+
$data['csstidy']['all_properties']['hyphens'] = 'CSS3.0';
|
416 |
+
$data['csstidy']['all_properties']['icon'] = 'CSS3.0';
|
417 |
+
$data['csstidy']['all_properties']['image-orientation'] = 'CSS3.0';
|
418 |
+
$data['csstidy']['all_properties']['image-rendering'] = 'CSS3.0';
|
419 |
+
$data['csstidy']['all_properties']['image-resolution'] = 'CSS3.0';
|
420 |
+
$data['csstidy']['all_properties']['inline-box-align'] = 'CSS3.0';
|
421 |
+
$data['csstidy']['all_properties']['left'] = 'CSS2.0,CSS2.1,CSS3.0';
|
422 |
+
$data['csstidy']['all_properties']['letter-spacing'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
423 |
+
$data['csstidy']['all_properties']['line-break'] = 'CSS3.0';
|
424 |
+
$data['csstidy']['all_properties']['line-height'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
425 |
+
$data['csstidy']['all_properties']['line-stacking'] = 'CSS3.0';
|
426 |
+
$data['csstidy']['all_properties']['line-stacking-ruby'] = 'CSS3.0';
|
427 |
+
$data['csstidy']['all_properties']['line-stacking-shift'] = 'CSS3.0';
|
428 |
+
$data['csstidy']['all_properties']['line-stacking-strategy'] = 'CSS3.0';
|
429 |
+
$data['csstidy']['all_properties']['list-style'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
430 |
+
$data['csstidy']['all_properties']['list-style-image'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
431 |
+
$data['csstidy']['all_properties']['list-style-position'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
432 |
+
$data['csstidy']['all_properties']['list-style-type'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
433 |
+
$data['csstidy']['all_properties']['margin'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
434 |
+
$data['csstidy']['all_properties']['margin-bottom'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
435 |
+
$data['csstidy']['all_properties']['margin-left'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
436 |
+
$data['csstidy']['all_properties']['margin-right'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
437 |
+
$data['csstidy']['all_properties']['margin-top'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
438 |
+
$data['csstidy']['all_properties']['marker-offset'] = 'CSS2.0,CSS3.0';
|
439 |
+
$data['csstidy']['all_properties']['marks'] = 'CSS2.0,CSS3.0';
|
440 |
+
$data['csstidy']['all_properties']['marquee-direction'] = 'CSS3.0';
|
441 |
+
$data['csstidy']['all_properties']['marquee-loop'] = 'CSS3.0';
|
442 |
+
$data['csstidy']['all_properties']['marquee-play-count'] = 'CSS3.0';
|
443 |
+
$data['csstidy']['all_properties']['marquee-speed'] = 'CSS3.0';
|
444 |
+
$data['csstidy']['all_properties']['marquee-style'] = 'CSS3.0';
|
445 |
+
$data['csstidy']['all_properties']['max-height'] = 'CSS2.0,CSS2.1,CSS3.0';
|
446 |
+
$data['csstidy']['all_properties']['max-width'] = 'CSS2.0,CSS2.1,CSS3.0';
|
447 |
+
$data['csstidy']['all_properties']['min-height'] = 'CSS2.0,CSS2.1,CSS3.0';
|
448 |
+
$data['csstidy']['all_properties']['min-width'] = 'CSS2.0,CSS2.1,CSS3.0';
|
449 |
+
$data['csstidy']['all_properties']['move-to'] = 'CSS3.0';
|
450 |
+
$data['csstidy']['all_properties']['nav-down'] = 'CSS3.0';
|
451 |
+
$data['csstidy']['all_properties']['nav-index'] = 'CSS3.0';
|
452 |
+
$data['csstidy']['all_properties']['nav-left'] = 'CSS3.0';
|
453 |
+
$data['csstidy']['all_properties']['nav-right'] = 'CSS3.0';
|
454 |
+
$data['csstidy']['all_properties']['nav-up'] = 'CSS3.0';
|
455 |
+
$data['csstidy']['all_properties']['opacity'] = 'CSS3.0';
|
456 |
+
$data['csstidy']['all_properties']['orphans'] = 'CSS2.0,CSS2.1,CSS3.0';
|
457 |
+
$data['csstidy']['all_properties']['outline'] = 'CSS2.0,CSS2.1,CSS3.0';
|
458 |
+
$data['csstidy']['all_properties']['outline-color'] = 'CSS2.0,CSS2.1,CSS3.0';
|
459 |
+
$data['csstidy']['all_properties']['outline-offset'] = 'CSS3.0';
|
460 |
+
$data['csstidy']['all_properties']['outline-style'] = 'CSS2.0,CSS2.1,CSS3.0';
|
461 |
+
$data['csstidy']['all_properties']['outline-width'] = 'CSS2.0,CSS2.1,CSS3.0';
|
462 |
+
$data['csstidy']['all_properties']['overflow'] = 'CSS2.0,CSS2.1,CSS3.0';
|
463 |
+
$data['csstidy']['all_properties']['overflow-style'] = 'CSS3.0';
|
464 |
+
$data['csstidy']['all_properties']['overflow-wrap'] = 'CSS3.0';
|
465 |
+
$data['csstidy']['all_properties']['overflow-x'] = 'CSS3.0';
|
466 |
+
$data['csstidy']['all_properties']['overflow-y'] = 'CSS3.0';
|
467 |
+
$data['csstidy']['all_properties']['padding'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
468 |
+
$data['csstidy']['all_properties']['padding-bottom'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
469 |
+
$data['csstidy']['all_properties']['padding-left'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
470 |
+
$data['csstidy']['all_properties']['padding-right'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
471 |
+
$data['csstidy']['all_properties']['padding-top'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
472 |
+
$data['csstidy']['all_properties']['page'] = 'CSS2.0,CSS3.0';
|
473 |
+
$data['csstidy']['all_properties']['page-break-after'] = 'CSS2.0,CSS2.1,CSS3.0';
|
474 |
+
$data['csstidy']['all_properties']['page-break-before'] = 'CSS2.0,CSS2.1,CSS3.0';
|
475 |
+
$data['csstidy']['all_properties']['page-break-inside'] = 'CSS2.0,CSS2.1,CSS3.0';
|
476 |
+
$data['csstidy']['all_properties']['page-policy'] = 'CSS3.0';
|
477 |
+
$data['csstidy']['all_properties']['pause'] = 'CSS2.0,CSS2.1,CSS3.0';
|
478 |
+
$data['csstidy']['all_properties']['pause-after'] = 'CSS2.0,CSS2.1,CSS3.0';
|
479 |
+
$data['csstidy']['all_properties']['pause-before'] = 'CSS2.0,CSS2.1,CSS3.0';
|
480 |
+
$data['csstidy']['all_properties']['perspective'] = 'CSS3.0';
|
481 |
+
$data['csstidy']['all_properties']['perspective-origin'] = 'CSS3.0';
|
482 |
+
$data['csstidy']['all_properties']['phonemes'] = 'CSS3.0';
|
483 |
+
$data['csstidy']['all_properties']['pitch'] = 'CSS2.0,CSS2.1,CSS3.0';
|
484 |
+
$data['csstidy']['all_properties']['pitch-range'] = 'CSS2.0,CSS2.1,CSS3.0';
|
485 |
+
$data['csstidy']['all_properties']['play-during'] = 'CSS2.0,CSS2.1,CSS3.0';
|
486 |
+
$data['csstidy']['all_properties']['position'] = 'CSS2.0,CSS2.1,CSS3.0';
|
487 |
+
$data['csstidy']['all_properties']['presentation-level'] = 'CSS3.0';
|
488 |
+
$data['csstidy']['all_properties']['punctuation-trim'] = 'CSS3.0';
|
489 |
+
$data['csstidy']['all_properties']['quotes'] = 'CSS2.0,CSS2.1,CSS3.0';
|
490 |
+
$data['csstidy']['all_properties']['rendering-intent'] = 'CSS3.0';
|
491 |
+
$data['csstidy']['all_properties']['resize'] = 'CSS3.0';
|
492 |
+
$data['csstidy']['all_properties']['rest'] = 'CSS3.0';
|
493 |
+
$data['csstidy']['all_properties']['rest-after'] = 'CSS3.0';
|
494 |
+
$data['csstidy']['all_properties']['rest-before'] = 'CSS3.0';
|
495 |
+
$data['csstidy']['all_properties']['richness'] = 'CSS2.0,CSS2.1,CSS3.0';
|
496 |
+
$data['csstidy']['all_properties']['right'] = 'CSS2.0,CSS2.1,CSS3.0';
|
497 |
+
$data['csstidy']['all_properties']['rotation'] = 'CSS3.0';
|
498 |
+
$data['csstidy']['all_properties']['rotation-point'] = 'CSS3.0';
|
499 |
+
$data['csstidy']['all_properties']['ruby-align'] = 'CSS3.0';
|
500 |
+
$data['csstidy']['all_properties']['ruby-overhang'] = 'CSS3.0';
|
501 |
+
$data['csstidy']['all_properties']['ruby-position'] = 'CSS3.0';
|
502 |
+
$data['csstidy']['all_properties']['ruby-span'] = 'CSS3.0';
|
503 |
+
$data['csstidy']['all_properties']['size'] = 'CSS2.0,CSS3.0';
|
504 |
+
$data['csstidy']['all_properties']['speak'] = 'CSS2.0,CSS2.1,CSS3.0';
|
505 |
+
$data['csstidy']['all_properties']['speak-header'] = 'CSS2.0,CSS2.1,CSS3.0';
|
506 |
+
$data['csstidy']['all_properties']['speak-numeral'] = 'CSS2.0,CSS2.1,CSS3.0';
|
507 |
+
$data['csstidy']['all_properties']['speak-punctuation'] = 'CSS2.0,CSS2.1,CSS3.0';
|
508 |
+
$data['csstidy']['all_properties']['speech-rate'] = 'CSS2.0,CSS2.1,CSS3.0';
|
509 |
+
$data['csstidy']['all_properties']['src'] = 'CSS3.0';
|
510 |
+
$data['csstidy']['all_properties']['stress'] = 'CSS2.0,CSS2.1,CSS3.0';
|
511 |
+
$data['csstidy']['all_properties']['string-set'] = 'CSS3.0';
|
512 |
+
$data['csstidy']['all_properties']['tab-size'] = 'CSS3.0';
|
513 |
+
$data['csstidy']['all_properties']['table-layout'] = 'CSS2.0,CSS2.1,CSS3.0';
|
514 |
+
$data['csstidy']['all_properties']['target'] = 'CSS3.0';
|
515 |
+
$data['csstidy']['all_properties']['target-name'] = 'CSS3.0';
|
516 |
+
$data['csstidy']['all_properties']['target-new'] = 'CSS3.0';
|
517 |
+
$data['csstidy']['all_properties']['target-position'] = 'CSS3.0';
|
518 |
+
$data['csstidy']['all_properties']['text-align'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
519 |
+
$data['csstidy']['all_properties']['text-align-last'] = 'CSS3.0';
|
520 |
+
$data['csstidy']['all_properties']['text-decoration'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
521 |
+
$data['csstidy']['all_properties']['text-decoration-color'] = 'CSS3.0';
|
522 |
+
$data['csstidy']['all_properties']['text-decoration-line'] = 'CSS3.0';
|
523 |
+
$data['csstidy']['all_properties']['text-decoration-skip'] = 'CSS3.0';
|
524 |
+
$data['csstidy']['all_properties']['text-decoration-style'] = 'CSS3.0';
|
525 |
+
$data['csstidy']['all_properties']['text-emphasis'] = 'CSS3.0';
|
526 |
+
$data['csstidy']['all_properties']['text-emphasis-color'] = 'CSS3.0';
|
527 |
+
$data['csstidy']['all_properties']['text-emphasis-position'] = 'CSS3.0';
|
528 |
+
$data['csstidy']['all_properties']['text-emphasis-style'] = 'CSS3.0';
|
529 |
+
$data['csstidy']['all_properties']['text-height'] = 'CSS3.0';
|
530 |
+
$data['csstidy']['all_properties']['text-indent'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
531 |
+
$data['csstidy']['all_properties']['text-justify'] = 'CSS3.0';
|
532 |
+
$data['csstidy']['all_properties']['text-outline'] = 'CSS3.0';
|
533 |
+
$data['csstidy']['all_properties']['text-shadow'] = 'CSS2.0,CSS3.0';
|
534 |
+
$data['csstidy']['all_properties']['text-space-collapse'] = 'CSS3.0';
|
535 |
+
$data['csstidy']['all_properties']['text-transform'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
536 |
+
$data['csstidy']['all_properties']['text-underline-position'] = 'CSS3.0';
|
537 |
+
$data['csstidy']['all_properties']['text-wrap'] = 'CSS3.0';
|
538 |
+
$data['csstidy']['all_properties']['top'] = 'CSS2.0,CSS2.1,CSS3.0';
|
539 |
+
$data['csstidy']['all_properties']['transform'] = 'CSS3.0';
|
540 |
+
$data['csstidy']['all_properties']['transform-origin'] = 'CSS3.0';
|
541 |
+
$data['csstidy']['all_properties']['transform-style'] = 'CSS3.0';
|
542 |
+
$data['csstidy']['all_properties']['transition'] = 'CSS3.0';
|
543 |
+
$data['csstidy']['all_properties']['transition-delay'] = 'CSS3.0';
|
544 |
+
$data['csstidy']['all_properties']['transition-duration'] = 'CSS3.0';
|
545 |
+
$data['csstidy']['all_properties']['transition-property'] = 'CSS3.0';
|
546 |
+
$data['csstidy']['all_properties']['transition-timing-function'] = 'CSS3.0';
|
547 |
+
$data['csstidy']['all_properties']['unicode-bidi'] = 'CSS2.0,CSS2.1,CSS3.0';
|
548 |
+
$data['csstidy']['all_properties']['vertical-align'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
549 |
+
$data['csstidy']['all_properties']['visibility'] = 'CSS2.0,CSS2.1,CSS3.0';
|
550 |
+
$data['csstidy']['all_properties']['voice-balance'] = 'CSS3.0';
|
551 |
+
$data['csstidy']['all_properties']['voice-duration'] = 'CSS3.0';
|
552 |
+
$data['csstidy']['all_properties']['voice-family'] = 'CSS2.0,CSS2.1,CSS3.0';
|
553 |
+
$data['csstidy']['all_properties']['voice-pitch'] = 'CSS3.0';
|
554 |
+
$data['csstidy']['all_properties']['voice-pitch-range'] = 'CSS3.0';
|
555 |
+
$data['csstidy']['all_properties']['voice-rate'] = 'CSS3.0';
|
556 |
+
$data['csstidy']['all_properties']['voice-stress'] = 'CSS3.0';
|
557 |
+
$data['csstidy']['all_properties']['voice-volume'] = 'CSS3.0';
|
558 |
+
$data['csstidy']['all_properties']['volume'] = 'CSS2.0,CSS2.1,CSS3.0';
|
559 |
+
$data['csstidy']['all_properties']['white-space'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
560 |
+
$data['csstidy']['all_properties']['widows'] = 'CSS2.0,CSS2.1,CSS3.0';
|
561 |
+
$data['csstidy']['all_properties']['width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
562 |
+
$data['csstidy']['all_properties']['word-break'] = 'CSS3.0';
|
563 |
+
$data['csstidy']['all_properties']['word-spacing'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
|
564 |
+
$data['csstidy']['all_properties']['word-wrap'] = 'CSS3.0';
|
565 |
+
$data['csstidy']['all_properties']['z-index'] = 'CSS2.0,CSS2.1,CSS3.0';
|
566 |
+
|
567 |
+
/**
|
568 |
+
* An array containing all properties that can accept a quoted string as a value.
|
569 |
+
*
|
570 |
+
* @global array $data['csstidy']['quoted_string_properties']
|
571 |
+
*/
|
572 |
+
$data['csstidy']['quoted_string_properties'] = array('content', 'font-family', 'quotes');
|
573 |
+
|
574 |
+
/**
|
575 |
+
* An array containing all properties that can be defined multiple times without being overwritten.
|
576 |
+
*
|
577 |
+
* @global array $data['csstidy']['quoted_string_properties']
|
578 |
+
*/
|
579 |
+
$data['csstidy']['multiple_properties'] = array('background', 'background-image');
|
580 |
+
|
581 |
+
/**
|
582 |
+
* An array containing all predefined templates.
|
583 |
+
*
|
584 |
+
* @global array $data['csstidy']['predefined_templates']
|
585 |
+
* @version 1.0
|
586 |
+
* @see csstidy::load_template()
|
587 |
+
*/
|
588 |
+
$data['csstidy']['predefined_templates']['default'][] = '<span class="at">'; //string before @rule
|
589 |
+
$data['csstidy']['predefined_templates']['default'][] = '</span> <span class="format">{</span>'."\n"; //bracket after @-rule
|
590 |
+
$data['csstidy']['predefined_templates']['default'][] = '<span class="selector">'; //string before selector
|
591 |
+
$data['csstidy']['predefined_templates']['default'][] = '</span> <span class="format">{</span>'."\n"; //bracket after selector
|
592 |
+
$data['csstidy']['predefined_templates']['default'][] = '<span class="property">'; //string before property
|
593 |
+
$data['csstidy']['predefined_templates']['default'][] = '</span><span class="value">'; //string after property+before value
|
594 |
+
$data['csstidy']['predefined_templates']['default'][] = '</span><span class="format">;</span>'."\n"; //string after value
|
595 |
+
$data['csstidy']['predefined_templates']['default'][] = '<span class="format">}</span>'; //closing bracket - selector
|
596 |
+
$data['csstidy']['predefined_templates']['default'][] = "\n\n"; //space between blocks {...}
|
597 |
+
$data['csstidy']['predefined_templates']['default'][] = "\n".'<span class="format">}</span>'. "\n\n"; //closing bracket @-rule
|
598 |
+
$data['csstidy']['predefined_templates']['default'][] = ''; //indent in @-rule
|
599 |
+
$data['csstidy']['predefined_templates']['default'][] = '<span class="comment">'; // before comment
|
600 |
+
$data['csstidy']['predefined_templates']['default'][] = '</span>'."\n"; // after comment
|
601 |
+
$data['csstidy']['predefined_templates']['default'][] = "\n"; // after each line @-rule
|
602 |
+
|
603 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '<span class="at">';
|
604 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '</span> <span class="format">{</span>'."\n";
|
605 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '<span class="selector">';
|
606 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '</span><span class="format">{</span>';
|
607 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '<span class="property">';
|
608 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '</span><span class="value">';
|
609 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '</span><span class="format">;</span>';
|
610 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '<span class="format">}</span>';
|
611 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = "\n";
|
612 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = "\n". '<span class="format">}'."\n".'</span>';
|
613 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '';
|
614 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '<span class="comment">'; // before comment
|
615 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = '</span>'; // after comment
|
616 |
+
$data['csstidy']['predefined_templates']['high_compression'][] = "\n";
|
617 |
+
|
618 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '<span class="at">';
|
619 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="format">{</span>';
|
620 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '<span class="selector">';
|
621 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="format">{</span>';
|
622 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '<span class="property">';
|
623 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="value">';
|
624 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="format">;</span>';
|
625 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '<span class="format">}</span>';
|
626 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '';
|
627 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '<span class="format">}</span>';
|
628 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '';
|
629 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '<span class="comment">'; // before comment
|
630 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '</span>'; // after comment
|
631 |
+
$data['csstidy']['predefined_templates']['highest_compression'][] = '';
|
632 |
+
|
633 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = '<span class="at">';
|
634 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = '</span> <span class="format">{</span>'."\n";
|
635 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = '<span class="selector">';
|
636 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = '</span>'."\n".'<span class="format">{</span>'."\n";
|
637 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = ' <span class="property">';
|
638 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = '</span><span class="value">';
|
639 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = '</span><span class="format">;</span>'."\n";
|
640 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = '<span class="format">}</span>';
|
641 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = "\n\n";
|
642 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = "\n".'<span class="format">}</span>'."\n\n";
|
643 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = ' ';
|
644 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = '<span class="comment">'; // before comment
|
645 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = '</span>'."\n"; // after comment
|
646 |
+
$data['csstidy']['predefined_templates']['low_compression'][] = "\n";
|
libs/CSSTidy/lang.inc.php
ADDED
@@ -0,0 +1,309 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Localization of CSS Optimiser Interface of CSSTidy
|
5 |
+
*
|
6 |
+
* Copyright 2005, 2006, 2007 Florian Schmitz
|
7 |
+
*
|
8 |
+
* This file is part of CSSTidy.
|
9 |
+
*
|
10 |
+
* CSSTidy is free software; you can redistribute it and/or modify
|
11 |
+
* it under the terms of the GNU Lesser General Public License as published by
|
12 |
+
* the Free Software Foundation; either version 2.1 of the License, or
|
13 |
+
* (at your option) any later version.
|
14 |
+
*
|
15 |
+
* CSSTidy is distributed in the hope that it will be useful,
|
16 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
18 |
+
* GNU Lesser General Public License for more details.
|
19 |
+
*
|
20 |
+
* You should have received a copy of the GNU Lesser General Public License
|
21 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
22 |
+
*
|
23 |
+
* @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
|
24 |
+
* @package csstidy
|
25 |
+
* @author Florian Schmitz (floele at gmail dot com) 2005-2007
|
26 |
+
* @author Brett Zamir (brettz9 at yahoo dot com) 2007
|
27 |
+
*/
|
28 |
+
|
29 |
+
|
30 |
+
if (isset($_GET['lang'])) {
|
31 |
+
$l = $_GET['lang'];
|
32 |
+
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
33 |
+
$l = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
|
34 |
+
$l = strtolower(substr($l, 0, 2));
|
35 |
+
} else {
|
36 |
+
$l = '';
|
37 |
+
}
|
38 |
+
|
39 |
+
$l = (in_array($l, array('de', 'fr', 'zh'))) ? $l : 'en';
|
40 |
+
|
41 |
+
// note 5 in all but French, and 40 in all are orphaned
|
42 |
+
|
43 |
+
$lang = array();
|
44 |
+
$lang['en'][0] = 'CSS Formatter and Optimiser/Optimizer (based on CSSTidy ';
|
45 |
+
$lang['en'][1] = 'CSS Formatter and Optimiser';
|
46 |
+
$lang['en'][2] = '(based on';
|
47 |
+
$lang['en'][3] = '(plaintext)';
|
48 |
+
$lang['en'][4] = 'Important Note:';
|
49 |
+
$lang['en'][6] = 'Your code should be well-formed. This is <strong>not a validator</strong> which points out errors in your CSS code. To make sure that your code is valid, use the <a href="http://jigsaw.w3.org/css-validator/">W3C Validator</a>.';
|
50 |
+
$lang['en'][7] = 'all comments are removed';
|
51 |
+
$lang['en'][8] = 'CSS Input:';
|
52 |
+
$lang['en'][9] = 'CSS-Code:';
|
53 |
+
$lang['en'][10] = 'CSS from URL:';
|
54 |
+
$lang['en'][11] = 'Code Layout:';
|
55 |
+
$lang['en'][12] = 'Compression (code layout):';
|
56 |
+
$lang['en'][13] = 'Highest (no readability, smallest size)';
|
57 |
+
$lang['en'][14] = 'High (moderate readability, smaller size)';
|
58 |
+
$lang['en'][15] = 'Standard (balance between readability and size)';
|
59 |
+
$lang['en'][16] = 'Low (higher readability)';
|
60 |
+
$lang['en'][17] = 'Custom (enter below)';
|
61 |
+
$lang['en'][18] = 'Custom <a href="http://csstidy.sourceforge.net/templates.php">template</a>';
|
62 |
+
$lang['en'][19] = 'Options';
|
63 |
+
$lang['en'][20] = 'Sort Selectors (caution)';
|
64 |
+
$lang['en'][21] = 'Sort Properties';
|
65 |
+
$lang['en'][22] = 'Regroup selectors';
|
66 |
+
$lang['en'][23] = 'Optimise shorthands';
|
67 |
+
$lang['en'][24] = 'Compress colors';
|
68 |
+
$lang['en'][25] = 'Lowercase selectors';
|
69 |
+
$lang['en'][26] = 'Case for properties:';
|
70 |
+
$lang['en'][27] = 'Lowercase';
|
71 |
+
$lang['en'][28] = 'No or invalid CSS input or wrong URL!';
|
72 |
+
$lang['en'][29] = 'Uppercase';
|
73 |
+
$lang['en'][30] = 'lowercase elementnames needed for XHTML';
|
74 |
+
$lang['en'][31] = 'Remove unnecessary backslashes';
|
75 |
+
$lang['en'][32] = 'convert !important-hack';
|
76 |
+
$lang['en'][33] = 'Output as file';
|
77 |
+
$lang['en'][34] = 'Bigger compression because of smaller newlines (copy & paste doesn\'t work)';
|
78 |
+
$lang['en'][35] = 'Process CSS';
|
79 |
+
$lang['en'][36] = 'Compression Ratio';
|
80 |
+
$lang['en'][37] = 'Input';
|
81 |
+
$lang['en'][38] = 'Output';
|
82 |
+
$lang['en'][39] = 'Language';
|
83 |
+
$lang['en'][41] = 'Attention: This may change the behaviour of your CSS Code!';
|
84 |
+
$lang['en'][42] = 'Remove last ;';
|
85 |
+
$lang['en'][43] = 'Discard invalid properties';
|
86 |
+
$lang['en'][44] = 'Only safe optimisations';
|
87 |
+
$lang['en'][45] = 'Compress font-weight';
|
88 |
+
$lang['en'][46] = 'Save comments';
|
89 |
+
$lang['en'][47] = 'Do not change anything';
|
90 |
+
$lang['en'][48] = 'Only seperate selectors (split at ,)';
|
91 |
+
$lang['en'][49] = 'Merge selectors with the same properties (fast)';
|
92 |
+
$lang['en'][50] = 'Merge selectors intelligently (slow)';
|
93 |
+
$lang['en'][51] = 'Preserve CSS';
|
94 |
+
$lang['en'][52] = 'Save comments, hacks, etc. Most optimisations can *not* be applied if this is enabled.';
|
95 |
+
$lang['en'][53] = 'None';
|
96 |
+
$lang['en'][54] = 'Don\'t optimise';
|
97 |
+
$lang['en'][55] = 'Safe optimisations';
|
98 |
+
$lang['en'][56] = 'All optimisations';
|
99 |
+
$lang['en'][57] = 'Add timestamp';
|
100 |
+
$lang['en'][58] = 'Copy to clipboard';
|
101 |
+
$lang['en'][59] = 'Back to top';
|
102 |
+
$lang['en'][60] = 'Your browser doesn\'t support copy to clipboard.';
|
103 |
+
$lang['en'][61] = 'For bugs and suggestions feel free to';
|
104 |
+
$lang['en'][62] = 'contact me';
|
105 |
+
$lang['en'][63] = 'Output CSS code as complete HTML document';
|
106 |
+
$lang['en'][64] = 'Code';
|
107 |
+
$lang['en'][65] = 'CSS to style CSS output';
|
108 |
+
$lang['en'][66] = 'You need to go to about:config in your URL bar, select \'signed.applets.codebase_principal_support\' in the filter field, and set its value to true in order to use this feature; however, be aware that doing so increases security risks.';
|
109 |
+
|
110 |
+
|
111 |
+
$lang['de'][0] = 'CSS Formatierer und Optimierer (basierend auf CSSTidy ';
|
112 |
+
$lang['de'][1] = 'CSS Formatierer und Optimierer';
|
113 |
+
$lang['de'][2] = '(basierend auf';
|
114 |
+
$lang['de'][3] = '(Textversion)';
|
115 |
+
$lang['de'][4] = 'Wichtiger Hinweis:';
|
116 |
+
$lang['de'][6] = 'Der CSS Code sollte wohlgeformt sein. Der CSS Code wird <strong>nicht auf Gültigkeit überprüft</strong>. Um sicherzugehen dass dein Code valide ist, benutze den <a href="http://jigsaw.w3.org/css-validator/">W3C Validierungsservice</a>.';
|
117 |
+
$lang['de'][7] = 'alle Kommentare werden entfernt';
|
118 |
+
$lang['de'][8] = 'CSS Eingabe:';
|
119 |
+
$lang['de'][9] = 'CSS-Code:';
|
120 |
+
$lang['de'][10] = 'CSS von URL:';
|
121 |
+
$lang['de'][11] = 'Code Layout:';
|
122 |
+
$lang['de'][12] = 'Komprimierung (Code Layout):';
|
123 |
+
$lang['de'][13] = 'Höchste (keine Lesbarkeit, niedrigste Größe)';
|
124 |
+
$lang['de'][14] = 'Hoch (mittelmäßige Lesbarkeit, geringe Größe)';
|
125 |
+
$lang['de'][15] = 'Standard (Kompromiss zwischen Lesbarkeit und Größe)';
|
126 |
+
$lang['de'][16] = 'Niedrig (höhere Lesbarkeit)';
|
127 |
+
$lang['de'][17] = 'Benutzerdefiniert (unten eingeben)';
|
128 |
+
$lang['de'][18] = 'Benutzerdefinierte <a href="http://csstidy.sourceforge.net/templates.php">Vorlage</a>';
|
129 |
+
$lang['de'][19] = 'Optionen';
|
130 |
+
$lang['de'][20] = 'Selektoren sortieren (Vorsicht)';
|
131 |
+
$lang['de'][21] = 'Eigenschaften sortieren';
|
132 |
+
$lang['de'][22] = 'Selektoren umgruppieren';
|
133 |
+
$lang['de'][23] = 'Shorthands optimieren';
|
134 |
+
$lang['de'][24] = 'Farben komprimieren';
|
135 |
+
$lang['de'][25] = 'Selektoren in Kleinbuchstaben';
|
136 |
+
$lang['de'][26] = 'Groß-/Kleinschreibung für Eigenschaften';
|
137 |
+
$lang['de'][27] = 'Kleinbuchstaben';
|
138 |
+
$lang['de'][28] = 'Keine oder ungültige CSS Eingabe oder falsche URL!';
|
139 |
+
$lang['de'][29] = 'Großbuchstaben';
|
140 |
+
$lang['de'][30] = 'kleingeschriebene Elementnamen benötigt für XHTML';
|
141 |
+
$lang['de'][31] = 'Unnötige Backslashes entfernen';
|
142 |
+
$lang['de'][32] = '!important-Hack konvertieren';
|
143 |
+
$lang['de'][33] = 'Als Datei ausgeben';
|
144 |
+
$lang['de'][34] = 'Größere Komprimierung augrund von kleineren Neuezeile-Zeichen';
|
145 |
+
$lang['de'][35] = 'CSS verarbeiten';
|
146 |
+
$lang['de'][36] = 'Komprimierungsrate';
|
147 |
+
$lang['de'][37] = 'Eingabe';
|
148 |
+
$lang['de'][38] = 'Ausgabe';
|
149 |
+
$lang['de'][39] = 'Sprache';
|
150 |
+
$lang['de'][41] = 'Achtung: Dies könnte das Verhalten ihres CSS-Codes verändern!';
|
151 |
+
$lang['de'][42] = 'Letztes ; entfernen';
|
152 |
+
$lang['de'][43] = 'Ungültige Eigenschaften entfernen';
|
153 |
+
$lang['de'][44] = 'Nur sichere Optimierungen';
|
154 |
+
$lang['de'][45] = 'font-weight komprimieren';
|
155 |
+
$lang['de'][46] = 'Kommentare beibehalten';
|
156 |
+
$lang['de'][47] = 'Nichts ändern';
|
157 |
+
$lang['de'][48] = 'Selektoren nur trennen (am Komma)';
|
158 |
+
$lang['de'][49] = 'Selektoren mit gleichen Eigenschaften zusammenfassen (schnell)';
|
159 |
+
$lang['de'][50] = 'Selektoren intelligent zusammenfassen (langsam!)';
|
160 |
+
$lang['de'][51] = 'CSS erhalten';
|
161 |
+
$lang['de'][52] = 'Kommentare, Hacks, etc. speichern. Viele Optimierungen sind dann aber nicht mehr möglich.';
|
162 |
+
$lang['de'][53] = 'Keine';
|
163 |
+
$lang['de'][54] = 'Nicht optimieren';
|
164 |
+
$lang['de'][55] = 'Sichere Optimierungen';
|
165 |
+
$lang['de'][56] = 'Alle Optimierungen';
|
166 |
+
$lang['de'][57] = 'Zeitstempel hinzufügen';
|
167 |
+
$lang['de'][58] = 'Copy to clipboard';
|
168 |
+
$lang['de'][59] = 'Back to top';
|
169 |
+
$lang['de'][60] = 'Your browser doesn\'t support copy to clipboard.';
|
170 |
+
$lang['de'][61] = 'For bugs and suggestions feel free to';
|
171 |
+
$lang['de'][62] = 'contact me';
|
172 |
+
$lang['de'][63] = 'Output CSS code as complete HTML document';
|
173 |
+
$lang['de'][64] = 'Code';
|
174 |
+
$lang['de'][65] = 'CSS to style CSS output';
|
175 |
+
$lang['de'][66] = 'You need to go to about:config in your URL bar, select \'signed.applets.codebase_principal_support\' in the filter field, and set its value to true in order to use this feature; however, be aware that doing so increases security risks.';
|
176 |
+
|
177 |
+
|
178 |
+
$lang['fr'][0] = 'CSS Formateur et Optimiseur (basé sur CSSTidy ';
|
179 |
+
$lang['fr'][1] = 'CSS Formateur et Optimiseur';
|
180 |
+
$lang['fr'][2] = '(basé sur ';
|
181 |
+
$lang['fr'][3] = '(Version texte)';
|
182 |
+
$lang['fr'][4] = 'Note Importante :';
|
183 |
+
$lang['fr'][6] = 'Votre code doit être valide. Ce n’est <strong>pas un validateur</strong> qui signale les erreurs dans votre code CSS. Pour être sûr que votre code est correct, utilisez le validateur : <a href="http://jigsaw.w3.org/css-validator/">W3C Validator</a>.';
|
184 |
+
$lang['fr'][7] = 'tous les commentaires sont enlevés';
|
185 |
+
$lang['fr'][8] = 'Champ CSS :';
|
186 |
+
$lang['fr'][9] = 'Code CSS :';
|
187 |
+
$lang['fr'][10] = 'CSS en provenance d’une URL :<br />';
|
188 |
+
$lang['fr'][11] = 'Mise en page du code :';
|
189 |
+
$lang['fr'][12] = 'Compression (mise en page du code) :';
|
190 |
+
$lang['fr'][13] = 'La plus élevée (aucune lisibilité, taille minimale)';
|
191 |
+
$lang['fr'][14] = 'Élevée (lisibilité modérée, petite taille)';
|
192 |
+
$lang['fr'][15] = 'Normale (équilibre entre lisibilité et taille)';
|
193 |
+
$lang['fr'][16] = 'Faible (lisibilité élevée)';
|
194 |
+
$lang['fr'][17] = 'Sur mesure (entrer ci-dessous)';
|
195 |
+
$lang['fr'][18] = '<a href="http://csstidy.sourceforge.net/templates.php">Gabarit</a> sur mesure';
|
196 |
+
$lang['fr'][19] = 'Options';
|
197 |
+
$lang['fr'][20] = 'Trier les sélecteurs (attention)';
|
198 |
+
$lang['fr'][21] = 'Trier les propriétés';
|
199 |
+
$lang['fr'][22] = 'Regrouper les sélecteurs';
|
200 |
+
$lang['fr'][23] = 'Propriétés raccourcies';
|
201 |
+
$lang['fr'][24] = 'Compresser les couleurs';
|
202 |
+
$lang['fr'][25] = 'Sélecteurs en minuscules';
|
203 |
+
$lang['fr'][26] = 'Case pour les propriétés :';
|
204 |
+
$lang['fr'][27] = 'Minuscule';
|
205 |
+
$lang['fr'][28] = 'CSS non valide ou URL incorrecte !';
|
206 |
+
$lang['fr'][29] = 'Majuscule';
|
207 |
+
$lang['fr'][30] = 'les noms des éléments en minuscules (indispensables pour XHTML)';
|
208 |
+
$lang['fr'][31] = 'enlever les antislashs inutiles';
|
209 |
+
$lang['fr'][32] = 'convertir !important-hack';
|
210 |
+
$lang['fr'][33] = 'Sauver en tant que fichier';
|
211 |
+
$lang['fr'][34] = 'Meilleure compression grâce aux caractères de saut de ligne plus petits (copier & coller ne marche pas)';
|
212 |
+
$lang['fr'][35] = 'Compresser la CSS';
|
213 |
+
$lang['fr'][36] = 'Facteur de Compression';
|
214 |
+
$lang['fr'][37] = 'Entrée';
|
215 |
+
$lang['fr'][38] = 'Sortie';
|
216 |
+
$lang['fr'][39] = 'Langue';
|
217 |
+
$lang['fr'][41] = 'Attention : ceci peut changer le comportement de votre code CSS !';
|
218 |
+
$lang['fr'][42] = 'Enlever le dernier ;';
|
219 |
+
$lang['fr'][43] = 'Supprimer les propriétés non valide';
|
220 |
+
$lang['fr'][44] = 'Seulement les optimisations sûres';
|
221 |
+
$lang['fr'][45] = 'Compresser font-weight';
|
222 |
+
$lang['fr'][46] = 'Sauvegarder les commentaires ';
|
223 |
+
$lang['fr'][47] = 'Ne rien changer';
|
224 |
+
$lang['fr'][48] = 'Sépare les sélecteurs (sépare au niveau de ,)';
|
225 |
+
$lang['fr'][49] = 'Fusionne les sélecteurs avec les mêmes propriétés (rapide)';
|
226 |
+
$lang['fr'][50] = 'Fusionne les sélecteurs intelligemment (lent)';
|
227 |
+
$lang['fr'][51] = 'Préserver la CSS';
|
228 |
+
$lang['fr'][52] = 'Sauvegarder les commentaires, hacks, etc. La plupart des optimisations ne peuvent *pas* être appliquées si cela est activé.';
|
229 |
+
$lang['fr'][53] = 'Aucun';
|
230 |
+
$lang['fr'][54] = 'Ne pas optimiser';
|
231 |
+
$lang['fr'][55] = 'Optimisations sûres';
|
232 |
+
$lang['fr'][56] = 'Toutes les optimisations';
|
233 |
+
$lang['fr'][57] = 'Ajouter un timestamp';
|
234 |
+
$lang['fr'][58] = 'Copier dans le presse-papiers';
|
235 |
+
$lang['fr'][59] = 'Retour en haut';
|
236 |
+
$lang['fr'][60] = 'Votre navigateur ne supporte pas la copie vers le presse-papiers.';
|
237 |
+
$lang['fr'][61] = 'Pour signaler des bugs ou pour des suggestions,';
|
238 |
+
$lang['fr'][62] = 'contactez-moi';
|
239 |
+
$lang['fr'][63] = 'Sauver le code CSS comme document complet HTML';
|
240 |
+
$lang['fr'][64] = 'Code';
|
241 |
+
$lang['fr'][65] = 'CSS pour colorier la sortie CSS';
|
242 |
+
$lang['fr'][66] = 'Vous devez aller dans about:config dans votre barre d’adresse, sélectionner \'signed.applets.codebase_principal_support\' dans le champ Filtre et attribuez-lui la valeur \'true\' pour utiliser cette fonctionnalité; toutefois, soyez conscient que cela augmente les risques de sécurité.';
|
243 |
+
|
244 |
+
|
245 |
+
$lang['zh'][0] = 'CSS整形與最佳化工具(使用 CSSTidy ';
|
246 |
+
$lang['zh'][1] = 'CSS整形與最佳化工具';
|
247 |
+
$lang['zh'][2] = '(使用';
|
248 |
+
$lang['zh'][3] = '(純文字)';
|
249 |
+
$lang['zh'][4] = '重要事項:';
|
250 |
+
$lang['zh'][6] = '你的原始碼必須是良構的(well-formed). 這個工具<strong>沒有內建驗證器(validator)</strong>. 驗證器能夠指出你CSS原始碼裡的錯誤. 請使用 <a href="http://jigsaw.w3.org/css-validator/">W3C 驗證器</a>, 確保你的原始碼合乎規範.';
|
251 |
+
$lang['zh'][7] = '所有註解都移除了';
|
252 |
+
$lang['zh'][8] = 'CSS 輸入:';
|
253 |
+
$lang['zh'][9] = 'CSS 原始碼:';
|
254 |
+
$lang['zh'][10] = 'CSS 檔案網址(URL):';
|
255 |
+
$lang['zh'][11] = '原始碼規劃:';
|
256 |
+
$lang['zh'][12] = '壓縮程度(原始碼規劃):';
|
257 |
+
$lang['zh'][13] = '最高 (沒有辦法讀, 檔案最小)';
|
258 |
+
$lang['zh'][14] = '高 (適度的可讀性, 檔案小)';
|
259 |
+
$lang['zh'][15] = '標準 (兼顧可讀性與檔案大小)';
|
260 |
+
$lang['zh'][16] = '低 (注重可讀性)';
|
261 |
+
$lang['zh'][17] = '自訂 (在下方設定)';
|
262 |
+
$lang['zh'][18] = '自訂<a href="http://csstidy.sourceforge.net/templates.php">樣板</a>';
|
263 |
+
$lang['zh'][19] = '選項';
|
264 |
+
$lang['zh'][20] = '整理選擇符(請謹慎使用)';
|
265 |
+
$lang['zh'][21] = '整理屬性';
|
266 |
+
$lang['zh'][22] = '重組選擇符';
|
267 |
+
$lang['zh'][23] = '速記法(shorthand)最佳化';
|
268 |
+
$lang['zh'][24] = '壓縮色彩語法';
|
269 |
+
$lang['zh'][25] = '改用小寫選擇符';
|
270 |
+
$lang['zh'][26] = '屬性的字形:';
|
271 |
+
$lang['zh'][27] = '小寫';
|
272 |
+
$lang['zh'][28] = '沒有輸入CSS, 語法不符合規定, 或是網址錯誤!';
|
273 |
+
$lang['zh'][29] = '大寫';
|
274 |
+
$lang['zh'][30] = 'XHTML必須使用小寫的元素名稱';
|
275 |
+
$lang['zh'][31] = '移除不必要的反斜線';
|
276 |
+
$lang['zh'][32] = '轉換 !important-hack';
|
277 |
+
$lang['zh'][33] = '輸出成檔案形式';
|
278 |
+
$lang['zh'][34] = '由於比較少換行字元, 會有更大的壓縮比率(複製&貼上沒有用)';
|
279 |
+
$lang['zh'][35] = '執行';
|
280 |
+
$lang['zh'][36] = '壓縮比率';
|
281 |
+
$lang['zh'][37] = '輸入';
|
282 |
+
$lang['zh'][38] = '輸出';
|
283 |
+
$lang['zh'][39] = '語言';
|
284 |
+
$lang['zh'][41] = '注意: 這或許會變更你CSS原始碼的行為!';
|
285 |
+
$lang['zh'][42] = '除去最後一個分號';
|
286 |
+
$lang['zh'][43] = '拋棄不符合規定的屬性';
|
287 |
+
$lang['zh'][44] = '只安全地最佳化';
|
288 |
+
$lang['zh'][45] = '壓縮 font-weight';
|
289 |
+
$lang['zh'][46] = '保留註解';
|
290 |
+
$lang['zh'][47] = '什麼都不要改';
|
291 |
+
$lang['zh'][48] = '只分開原本用逗號分隔的選擇符';
|
292 |
+
$lang['zh'][49] = '合併有相同屬性的選擇符(快速)';
|
293 |
+
$lang['zh'][50] = '聰明地合併選擇符(慢速)';
|
294 |
+
$lang['zh'][51] = '保護CSS';
|
295 |
+
$lang['zh'][52] = '保留註解與 hack 等等. 如果啟用這個選項, 大多數的最佳化程序都不會執行.';
|
296 |
+
$lang['zh'][53] = '不改變';
|
297 |
+
$lang['zh'][54] = '不做最佳化';
|
298 |
+
$lang['zh'][55] = '安全地最佳化';
|
299 |
+
$lang['zh'][56] = '全部最佳化';
|
300 |
+
$lang['zh'][57] = '加上時間戳記';
|
301 |
+
$lang['zh'][58] = '复制到剪贴板';
|
302 |
+
$lang['zh'][59] = '回到页面上方';
|
303 |
+
$lang['zh'][60] = '你的浏览器不支持复制到剪贴板。';
|
304 |
+
$lang['zh'][61] = '如果程序有错误或你有建议,欢迎';
|
305 |
+
$lang['zh'][62] = '和我联系';
|
306 |
+
$lang['zh'][63] = 'Output CSS code as complete HTML document';
|
307 |
+
$lang['zh'][64] = '代码';
|
308 |
+
$lang['zh'][65] = 'CSS to style CSS output';
|
309 |
+
$lang['zh'][66] = 'You need to go to about:config in your URL bar, select \'signed.applets.codebase_principal_support\' in the filter field, and set its value to true in order to use this feature; however, be aware that doing so increases security risks.';
|
libs/JSMin/jsmin.php
ADDED
@@ -0,0 +1,386 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* jsmin.php - PHP implementation of Douglas Crockford's JSMin.
|
4 |
+
*
|
5 |
+
* This is pretty much a direct port of jsmin.c to PHP with just a few
|
6 |
+
* PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
|
7 |
+
* outputs to stdout, this library accepts a string as input and returns another
|
8 |
+
* string as output.
|
9 |
+
*
|
10 |
+
* PHP 5 or higher is required.
|
11 |
+
*
|
12 |
+
* Permission is hereby granted to use this version of the library under the
|
13 |
+
* same terms as jsmin.c, which has the following license:
|
14 |
+
*
|
15 |
+
* --
|
16 |
+
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
17 |
+
*
|
18 |
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
19 |
+
* this software and associated documentation files (the "Software"), to deal in
|
20 |
+
* the Software without restriction, including without limitation the rights to
|
21 |
+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
22 |
+
* of the Software, and to permit persons to whom the Software is furnished to do
|
23 |
+
* so, subject to the following conditions:
|
24 |
+
*
|
25 |
+
* The above copyright notice and this permission notice shall be included in all
|
26 |
+
* copies or substantial portions of the Software.
|
27 |
+
*
|
28 |
+
* The Software shall be used for Good, not Evil.
|
29 |
+
*
|
30 |
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
31 |
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
32 |
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
33 |
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
34 |
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
35 |
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
36 |
+
* SOFTWARE.
|
37 |
+
* --
|
38 |
+
*
|
39 |
+
* @package JSMin
|
40 |
+
* @author Ryan Grove <ryan@wonko.com>
|
41 |
+
* @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
|
42 |
+
* @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
|
43 |
+
* @copyright 2012 Adam Goforth <aag@adamgoforth.com> (Updates)
|
44 |
+
* @license http://opensource.org/licenses/mit-license.php MIT License
|
45 |
+
* @version 1.1.2 (2012-05-01)
|
46 |
+
* @link https://github.com/rgrove/jsmin-php
|
47 |
+
*/
|
48 |
+
|
49 |
+
class JSMin {
|
50 |
+
const ORD_LF = 10;
|
51 |
+
const ORD_SPACE = 32;
|
52 |
+
const ACTION_KEEP_A = 1;
|
53 |
+
const ACTION_DELETE_A = 2;
|
54 |
+
const ACTION_DELETE_A_B = 3;
|
55 |
+
|
56 |
+
protected $a = '';
|
57 |
+
protected $b = '';
|
58 |
+
protected $input = '';
|
59 |
+
protected $inputIndex = 0;
|
60 |
+
protected $inputLength = 0;
|
61 |
+
protected $lookAhead = null;
|
62 |
+
protected $output = '';
|
63 |
+
|
64 |
+
// -- Public Static Methods --------------------------------------------------
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Minify Javascript
|
68 |
+
*
|
69 |
+
* @uses __construct()
|
70 |
+
* @uses min()
|
71 |
+
* @param string $js Javascript to be minified
|
72 |
+
* @return string
|
73 |
+
*/
|
74 |
+
public static function minify($js) {
|
75 |
+
$jsmin = new JSMin($js);
|
76 |
+
return $jsmin->min();
|
77 |
+
}
|
78 |
+
|
79 |
+
// -- Public Instance Methods ------------------------------------------------
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Constructor
|
83 |
+
*
|
84 |
+
* @param string $input Javascript to be minified
|
85 |
+
*/
|
86 |
+
public function __construct($input) {
|
87 |
+
$this->input = str_replace("\r\n", "\n", $input);
|
88 |
+
$this->inputLength = strlen($this->input);
|
89 |
+
}
|
90 |
+
|
91 |
+
// -- Protected Instance Methods ---------------------------------------------
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Action -- do something! What to do is determined by the $command argument.
|
95 |
+
*
|
96 |
+
* action treats a string as a single character. Wow!
|
97 |
+
* action recognizes a regular expression if it is preceded by ( or , or =.
|
98 |
+
*
|
99 |
+
* @uses next()
|
100 |
+
* @uses get()
|
101 |
+
* @throws JSMinException If parser errors are found:
|
102 |
+
* - Unterminated string literal
|
103 |
+
* - Unterminated regular expression set in regex literal
|
104 |
+
* - Unterminated regular expression literal
|
105 |
+
* @param int $command One of class constants:
|
106 |
+
* ACTION_KEEP_A Output A. Copy B to A. Get the next B.
|
107 |
+
* ACTION_DELETE_A Copy B to A. Get the next B. (Delete A).
|
108 |
+
* ACTION_DELETE_A_B Get the next B. (Delete B).
|
109 |
+
*/
|
110 |
+
protected function action($command) {
|
111 |
+
switch($command) {
|
112 |
+
case self::ACTION_KEEP_A:
|
113 |
+
$this->output .= $this->a;
|
114 |
+
|
115 |
+
case self::ACTION_DELETE_A:
|
116 |
+
$this->a = $this->b;
|
117 |
+
|
118 |
+
if ($this->a === "'" || $this->a === '"') {
|
119 |
+
for (;;) {
|
120 |
+
$this->output .= $this->a;
|
121 |
+
$this->a = $this->get();
|
122 |
+
|
123 |
+
if ($this->a === $this->b) {
|
124 |
+
break;
|
125 |
+
}
|
126 |
+
|
127 |
+
if (ord($this->a) <= self::ORD_LF) {
|
128 |
+
throw new JSMinException('Unterminated string literal.');
|
129 |
+
}
|
130 |
+
|
131 |
+
if ($this->a === '\\') {
|
132 |
+
$this->output .= $this->a;
|
133 |
+
$this->a = $this->get();
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
case self::ACTION_DELETE_A_B:
|
139 |
+
$this->b = $this->next();
|
140 |
+
|
141 |
+
if ($this->b === '/' && (
|
142 |
+
$this->a === '(' || $this->a === ',' || $this->a === '=' ||
|
143 |
+
$this->a === ':' || $this->a === '[' || $this->a === '!' ||
|
144 |
+
$this->a === '&' || $this->a === '|' || $this->a === '?' ||
|
145 |
+
$this->a === '{' || $this->a === '}' || $this->a === ';' ||
|
146 |
+
$this->a === "\n" )) {
|
147 |
+
|
148 |
+
$this->output .= $this->a . $this->b;
|
149 |
+
|
150 |
+
for (;;) {
|
151 |
+
$this->a = $this->get();
|
152 |
+
|
153 |
+
if ($this->a === '[') {
|
154 |
+
/*
|
155 |
+
inside a regex [...] set, which MAY contain a '/' itself. Example: mootools Form.Validator near line 460:
|
156 |
+
return Form.Validator.getValidator('IsEmpty').test(element) || (/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(element.get('value'));
|
157 |
+
*/
|
158 |
+
for (;;) {
|
159 |
+
$this->output .= $this->a;
|
160 |
+
$this->a = $this->get();
|
161 |
+
|
162 |
+
if ($this->a === ']') {
|
163 |
+
break;
|
164 |
+
} elseif ($this->a === '\\') {
|
165 |
+
$this->output .= $this->a;
|
166 |
+
$this->a = $this->get();
|
167 |
+
} elseif (ord($this->a) <= self::ORD_LF) {
|
168 |
+
throw new JSMinException('Unterminated regular expression set in regex literal.');
|
169 |
+
}
|
170 |
+
}
|
171 |
+
} elseif ($this->a === '/') {
|
172 |
+
break;
|
173 |
+
} elseif ($this->a === '\\') {
|
174 |
+
$this->output .= $this->a;
|
175 |
+
$this->a = $this->get();
|
176 |
+
} elseif (ord($this->a) <= self::ORD_LF) {
|
177 |
+
throw new JSMinException('Unterminated regular expression literal.');
|
178 |
+
}
|
179 |
+
|
180 |
+
$this->output .= $this->a;
|
181 |
+
}
|
182 |
+
|
183 |
+
$this->b = $this->next();
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Get next char. Convert ctrl char to space.
|
190 |
+
*
|
191 |
+
* @return string|null
|
192 |
+
*/
|
193 |
+
protected function get() {
|
194 |
+
$c = $this->lookAhead;
|
195 |
+
$this->lookAhead = null;
|
196 |
+
|
197 |
+
if ($c === null) {
|
198 |
+
if ($this->inputIndex < $this->inputLength) {
|
199 |
+
$c = substr($this->input, $this->inputIndex, 1);
|
200 |
+
$this->inputIndex += 1;
|
201 |
+
} else {
|
202 |
+
$c = null;
|
203 |
+
}
|
204 |
+
}
|
205 |
+
|
206 |
+
if ($c === "\r") {
|
207 |
+
return "\n";
|
208 |
+
}
|
209 |
+
|
210 |
+
if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
|
211 |
+
return $c;
|
212 |
+
}
|
213 |
+
|
214 |
+
return ' ';
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Is $c a letter, digit, underscore, dollar sign, or non-ASCII character.
|
219 |
+
*
|
220 |
+
* @return bool
|
221 |
+
*/
|
222 |
+
protected function isAlphaNum($c) {
|
223 |
+
return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* Perform minification, return result
|
228 |
+
*
|
229 |
+
* @uses action()
|
230 |
+
* @uses isAlphaNum()
|
231 |
+
* @uses get()
|
232 |
+
* @uses peek()
|
233 |
+
* @return string
|
234 |
+
*/
|
235 |
+
protected function min() {
|
236 |
+
if (0 == strncmp($this->peek(), "\xef", 1)) {
|
237 |
+
$this->get();
|
238 |
+
$this->get();
|
239 |
+
$this->get();
|
240 |
+
}
|
241 |
+
|
242 |
+
$this->a = "\n";
|
243 |
+
$this->action(self::ACTION_DELETE_A_B);
|
244 |
+
|
245 |
+
while ($this->a !== null) {
|
246 |
+
switch ($this->a) {
|
247 |
+
case ' ':
|
248 |
+
if ($this->isAlphaNum($this->b)) {
|
249 |
+
$this->action(self::ACTION_KEEP_A);
|
250 |
+
} else {
|
251 |
+
$this->action(self::ACTION_DELETE_A);
|
252 |
+
}
|
253 |
+
break;
|
254 |
+
|
255 |
+
case "\n":
|
256 |
+
switch ($this->b) {
|
257 |
+
case '{':
|
258 |
+
case '[':
|
259 |
+
case '(':
|
260 |
+
case '+':
|
261 |
+
case '-':
|
262 |
+
case '!':
|
263 |
+
case '~':
|
264 |
+
$this->action(self::ACTION_KEEP_A);
|
265 |
+
break;
|
266 |
+
|
267 |
+
case ' ':
|
268 |
+
$this->action(self::ACTION_DELETE_A_B);
|
269 |
+
break;
|
270 |
+
|
271 |
+
default:
|
272 |
+
if ($this->isAlphaNum($this->b)) {
|
273 |
+
$this->action(self::ACTION_KEEP_A);
|
274 |
+
}
|
275 |
+
else {
|
276 |
+
$this->action(self::ACTION_DELETE_A);
|
277 |
+
}
|
278 |
+
}
|
279 |
+
break;
|
280 |
+
|
281 |
+
default:
|
282 |
+
switch ($this->b) {
|
283 |
+
case ' ':
|
284 |
+
if ($this->isAlphaNum($this->a)) {
|
285 |
+
$this->action(self::ACTION_KEEP_A);
|
286 |
+
break;
|
287 |
+
}
|
288 |
+
|
289 |
+
$this->action(self::ACTION_DELETE_A_B);
|
290 |
+
break;
|
291 |
+
|
292 |
+
case "\n":
|
293 |
+
switch ($this->a) {
|
294 |
+
case '}':
|
295 |
+
case ']':
|
296 |
+
case ')':
|
297 |
+
case '+':
|
298 |
+
case '-':
|
299 |
+
case '"':
|
300 |
+
case "'":
|
301 |
+
$this->action(self::ACTION_KEEP_A);
|
302 |
+
break;
|
303 |
+
|
304 |
+
default:
|
305 |
+
if ($this->isAlphaNum($this->a)) {
|
306 |
+
$this->action(self::ACTION_KEEP_A);
|
307 |
+
}
|
308 |
+
else {
|
309 |
+
$this->action(self::ACTION_DELETE_A_B);
|
310 |
+
}
|
311 |
+
}
|
312 |
+
break;
|
313 |
+
|
314 |
+
default:
|
315 |
+
$this->action(self::ACTION_KEEP_A);
|
316 |
+
break;
|
317 |
+
}
|
318 |
+
}
|
319 |
+
}
|
320 |
+
|
321 |
+
return $this->output;
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Get the next character, skipping over comments. peek() is used to see
|
326 |
+
* if a '/' is followed by a '/' or '*'.
|
327 |
+
*
|
328 |
+
* @uses get()
|
329 |
+
* @uses peek()
|
330 |
+
* @throws JSMinException On unterminated comment.
|
331 |
+
* @return string
|
332 |
+
*/
|
333 |
+
protected function next() {
|
334 |
+
$c = $this->get();
|
335 |
+
|
336 |
+
if ($c === '/') {
|
337 |
+
switch($this->peek()) {
|
338 |
+
case '/':
|
339 |
+
for (;;) {
|
340 |
+
$c = $this->get();
|
341 |
+
|
342 |
+
if (ord($c) <= self::ORD_LF) {
|
343 |
+
return $c;
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
case '*':
|
348 |
+
$this->get();
|
349 |
+
|
350 |
+
for (;;) {
|
351 |
+
switch($this->get()) {
|
352 |
+
case '*':
|
353 |
+
if ($this->peek() === '/') {
|
354 |
+
$this->get();
|
355 |
+
return ' ';
|
356 |
+
}
|
357 |
+
break;
|
358 |
+
|
359 |
+
case null:
|
360 |
+
throw new JSMinException('Unterminated comment.');
|
361 |
+
}
|
362 |
+
}
|
363 |
+
|
364 |
+
default:
|
365 |
+
return $c;
|
366 |
+
}
|
367 |
+
}
|
368 |
+
|
369 |
+
return $c;
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Get next char. If is ctrl character, translate to a space or newline.
|
374 |
+
*
|
375 |
+
* @uses get()
|
376 |
+
* @return string|null
|
377 |
+
*/
|
378 |
+
protected function peek() {
|
379 |
+
$this->lookAhead = $this->get();
|
380 |
+
return $this->lookAhead;
|
381 |
+
}
|
382 |
+
}
|
383 |
+
|
384 |
+
// -- Exceptions ---------------------------------------------------------------
|
385 |
+
class JSMinException extends Exception {}
|
386 |
+
?>
|
libs/matthiasmullie/index.html
DELETED
File without changes
|
libs/matthiasmullie/minify/bin/index.html
DELETED
File without changes
|
libs/matthiasmullie/minify/bin/minifycss
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
#!/usr/bin/env php
|
2 |
-
<?php
|
3 |
-
use MatthiasMullie\Minify;
|
4 |
-
|
5 |
-
// command line utility to minify CSS
|
6 |
-
if (file_exists(__DIR__ . '/../../../autoload.php')) {
|
7 |
-
// if composer install
|
8 |
-
require_once __DIR__ . '/../../../autoload.php';
|
9 |
-
} else {
|
10 |
-
require_once __DIR__ . '/../src/Minify.php';
|
11 |
-
require_once __DIR__ . '/../src/CSS.php';
|
12 |
-
require_once __DIR__ . '/../src/Exception.php';
|
13 |
-
}
|
14 |
-
|
15 |
-
error_reporting(E_ALL);
|
16 |
-
// check PHP setup for cli arguments
|
17 |
-
if (!isset($_SERVER['argv']) && !isset($argv)) {
|
18 |
-
fwrite(STDERR, 'Please enable the "register_argc_argv" directive in your php.ini' . PHP_EOL);
|
19 |
-
exit(1);
|
20 |
-
} elseif (!isset($argv)) {
|
21 |
-
$argv = $_SERVER['argv'];
|
22 |
-
}
|
23 |
-
// check if path to file given
|
24 |
-
if (!isset($argv[1])) {
|
25 |
-
fwrite(STDERR, 'Argument expected: path to file' . PHP_EOL);
|
26 |
-
exit(1);
|
27 |
-
}
|
28 |
-
// check if script run in cli environment
|
29 |
-
if ('cli' !== php_sapi_name()) {
|
30 |
-
fwrite(STDERR, $argv[1] . ' must be run in the command line' . PHP_EOL);
|
31 |
-
exit(1);
|
32 |
-
}
|
33 |
-
// check if source file exists
|
34 |
-
if (!file_exists($argv[1])) {
|
35 |
-
fwrite(STDERR, 'Source file "' . $argv[1] . '" not found' . PHP_EOL);
|
36 |
-
exit(1);
|
37 |
-
}
|
38 |
-
|
39 |
-
try {
|
40 |
-
$minifier = new Minify\CSS($argv[1]);
|
41 |
-
echo $minifier->minify();
|
42 |
-
} catch (Exception $e) {
|
43 |
-
fwrite(STDERR, $e->getMessage(), PHP_EOL);
|
44 |
-
exit(1);
|
45 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/bin/minifyjs
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
#!/usr/bin/env php
|
2 |
-
<?php
|
3 |
-
use MatthiasMullie\Minify;
|
4 |
-
|
5 |
-
// command line utility to minify JS
|
6 |
-
if (file_exists(__DIR__ . '/../../../autoload.php')) {
|
7 |
-
// if composer install
|
8 |
-
require_once __DIR__ . '/../../../autoload.php';
|
9 |
-
} else {
|
10 |
-
require_once __DIR__ . '/../src/Minify.php';
|
11 |
-
require_once __DIR__ . '/../src/JS.php';
|
12 |
-
require_once __DIR__ . '/../src/Exception.php';
|
13 |
-
}
|
14 |
-
|
15 |
-
error_reporting(E_ALL);
|
16 |
-
// check PHP setup for cli arguments
|
17 |
-
if (!isset($_SERVER['argv']) && !isset($argv)) {
|
18 |
-
fwrite(STDERR, 'Please enable the "register_argc_argv" directive in your php.ini' . PHP_EOL);
|
19 |
-
exit(1);
|
20 |
-
} elseif (!isset($argv)) {
|
21 |
-
$argv = $_SERVER['argv'];
|
22 |
-
}
|
23 |
-
// check if path to file given
|
24 |
-
if (!isset($argv[1])) {
|
25 |
-
fwrite(STDERR, 'Argument expected: path to file' . PHP_EOL);
|
26 |
-
exit(1);
|
27 |
-
}
|
28 |
-
// check if script run in cli environment
|
29 |
-
if ('cli' !== php_sapi_name()) {
|
30 |
-
fwrite(STDERR, $argv[1] . ' must be run in the command line' . PHP_EOL);
|
31 |
-
exit(1);
|
32 |
-
}
|
33 |
-
// check if source file exists
|
34 |
-
if (!file_exists($argv[1])) {
|
35 |
-
fwrite(STDERR, 'Source file "' . $argv[1] . '" not found' . PHP_EOL);
|
36 |
-
exit(1);
|
37 |
-
}
|
38 |
-
|
39 |
-
try {
|
40 |
-
$minifier = new Minify\JS($argv[1]);
|
41 |
-
echo $minifier->minify();
|
42 |
-
} catch (Exception $e) {
|
43 |
-
fwrite(STDERR, $e->getMessage(), PHP_EOL);
|
44 |
-
exit(1);
|
45 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/data/index.html
DELETED
File without changes
|
libs/matthiasmullie/minify/data/js/index.html
DELETED
File without changes
|
libs/matthiasmullie/minify/data/js/keywords_after.txt
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
in
|
2 |
-
public
|
3 |
-
extends
|
4 |
-
private
|
5 |
-
protected
|
6 |
-
implements
|
7 |
-
instanceof
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/data/js/keywords_before.txt
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
do
|
2 |
-
in
|
3 |
-
let
|
4 |
-
new
|
5 |
-
var
|
6 |
-
case
|
7 |
-
else
|
8 |
-
enum
|
9 |
-
void
|
10 |
-
with
|
11 |
-
class
|
12 |
-
const
|
13 |
-
yield
|
14 |
-
delete
|
15 |
-
export
|
16 |
-
import
|
17 |
-
public
|
18 |
-
static
|
19 |
-
typeof
|
20 |
-
extends
|
21 |
-
package
|
22 |
-
private
|
23 |
-
function
|
24 |
-
protected
|
25 |
-
implements
|
26 |
-
instanceof
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/data/js/keywords_reserved.txt
DELETED
@@ -1,63 +0,0 @@
|
|
1 |
-
do
|
2 |
-
if
|
3 |
-
in
|
4 |
-
for
|
5 |
-
let
|
6 |
-
new
|
7 |
-
try
|
8 |
-
var
|
9 |
-
case
|
10 |
-
else
|
11 |
-
enum
|
12 |
-
eval
|
13 |
-
null
|
14 |
-
this
|
15 |
-
true
|
16 |
-
void
|
17 |
-
with
|
18 |
-
break
|
19 |
-
catch
|
20 |
-
class
|
21 |
-
const
|
22 |
-
false
|
23 |
-
super
|
24 |
-
throw
|
25 |
-
while
|
26 |
-
yield
|
27 |
-
delete
|
28 |
-
export
|
29 |
-
import
|
30 |
-
public
|
31 |
-
return
|
32 |
-
static
|
33 |
-
switch
|
34 |
-
typeof
|
35 |
-
default
|
36 |
-
extends
|
37 |
-
finally
|
38 |
-
package
|
39 |
-
private
|
40 |
-
continue
|
41 |
-
debugger
|
42 |
-
function
|
43 |
-
arguments
|
44 |
-
interface
|
45 |
-
protected
|
46 |
-
implements
|
47 |
-
instanceof
|
48 |
-
abstract
|
49 |
-
boolean
|
50 |
-
byte
|
51 |
-
char
|
52 |
-
double
|
53 |
-
final
|
54 |
-
float
|
55 |
-
goto
|
56 |
-
int
|
57 |
-
long
|
58 |
-
native
|
59 |
-
short
|
60 |
-
synchronized
|
61 |
-
throws
|
62 |
-
transient
|
63 |
-
volatile
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/data/js/operators.txt
DELETED
@@ -1,46 +0,0 @@
|
|
1 |
-
+
|
2 |
-
-
|
3 |
-
*
|
4 |
-
/
|
5 |
-
%
|
6 |
-
=
|
7 |
-
+=
|
8 |
-
-=
|
9 |
-
*=
|
10 |
-
/=
|
11 |
-
%=
|
12 |
-
<<=
|
13 |
-
>>=
|
14 |
-
>>>=
|
15 |
-
&=
|
16 |
-
^=
|
17 |
-
|=
|
18 |
-
&
|
19 |
-
|
|
20 |
-
^
|
21 |
-
~
|
22 |
-
<<
|
23 |
-
>>
|
24 |
-
>>>
|
25 |
-
==
|
26 |
-
===
|
27 |
-
!=
|
28 |
-
!==
|
29 |
-
>
|
30 |
-
<
|
31 |
-
>=
|
32 |
-
<=
|
33 |
-
&&
|
34 |
-
||
|
35 |
-
!
|
36 |
-
.
|
37 |
-
[
|
38 |
-
]
|
39 |
-
?
|
40 |
-
:
|
41 |
-
,
|
42 |
-
;
|
43 |
-
(
|
44 |
-
)
|
45 |
-
{
|
46 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/data/js/operators_after.txt
DELETED
@@ -1,43 +0,0 @@
|
|
1 |
-
+
|
2 |
-
-
|
3 |
-
*
|
4 |
-
/
|
5 |
-
%
|
6 |
-
=
|
7 |
-
+=
|
8 |
-
-=
|
9 |
-
*=
|
10 |
-
/=
|
11 |
-
%=
|
12 |
-
<<=
|
13 |
-
>>=
|
14 |
-
>>>=
|
15 |
-
&=
|
16 |
-
^=
|
17 |
-
|=
|
18 |
-
&
|
19 |
-
|
|
20 |
-
^
|
21 |
-
<<
|
22 |
-
>>
|
23 |
-
>>>
|
24 |
-
==
|
25 |
-
===
|
26 |
-
!=
|
27 |
-
!==
|
28 |
-
>
|
29 |
-
<
|
30 |
-
>=
|
31 |
-
<=
|
32 |
-
&&
|
33 |
-
||
|
34 |
-
.
|
35 |
-
[
|
36 |
-
]
|
37 |
-
?
|
38 |
-
:
|
39 |
-
,
|
40 |
-
;
|
41 |
-
(
|
42 |
-
)
|
43 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/data/js/operators_before.txt
DELETED
@@ -1,43 +0,0 @@
|
|
1 |
-
+
|
2 |
-
-
|
3 |
-
*
|
4 |
-
/
|
5 |
-
%
|
6 |
-
=
|
7 |
-
+=
|
8 |
-
-=
|
9 |
-
*=
|
10 |
-
/=
|
11 |
-
%=
|
12 |
-
<<=
|
13 |
-
>>=
|
14 |
-
>>>=
|
15 |
-
&=
|
16 |
-
^=
|
17 |
-
|=
|
18 |
-
&
|
19 |
-
|
|
20 |
-
^
|
21 |
-
~
|
22 |
-
<<
|
23 |
-
>>
|
24 |
-
>>>
|
25 |
-
==
|
26 |
-
===
|
27 |
-
!=
|
28 |
-
!==
|
29 |
-
>
|
30 |
-
<
|
31 |
-
>=
|
32 |
-
<=
|
33 |
-
&&
|
34 |
-
||
|
35 |
-
!
|
36 |
-
.
|
37 |
-
[
|
38 |
-
?
|
39 |
-
:
|
40 |
-
,
|
41 |
-
;
|
42 |
-
(
|
43 |
-
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/index.html
DELETED
File without changes
|
libs/matthiasmullie/minify/src/CSS.php
DELETED
@@ -1,735 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* CSS Minifier
|
4 |
-
*
|
5 |
-
* Please report bugs on https://github.com/matthiasmullie/minify/issues
|
6 |
-
*
|
7 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
8 |
-
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
|
9 |
-
* @license MIT License
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace MatthiasMullie\Minify;
|
13 |
-
|
14 |
-
use MatthiasMullie\Minify\Exceptions\FileImportException;
|
15 |
-
use MatthiasMullie\PathConverter\ConverterInterface;
|
16 |
-
use MatthiasMullie\PathConverter\Converter;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* CSS minifier
|
20 |
-
*
|
21 |
-
* Please report bugs on https://github.com/matthiasmullie/minify/issues
|
22 |
-
*
|
23 |
-
* @package Minify
|
24 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
25 |
-
* @author Tijs Verkoyen <minify@verkoyen.eu>
|
26 |
-
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
|
27 |
-
* @license MIT License
|
28 |
-
*/
|
29 |
-
class CSS extends Minify
|
30 |
-
{
|
31 |
-
/**
|
32 |
-
* @var int maximum inport size in kB
|
33 |
-
*/
|
34 |
-
protected $maxImportSize = 5;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* @var string[] valid import extensions
|
38 |
-
*/
|
39 |
-
protected $importExtensions = array(
|
40 |
-
'gif' => 'data:image/gif',
|
41 |
-
'png' => 'data:image/png',
|
42 |
-
'jpe' => 'data:image/jpeg',
|
43 |
-
'jpg' => 'data:image/jpeg',
|
44 |
-
'jpeg' => 'data:image/jpeg',
|
45 |
-
'svg' => 'data:image/svg+xml',
|
46 |
-
'woff' => 'data:application/x-font-woff',
|
47 |
-
'tif' => 'image/tiff',
|
48 |
-
'tiff' => 'image/tiff',
|
49 |
-
'xbm' => 'image/x-xbitmap',
|
50 |
-
);
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Set the maximum size if files to be imported.
|
54 |
-
*
|
55 |
-
* Files larger than this size (in kB) will not be imported into the CSS.
|
56 |
-
* Importing files into the CSS as data-uri will save you some connections,
|
57 |
-
* but we should only import relatively small decorative images so that our
|
58 |
-
* CSS file doesn't get too bulky.
|
59 |
-
*
|
60 |
-
* @param int $size Size in kB
|
61 |
-
*/
|
62 |
-
public function setMaxImportSize($size)
|
63 |
-
{
|
64 |
-
$this->maxImportSize = $size;
|
65 |
-
}
|
66 |
-
|
67 |
-
/**
|
68 |
-
* Set the type of extensions to be imported into the CSS (to save network
|
69 |
-
* connections).
|
70 |
-
* Keys of the array should be the file extensions & respective values
|
71 |
-
* should be the data type.
|
72 |
-
*
|
73 |
-
* @param string[] $extensions Array of file extensions
|
74 |
-
*/
|
75 |
-
public function setImportExtensions(array $extensions)
|
76 |
-
{
|
77 |
-
$this->importExtensions = $extensions;
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Move any import statements to the top.
|
82 |
-
*
|
83 |
-
* @param string $content Nearly finished CSS content
|
84 |
-
*
|
85 |
-
* @return string
|
86 |
-
*/
|
87 |
-
protected function moveImportsToTop($content)
|
88 |
-
{
|
89 |
-
if (preg_match_all('/(;?)(@import (?<url>url\()?(?P<quotes>["\']?).+?(?P=quotes)(?(url)\)))/', $content, $matches)) {
|
90 |
-
// remove from content
|
91 |
-
foreach ($matches[0] as $import) {
|
92 |
-
$content = str_replace($import, '', $content);
|
93 |
-
}
|
94 |
-
|
95 |
-
// add to top
|
96 |
-
$content = implode(';', $matches[2]).';'.trim($content, ';');
|
97 |
-
}
|
98 |
-
|
99 |
-
return $content;
|
100 |
-
}
|
101 |
-
|
102 |
-
/**
|
103 |
-
* Combine CSS from import statements.
|
104 |
-
*
|
105 |
-
* @import's will be loaded and their content merged into the original file,
|
106 |
-
* to save HTTP requests.
|
107 |
-
*
|
108 |
-
* @param string $source The file to combine imports for
|
109 |
-
* @param string $content The CSS content to combine imports for
|
110 |
-
* @param string[] $parents Parent paths, for circular reference checks
|
111 |
-
*
|
112 |
-
* @return string
|
113 |
-
*
|
114 |
-
* @throws FileImportException
|
115 |
-
*/
|
116 |
-
protected function combineImports($source, $content, $parents)
|
117 |
-
{
|
118 |
-
$importRegexes = array(
|
119 |
-
// @import url(xxx)
|
120 |
-
'/
|
121 |
-
# import statement
|
122 |
-
@import
|
123 |
-
|
124 |
-
# whitespace
|
125 |
-
\s+
|
126 |
-
|
127 |
-
# open url()
|
128 |
-
url\(
|
129 |
-
|
130 |
-
# (optional) open path enclosure
|
131 |
-
(?P<quotes>["\']?)
|
132 |
-
|
133 |
-
# fetch path
|
134 |
-
(?P<path>.+?)
|
135 |
-
|
136 |
-
# (optional) close path enclosure
|
137 |
-
(?P=quotes)
|
138 |
-
|
139 |
-
# close url()
|
140 |
-
\)
|
141 |
-
|
142 |
-
# (optional) trailing whitespace
|
143 |
-
\s*
|
144 |
-
|
145 |
-
# (optional) media statement(s)
|
146 |
-
(?P<media>[^;]*)
|
147 |
-
|
148 |
-
# (optional) trailing whitespace
|
149 |
-
\s*
|
150 |
-
|
151 |
-
# (optional) closing semi-colon
|
152 |
-
;?
|
153 |
-
|
154 |
-
/ix',
|
155 |
-
|
156 |
-
// @import 'xxx'
|
157 |
-
'/
|
158 |
-
|
159 |
-
# import statement
|
160 |
-
@import
|
161 |
-
|
162 |
-
# whitespace
|
163 |
-
\s+
|
164 |
-
|
165 |
-
# open path enclosure
|
166 |
-
(?P<quotes>["\'])
|
167 |
-
|
168 |
-
# fetch path
|
169 |
-
(?P<path>.+?)
|
170 |
-
|
171 |
-
# close path enclosure
|
172 |
-
(?P=quotes)
|
173 |
-
|
174 |
-
# (optional) trailing whitespace
|
175 |
-
\s*
|
176 |
-
|
177 |
-
# (optional) media statement(s)
|
178 |
-
(?P<media>[^;]*)
|
179 |
-
|
180 |
-
# (optional) trailing whitespace
|
181 |
-
\s*
|
182 |
-
|
183 |
-
# (optional) closing semi-colon
|
184 |
-
;?
|
185 |
-
|
186 |
-
/ix',
|
187 |
-
);
|
188 |
-
|
189 |
-
// find all relative imports in css
|
190 |
-
$matches = array();
|
191 |
-
foreach ($importRegexes as $importRegex) {
|
192 |
-
if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) {
|
193 |
-
$matches = array_merge($matches, $regexMatches);
|
194 |
-
}
|
195 |
-
}
|
196 |
-
|
197 |
-
$search = array();
|
198 |
-
$replace = array();
|
199 |
-
|
200 |
-
// loop the matches
|
201 |
-
foreach ($matches as $match) {
|
202 |
-
// get the path for the file that will be imported
|
203 |
-
$importPath = dirname($source).'/'.$match['path'];
|
204 |
-
|
205 |
-
// only replace the import with the content if we can grab the
|
206 |
-
// content of the file
|
207 |
-
if (!$this->canImportByPath($match['path']) || !$this->canImportFile($importPath)) {
|
208 |
-
continue;
|
209 |
-
}
|
210 |
-
|
211 |
-
// check if current file was not imported previously in the same
|
212 |
-
// import chain.
|
213 |
-
if (in_array($importPath, $parents)) {
|
214 |
-
throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.');
|
215 |
-
}
|
216 |
-
|
217 |
-
// grab referenced file & minify it (which may include importing
|
218 |
-
// yet other @import statements recursively)
|
219 |
-
$minifier = new static($importPath);
|
220 |
-
$importContent = $minifier->execute($source, $parents);
|
221 |
-
|
222 |
-
// check if this is only valid for certain media
|
223 |
-
if (!empty($match['media'])) {
|
224 |
-
$importContent = '@media '.$match['media'].'{'.$importContent.'}';
|
225 |
-
}
|
226 |
-
|
227 |
-
// add to replacement array
|
228 |
-
$search[] = $match[0];
|
229 |
-
$replace[] = $importContent;
|
230 |
-
}
|
231 |
-
|
232 |
-
// replace the import statements
|
233 |
-
return str_replace($search, $replace, $content);
|
234 |
-
}
|
235 |
-
|
236 |
-
/**
|
237 |
-
* Import files into the CSS, base64-ized.
|
238 |
-
*
|
239 |
-
* @url(image.jpg) images will be loaded and their content merged into the
|
240 |
-
* original file, to save HTTP requests.
|
241 |
-
*
|
242 |
-
* @param string $source The file to import files for
|
243 |
-
* @param string $content The CSS content to import files for
|
244 |
-
*
|
245 |
-
* @return string
|
246 |
-
*/
|
247 |
-
protected function importFiles($source, $content)
|
248 |
-
{
|
249 |
-
$regex = '/url\((["\']?)(.+?)\\1\)/i';
|
250 |
-
if ($this->importExtensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {
|
251 |
-
$search = array();
|
252 |
-
$replace = array();
|
253 |
-
|
254 |
-
// loop the matches
|
255 |
-
foreach ($matches as $match) {
|
256 |
-
$extension = substr(strrchr($match[2], '.'), 1);
|
257 |
-
if ($extension && !array_key_exists($extension, $this->importExtensions)) {
|
258 |
-
continue;
|
259 |
-
}
|
260 |
-
|
261 |
-
// get the path for the file that will be imported
|
262 |
-
$path = $match[2];
|
263 |
-
$path = dirname($source).'/'.$path;
|
264 |
-
|
265 |
-
// only replace the import with the content if we're able to get
|
266 |
-
// the content of the file, and it's relatively small
|
267 |
-
if ($this->canImportFile($path) && $this->canImportBySize($path)) {
|
268 |
-
// grab content && base64-ize
|
269 |
-
$importContent = $this->load($path);
|
270 |
-
$importContent = base64_encode($importContent);
|
271 |
-
|
272 |
-
// build replacement
|
273 |
-
$search[] = $match[0];
|
274 |
-
$replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')';
|
275 |
-
}
|
276 |
-
}
|
277 |
-
|
278 |
-
// replace the import statements
|
279 |
-
$content = str_replace($search, $replace, $content);
|
280 |
-
}
|
281 |
-
|
282 |
-
return $content;
|
283 |
-
}
|
284 |
-
|
285 |
-
/**
|
286 |
-
* Minify the data.
|
287 |
-
* Perform CSS optimizations.
|
288 |
-
*
|
289 |
-
* @param string[optional] $path Path to write the data to
|
290 |
-
* @param string[] $parents Parent paths, for circular reference checks
|
291 |
-
*
|
292 |
-
* @return string The minified data
|
293 |
-
*/
|
294 |
-
public function execute($path = null, $parents = array())
|
295 |
-
{
|
296 |
-
$content = '';
|
297 |
-
|
298 |
-
// loop CSS data (raw data and files)
|
299 |
-
foreach ($this->data as $source => $css) {
|
300 |
-
/*
|
301 |
-
* Let's first take out strings & comments, since we can't just
|
302 |
-
* remove whitespace anywhere. If whitespace occurs inside a string,
|
303 |
-
* we should leave it alone. E.g.:
|
304 |
-
* p { content: "a test" }
|
305 |
-
*/
|
306 |
-
$this->extractStrings();
|
307 |
-
$this->stripComments();
|
308 |
-
$css = $this->replace($css);
|
309 |
-
|
310 |
-
$css = $this->stripWhitespace($css);
|
311 |
-
$css = $this->shortenHex($css);
|
312 |
-
$css = $this->shortenZeroes($css);
|
313 |
-
$css = $this->shortenFontWeights($css);
|
314 |
-
$css = $this->stripEmptyTags($css);
|
315 |
-
|
316 |
-
// restore the string we've extracted earlier
|
317 |
-
$css = $this->restoreExtractedData($css);
|
318 |
-
|
319 |
-
$source = is_int($source) ? '' : $source;
|
320 |
-
$parents = $source ? array_merge($parents, array($source)) : $parents;
|
321 |
-
$css = $this->combineImports($source, $css, $parents);
|
322 |
-
$css = $this->importFiles($source, $css);
|
323 |
-
|
324 |
-
/*
|
325 |
-
* If we'll save to a new path, we'll have to fix the relative paths
|
326 |
-
* to be relative no longer to the source file, but to the new path.
|
327 |
-
* If we don't write to a file, fall back to same path so no
|
328 |
-
* conversion happens (because we still want it to go through most
|
329 |
-
* of the move code, which also addresses url() & @import syntax...)
|
330 |
-
*/
|
331 |
-
$converter = $this->getPathConverter($source, $path ?: $source);
|
332 |
-
$css = $this->move($converter, $css);
|
333 |
-
|
334 |
-
// combine css
|
335 |
-
$content .= $css;
|
336 |
-
}
|
337 |
-
|
338 |
-
$content = $this->moveImportsToTop($content);
|
339 |
-
|
340 |
-
return $content;
|
341 |
-
}
|
342 |
-
|
343 |
-
/**
|
344 |
-
* Moving a css file should update all relative urls.
|
345 |
-
* Relative references (e.g. ../images/image.gif) in a certain css file,
|
346 |
-
* will have to be updated when a file is being saved at another location
|
347 |
-
* (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper).
|
348 |
-
*
|
349 |
-
* @param ConverterInterface $converter Relative path converter
|
350 |
-
* @param string $content The CSS content to update relative urls for
|
351 |
-
*
|
352 |
-
* @return string
|
353 |
-
*/
|
354 |
-
protected function move(ConverterInterface $converter, $content)
|
355 |
-
{
|
356 |
-
/*
|
357 |
-
* Relative path references will usually be enclosed by url(). @import
|
358 |
-
* is an exception, where url() is not necessary around the path (but is
|
359 |
-
* allowed).
|
360 |
-
* This *could* be 1 regular expression, where both regular expressions
|
361 |
-
* in this array are on different sides of a |. But we're using named
|
362 |
-
* patterns in both regexes, the same name on both regexes. This is only
|
363 |
-
* possible with a (?J) modifier, but that only works after a fairly
|
364 |
-
* recent PCRE version. That's why I'm doing 2 separate regular
|
365 |
-
* expressions & combining the matches after executing of both.
|
366 |
-
*/
|
367 |
-
$relativeRegexes = array(
|
368 |
-
// url(xxx)
|
369 |
-
'/
|
370 |
-
# open url()
|
371 |
-
url\(
|
372 |
-
|
373 |
-
\s*
|
374 |
-
|
375 |
-
# open path enclosure
|
376 |
-
(?P<quotes>["\'])?
|
377 |
-
|
378 |
-
# fetch path
|
379 |
-
(?P<path>.+?)
|
380 |
-
|
381 |
-
# close path enclosure
|
382 |
-
(?(quotes)(?P=quotes))
|
383 |
-
|
384 |
-
\s*
|
385 |
-
|
386 |
-
# close url()
|
387 |
-
\)
|
388 |
-
|
389 |
-
/ix',
|
390 |
-
|
391 |
-
// @import "xxx"
|
392 |
-
'/
|
393 |
-
# import statement
|
394 |
-
@import
|
395 |
-
|
396 |
-
# whitespace
|
397 |
-
\s+
|
398 |
-
|
399 |
-
# we don\'t have to check for @import url(), because the
|
400 |
-
# condition above will already catch these
|
401 |
-
|
402 |
-
# open path enclosure
|
403 |
-
(?P<quotes>["\'])
|
404 |
-
|
405 |
-
# fetch path
|
406 |
-
(?P<path>.+?)
|
407 |
-
|
408 |
-
# close path enclosure
|
409 |
-
(?P=quotes)
|
410 |
-
|
411 |
-
/ix',
|
412 |
-
);
|
413 |
-
|
414 |
-
// find all relative urls in css
|
415 |
-
$matches = array();
|
416 |
-
foreach ($relativeRegexes as $relativeRegex) {
|
417 |
-
if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) {
|
418 |
-
$matches = array_merge($matches, $regexMatches);
|
419 |
-
}
|
420 |
-
}
|
421 |
-
|
422 |
-
$search = array();
|
423 |
-
$replace = array();
|
424 |
-
|
425 |
-
// loop all urls
|
426 |
-
foreach ($matches as $match) {
|
427 |
-
// determine if it's a url() or an @import match
|
428 |
-
$type = (strpos($match[0], '@import') === 0 ? 'import' : 'url');
|
429 |
-
|
430 |
-
$url = $match['path'];
|
431 |
-
if ($this->canImportByPath($url)) {
|
432 |
-
// attempting to interpret GET-params makes no sense, so let's discard them for awhile
|
433 |
-
$params = strrchr($url, '?');
|
434 |
-
$url = $params ? substr($url, 0, -strlen($params)) : $url;
|
435 |
-
|
436 |
-
// fix relative url
|
437 |
-
$url = $converter->convert($url);
|
438 |
-
|
439 |
-
// now that the path has been converted, re-apply GET-params
|
440 |
-
$url .= $params;
|
441 |
-
}
|
442 |
-
|
443 |
-
/*
|
444 |
-
* Urls with control characters above 0x7e should be quoted.
|
445 |
-
* According to Mozilla's parser, whitespace is only allowed at the
|
446 |
-
* end of unquoted urls.
|
447 |
-
* Urls with `)` (as could happen with data: uris) should also be
|
448 |
-
* quoted to avoid being confused for the url() closing parentheses.
|
449 |
-
* And urls with a # have also been reported to cause issues.
|
450 |
-
* Urls with quotes inside should also remain escaped.
|
451 |
-
*
|
452 |
-
* @see https://developer.mozilla.org/nl/docs/Web/CSS/url#The_url()_functional_notation
|
453 |
-
* @see https://hg.mozilla.org/mozilla-central/rev/14abca4e7378
|
454 |
-
* @see https://github.com/matthiasmullie/minify/issues/193
|
455 |
-
*/
|
456 |
-
$url = trim($url);
|
457 |
-
if (preg_match('/[\s\)\'"#\x{7f}-\x{9f}]/u', $url)) {
|
458 |
-
$url = $match['quotes'] . $url . $match['quotes'];
|
459 |
-
}
|
460 |
-
|
461 |
-
// build replacement
|
462 |
-
$search[] = $match[0];
|
463 |
-
if ($type === 'url') {
|
464 |
-
$replace[] = 'url('.$url.')';
|
465 |
-
} elseif ($type === 'import') {
|
466 |
-
$replace[] = '@import "'.$url.'"';
|
467 |
-
}
|
468 |
-
}
|
469 |
-
|
470 |
-
// replace urls
|
471 |
-
return str_replace($search, $replace, $content);
|
472 |
-
}
|
473 |
-
|
474 |
-
/**
|
475 |
-
* Shorthand hex color codes.
|
476 |
-
* #FF0000 -> #F00.
|
477 |
-
*
|
478 |
-
* @param string $content The CSS content to shorten the hex color codes for
|
479 |
-
*
|
480 |
-
* @return string
|
481 |
-
*/
|
482 |
-
protected function shortenHex($content)
|
483 |
-
{
|
484 |
-
$content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?=[; }])/i', '#$1$2$3', $content);
|
485 |
-
|
486 |
-
// we can shorten some even more by replacing them with their color name
|
487 |
-
$colors = array(
|
488 |
-
'#F0FFFF' => 'azure',
|
489 |
-
'#F5F5DC' => 'beige',
|
490 |
-
'#A52A2A' => 'brown',
|
491 |
-
'#FF7F50' => 'coral',
|
492 |
-
'#FFD700' => 'gold',
|
493 |
-
'#808080' => 'gray',
|
494 |
-
'#008000' => 'green',
|
495 |
-
'#4B0082' => 'indigo',
|
496 |
-
'#FFFFF0' => 'ivory',
|
497 |
-
'#F0E68C' => 'khaki',
|
498 |
-
'#FAF0E6' => 'linen',
|
499 |
-
'#800000' => 'maroon',
|
500 |
-
'#000080' => 'navy',
|
501 |
-
'#808000' => 'olive',
|
502 |
-
'#CD853F' => 'peru',
|
503 |
-
'#FFC0CB' => 'pink',
|
504 |
-
'#DDA0DD' => 'plum',
|
505 |
-
'#800080' => 'purple',
|
506 |
-
'#F00' => 'red',
|
507 |
-
'#FA8072' => 'salmon',
|
508 |
-
'#A0522D' => 'sienna',
|
509 |
-
'#C0C0C0' => 'silver',
|
510 |
-
'#FFFAFA' => 'snow',
|
511 |
-
'#D2B48C' => 'tan',
|
512 |
-
'#FF6347' => 'tomato',
|
513 |
-
'#EE82EE' => 'violet',
|
514 |
-
'#F5DEB3' => 'wheat',
|
515 |
-
);
|
516 |
-
|
517 |
-
return preg_replace_callback(
|
518 |
-
'/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i',
|
519 |
-
function ($match) use ($colors) {
|
520 |
-
return $colors[strtoupper($match[0])];
|
521 |
-
},
|
522 |
-
$content
|
523 |
-
);
|
524 |
-
}
|
525 |
-
|
526 |
-
/**
|
527 |
-
* Shorten CSS font weights.
|
528 |
-
*
|
529 |
-
* @param string $content The CSS content to shorten the font weights for
|
530 |
-
*
|
531 |
-
* @return string
|
532 |
-
*/
|
533 |
-
protected function shortenFontWeights($content)
|
534 |
-
{
|
535 |
-
$weights = array(
|
536 |
-
'normal' => 400,
|
537 |
-
'bold' => 700,
|
538 |
-
);
|
539 |
-
|
540 |
-
$callback = function ($match) use ($weights) {
|
541 |
-
return $match[1].$weights[$match[2]];
|
542 |
-
};
|
543 |
-
|
544 |
-
return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content);
|
545 |
-
}
|
546 |
-
|
547 |
-
/**
|
548 |
-
* Shorthand 0 values to plain 0, instead of e.g. -0em.
|
549 |
-
*
|
550 |
-
* @param string $content The CSS content to shorten the zero values for
|
551 |
-
*
|
552 |
-
* @return string
|
553 |
-
*/
|
554 |
-
protected function shortenZeroes($content)
|
555 |
-
{
|
556 |
-
// we don't want to strip units in `calc()` expressions:
|
557 |
-
// `5px - 0px` is valid, but `5px - 0` is not
|
558 |
-
// `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
|
559 |
-
// `10 * 0` is invalid
|
560 |
-
// best to just leave `calc()`s alone, even if they could be optimized
|
561 |
-
// (which is a whole other undertaking, where units & order of
|
562 |
-
// operations all need to be considered...)
|
563 |
-
$calcs = $this->findCalcs($content);
|
564 |
-
$content = str_replace($calcs, array_keys($calcs), $content);
|
565 |
-
|
566 |
-
// reusable bits of code throughout these regexes:
|
567 |
-
// before & after are used to make sure we don't match lose unintended
|
568 |
-
// 0-like values (e.g. in #000, or in http://url/1.0)
|
569 |
-
// units can be stripped from 0 values, or used to recognize non 0
|
570 |
-
// values (where wa may be able to strip a .0 suffix)
|
571 |
-
$before = '(?<=[:(, ])';
|
572 |
-
$after = '(?=[ ,);}])';
|
573 |
-
$units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)';
|
574 |
-
|
575 |
-
// strip units after zeroes (0px -> 0)
|
576 |
-
// NOTE: it should be safe to remove all units for a 0 value, but in
|
577 |
-
// practice, Webkit (especially Safari) seems to stumble over at least
|
578 |
-
// 0%, potentially other units as well. Only stripping 'px' for now.
|
579 |
-
// @see https://github.com/matthiasmullie/minify/issues/60
|
580 |
-
$content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content);
|
581 |
-
|
582 |
-
// strip 0-digits (.0 -> 0)
|
583 |
-
$content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content);
|
584 |
-
// strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px
|
585 |
-
$content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content);
|
586 |
-
// strip trailing 0: 50.00 -> 50, 50.00px -> 50px
|
587 |
-
$content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content);
|
588 |
-
// strip leading 0: 0.1 -> .1, 01.1 -> 1.1
|
589 |
-
$content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content);
|
590 |
-
|
591 |
-
// strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
|
592 |
-
$content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);
|
593 |
-
|
594 |
-
// IE doesn't seem to understand a unitless flex-basis value, so let's
|
595 |
-
// add it in again (make it `%`, which is only 1 char: 0%, 0px, 0
|
596 |
-
// anything, it's all just the same)
|
597 |
-
$content = preg_replace('/flex:([^ ]+ [^ ]+ )0([;\}])/', 'flex:${1}0%${2}', $content);
|
598 |
-
$content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
|
599 |
-
|
600 |
-
// restore `calc()` expressions
|
601 |
-
$content = str_replace(array_keys($calcs), $calcs, $content);
|
602 |
-
|
603 |
-
return $content;
|
604 |
-
}
|
605 |
-
|
606 |
-
/**
|
607 |
-
* Strip empty tags from source code.
|
608 |
-
*
|
609 |
-
* @param string $content
|
610 |
-
*
|
611 |
-
* @return string
|
612 |
-
*/
|
613 |
-
protected function stripEmptyTags($content)
|
614 |
-
{
|
615 |
-
$content = preg_replace('/(?<=^)[^\{\};]+\{\s*\}/', '', $content);
|
616 |
-
$content = preg_replace('/(?<=(\}|;))[^\{\};]+\{\s*\}/', '', $content);
|
617 |
-
|
618 |
-
return $content;
|
619 |
-
}
|
620 |
-
|
621 |
-
/**
|
622 |
-
* Strip comments from source code.
|
623 |
-
*/
|
624 |
-
protected function stripComments()
|
625 |
-
{
|
626 |
-
$this->registerPattern('/\/\*.*?\*\//s', '');
|
627 |
-
}
|
628 |
-
|
629 |
-
/**
|
630 |
-
* Strip whitespace.
|
631 |
-
*
|
632 |
-
* @param string $content The CSS content to strip the whitespace for
|
633 |
-
*
|
634 |
-
* @return string
|
635 |
-
*/
|
636 |
-
protected function stripWhitespace($content)
|
637 |
-
{
|
638 |
-
// remove leading & trailing whitespace
|
639 |
-
$content = preg_replace('/^\s*/m', '', $content);
|
640 |
-
$content = preg_replace('/\s*$/m', '', $content);
|
641 |
-
|
642 |
-
// replace newlines with a single space
|
643 |
-
$content = preg_replace('/\s+/', ' ', $content);
|
644 |
-
|
645 |
-
// remove whitespace around meta characters
|
646 |
-
// inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
|
647 |
-
$content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
|
648 |
-
$content = preg_replace('/([\[(:])\s+/', '$1', $content);
|
649 |
-
$content = preg_replace('/\s+([\]\)])/', '$1', $content);
|
650 |
-
$content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
|
651 |
-
|
652 |
-
// whitespace around + and - can only be stripped inside some pseudo-
|
653 |
-
// classes, like `:nth-child(3+2n)`
|
654 |
-
// not in things like `calc(3px + 2px)`, shorthands like `3px -2px`, or
|
655 |
-
// selectors like `div.weird- p`
|
656 |
-
$pseudos = array('nth-child', 'nth-last-child', 'nth-last-of-type', 'nth-of-type');
|
657 |
-
$content = preg_replace('/:('.implode('|', $pseudos).')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content);
|
658 |
-
|
659 |
-
// remove semicolon/whitespace followed by closing bracket
|
660 |
-
$content = str_replace(';}', '}', $content);
|
661 |
-
|
662 |
-
return trim($content);
|
663 |
-
}
|
664 |
-
|
665 |
-
/**
|
666 |
-
* Find all `calc()` occurrences.
|
667 |
-
*
|
668 |
-
* @param string $content The CSS content to find `calc()`s in.
|
669 |
-
*
|
670 |
-
* @return string[]
|
671 |
-
*/
|
672 |
-
protected function findCalcs($content)
|
673 |
-
{
|
674 |
-
$results = array();
|
675 |
-
preg_match_all('/calc(\(.+?)(?=$|;|calc\()/', $content, $matches, PREG_SET_ORDER);
|
676 |
-
|
677 |
-
foreach ($matches as $match) {
|
678 |
-
$length = strlen($match[1]);
|
679 |
-
$expr = '';
|
680 |
-
$opened = 0;
|
681 |
-
|
682 |
-
for ($i = 0; $i < $length; $i++) {
|
683 |
-
$char = $match[1][$i];
|
684 |
-
$expr .= $char;
|
685 |
-
if ($char === '(') {
|
686 |
-
$opened++;
|
687 |
-
} elseif ($char === ')' && --$opened === 0) {
|
688 |
-
break;
|
689 |
-
}
|
690 |
-
}
|
691 |
-
|
692 |
-
$results['calc('.count($results).')'] = 'calc'.$expr;
|
693 |
-
}
|
694 |
-
|
695 |
-
return $results;
|
696 |
-
}
|
697 |
-
|
698 |
-
/**
|
699 |
-
* Check if file is small enough to be imported.
|
700 |
-
*
|
701 |
-
* @param string $path The path to the file
|
702 |
-
*
|
703 |
-
* @return bool
|
704 |
-
*/
|
705 |
-
protected function canImportBySize($path)
|
706 |
-
{
|
707 |
-
return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024;
|
708 |
-
}
|
709 |
-
|
710 |
-
/**
|
711 |
-
* Check if file a file can be imported, going by the path.
|
712 |
-
*
|
713 |
-
* @param string $path
|
714 |
-
*
|
715 |
-
* @return bool
|
716 |
-
*/
|
717 |
-
protected function canImportByPath($path)
|
718 |
-
{
|
719 |
-
return preg_match('/^(data:|https?:|\\/)/', $path) === 0;
|
720 |
-
}
|
721 |
-
|
722 |
-
/**
|
723 |
-
* Return a converter to update relative paths to be relative to the new
|
724 |
-
* destination.
|
725 |
-
*
|
726 |
-
* @param string $source
|
727 |
-
* @param string $target
|
728 |
-
*
|
729 |
-
* @return ConverterInterface
|
730 |
-
*/
|
731 |
-
protected function getPathConverter($source, $target)
|
732 |
-
{
|
733 |
-
return new Converter($source, $target);
|
734 |
-
}
|
735 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/src/Exception.php
DELETED
@@ -1,20 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Base Exception
|
4 |
-
*
|
5 |
-
* @deprecated Use Exceptions\BasicException instead
|
6 |
-
*
|
7 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
8 |
-
*/
|
9 |
-
namespace MatthiasMullie\Minify;
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Base Exception Class
|
13 |
-
* @deprecated Use Exceptions\BasicException instead
|
14 |
-
*
|
15 |
-
* @package Minify
|
16 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
17 |
-
*/
|
18 |
-
abstract class Exception extends \Exception
|
19 |
-
{
|
20 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/src/Exceptions/BasicException.php
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Basic exception
|
4 |
-
*
|
5 |
-
* Please report bugs on https://github.com/matthiasmullie/minify/issues
|
6 |
-
*
|
7 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
8 |
-
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
|
9 |
-
* @license MIT License
|
10 |
-
*/
|
11 |
-
namespace MatthiasMullie\Minify\Exceptions;
|
12 |
-
|
13 |
-
use MatthiasMullie\Minify\Exception;
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Basic Exception Class
|
17 |
-
*
|
18 |
-
* @package Minify\Exception
|
19 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
20 |
-
*/
|
21 |
-
abstract class BasicException extends Exception
|
22 |
-
{
|
23 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/src/Exceptions/FileImportException.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* File Import Exception
|
4 |
-
*
|
5 |
-
* Please report bugs on https://github.com/matthiasmullie/minify/issues
|
6 |
-
*
|
7 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
8 |
-
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
|
9 |
-
* @license MIT License
|
10 |
-
*/
|
11 |
-
namespace MatthiasMullie\Minify\Exceptions;
|
12 |
-
|
13 |
-
/**
|
14 |
-
* File Import Exception Class
|
15 |
-
*
|
16 |
-
* @package Minify\Exception
|
17 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
18 |
-
*/
|
19 |
-
class FileImportException extends BasicException
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/src/Exceptions/IOException.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* IO Exception
|
4 |
-
*
|
5 |
-
* Please report bugs on https://github.com/matthiasmullie/minify/issues
|
6 |
-
*
|
7 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
8 |
-
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
|
9 |
-
* @license MIT License
|
10 |
-
*/
|
11 |
-
namespace MatthiasMullie\Minify\Exceptions;
|
12 |
-
|
13 |
-
/**
|
14 |
-
* IO Exception Class
|
15 |
-
*
|
16 |
-
* @package Minify\Exception
|
17 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
18 |
-
*/
|
19 |
-
class IOException extends BasicException
|
20 |
-
{
|
21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/src/Exceptions/index.html
DELETED
File without changes
|
libs/matthiasmullie/minify/src/JS.php
DELETED
@@ -1,577 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* JavaScript minifier
|
4 |
-
*
|
5 |
-
* Please report bugs on https://github.com/matthiasmullie/minify/issues
|
6 |
-
*
|
7 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
8 |
-
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
|
9 |
-
* @license MIT License
|
10 |
-
*/
|
11 |
-
namespace MatthiasMullie\Minify;
|
12 |
-
|
13 |
-
/**
|
14 |
-
* JavaScript Minifier Class
|
15 |
-
*
|
16 |
-
* Please report bugs on https://github.com/matthiasmullie/minify/issues
|
17 |
-
*
|
18 |
-
* @package Minify
|
19 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
20 |
-
* @author Tijs Verkoyen <minify@verkoyen.eu>
|
21 |
-
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
|
22 |
-
* @license MIT License
|
23 |
-
*/
|
24 |
-
class JS extends Minify
|
25 |
-
{
|
26 |
-
/**
|
27 |
-
* Var-matching regex based on http://stackoverflow.com/a/9337047/802993.
|
28 |
-
*
|
29 |
-
* Note that regular expressions using that bit must have the PCRE_UTF8
|
30 |
-
* pattern modifier (/u) set.
|
31 |
-
*
|
32 |
-
* @var string
|
33 |
-
*/
|
34 |
-
const REGEX_VARIABLE = '\b[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}0-9\x{0300}-\x{036f}\x{0483}-\x{0487}\x{0591}-\x{05bd}\x{05bf}\x{05c1}\x{05c2}\x{05c4}\x{05c5}\x{05c7}\x{0610}-\x{061a}\x{064b}-\x{0669}\x{0670}\x{06d6}-\x{06dc}\x{06df}-\x{06e4}\x{06e7}\x{06e8}\x{06ea}-\x{06ed}\x{06f0}-\x{06f9}\x{0711}\x{0730}-\x{074a}\x{07a6}-\x{07b0}\x{07c0}-\x{07c9}\x{07eb}-\x{07f3}\x{0816}-\x{0819}\x{081b}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082d}\x{0859}-\x{085b}\x{08e4}-\x{08fe}\x{0900}-\x{0903}\x{093a}-\x{093c}\x{093e}-\x{094f}\x{0951}-\x{0957}\x{0962}\x{0963}\x{0966}-\x{096f}\x{0981}-\x{0983}\x{09bc}\x{09be}-\x{09c4}\x{09c7}\x{09c8}\x{09cb}-\x{09cd}\x{09d7}\x{09e2}\x{09e3}\x{09e6}-\x{09ef}\x{0a01}-\x{0a03}\x{0a3c}\x{0a3e}-\x{0a42}\x{0a47}\x{0a48}\x{0a4b}-\x{0a4d}\x{0a51}\x{0a66}-\x{0a71}\x{0a75}\x{0a81}-\x{0a83}\x{0abc}\x{0abe}-\x{0ac5}\x{0ac7}-\x{0ac9}\x{0acb}-\x{0acd}\x{0ae2}\x{0ae3}\x{0ae6}-\x{0aef}\x{0b01}-\x{0b03}\x{0b3c}\x{0b3e}-\x{0b44}\x{0b47}\x{0b48}\x{0b4b}-\x{0b4d}\x{0b56}\x{0b57}\x{0b62}\x{0b63}\x{0b66}-\x{0b6f}\x{0b82}\x{0bbe}-\x{0bc2}\x{0bc6}-\x{0bc8}\x{0bca}-\x{0bcd}\x{0bd7}\x{0be6}-\x{0bef}\x{0c01}-\x{0c03}\x{0c3e}-\x{0c44}\x{0c46}-\x{0c48}\x{0c4a}-\x{0c4d}\x{0c55}\x{0c56}\x{0c62}\x{0c63}\x{0c66}-\x{0c6f}\x{0c82}\x{0c83}\x{0cbc}\x{0cbe}-\x{0cc4}\x{0cc6}-\x{0cc8}\x{0cca}-\x{0ccd}\x{0cd5}\x{0cd6}\x{0ce2}\x{0ce3}\x{0ce6}-\x{0cef}\x{0d02}\x{0d03}\x{0d3e}-\x{0d44}\x{0d46}-\x{0d48}\x{0d4a}-\x{0d4d}\x{0d57}\x{0d62}\x{0d63}\x{0d66}-\x{0d6f}\x{0d82}\x{0d83}\x{0dca}\x{0dcf}-\x{0dd4}\x{0dd6}\x{0dd8}-\x{0ddf}\x{0df2}\x{0df3}\x{0e31}\x{0e34}-\x{0e3a}\x{0e47}-\x{0e4e}\x{0e50}-\x{0e59}\x{0eb1}\x{0eb4}-\x{0eb9}\x{0ebb}\x{0ebc}\x{0ec8}-\x{0ecd}\x{0ed0}-\x{0ed9}\x{0f18}\x{0f19}\x{0f20}-\x{0f29}\x{0f35}\x{0f37}\x{0f39}\x{0f3e}\x{0f3f}\x{0f71}-\x{0f84}\x{0f86}\x{0f87}\x{0f8d}-\x{0f97}\x{0f99}-\x{0fbc}\x{0fc6}\x{102b}-\x{103e}\x{1040}-\x{1049}\x{1056}-\x{1059}\x{105e}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106d}\x{1071}-\x{1074}\x{1082}-\x{108d}\x{108f}-\x{109d}\x{135d}-\x{135f}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}\x{1753}\x{1772}\x{1773}\x{17b4}-\x{17d3}\x{17dd}\x{17e0}-\x{17e9}\x{180b}-\x{180d}\x{1810}-\x{1819}\x{18a9}\x{1920}-\x{192b}\x{1930}-\x{193b}\x{1946}-\x{194f}\x{19b0}-\x{19c0}\x{19c8}\x{19c9}\x{19d0}-\x{19d9}\x{1a17}-\x{1a1b}\x{1a55}-\x{1a5e}\x{1a60}-\x{1a7c}\x{1a7f}-\x{1a89}\x{1a90}-\x{1a99}\x{1b00}-\x{1b04}\x{1b34}-\x{1b44}\x{1b50}-\x{1b59}\x{1b6b}-\x{1b73}\x{1b80}-\x{1b82}\x{1ba1}-\x{1bad}\x{1bb0}-\x{1bb9}\x{1be6}-\x{1bf3}\x{1c24}-\x{1c37}\x{1c40}-\x{1c49}\x{1c50}-\x{1c59}\x{1cd0}-\x{1cd2}\x{1cd4}-\x{1ce8}\x{1ced}\x{1cf2}-\x{1cf4}\x{1dc0}-\x{1de6}\x{1dfc}-\x{1dff}\x{200c}\x{200d}\x{203f}\x{2040}\x{2054}\x{20d0}-\x{20dc}\x{20e1}\x{20e5}-\x{20f0}\x{2cef}-\x{2cf1}\x{2d7f}\x{2de0}-\x{2dff}\x{302a}-\x{302f}\x{3099}\x{309a}\x{a620}-\x{a629}\x{a66f}\x{a674}-\x{a67d}\x{a69f}\x{a6f0}\x{a6f1}\x{a802}\x{a806}\x{a80b}\x{a823}-\x{a827}\x{a880}\x{a881}\x{a8b4}-\x{a8c4}\x{a8d0}-\x{a8d9}\x{a8e0}-\x{a8f1}\x{a900}-\x{a909}\x{a926}-\x{a92d}\x{a947}-\x{a953}\x{a980}-\x{a983}\x{a9b3}-\x{a9c0}\x{a9d0}-\x{a9d9}\x{aa29}-\x{aa36}\x{aa43}\x{aa4c}\x{aa4d}\x{aa50}-\x{aa59}\x{aa7b}\x{aab0}\x{aab2}-\x{aab4}\x{aab7}\x{aab8}\x{aabe}\x{aabf}\x{aac1}\x{aaeb}-\x{aaef}\x{aaf5}\x{aaf6}\x{abe3}-\x{abea}\x{abec}\x{abed}\x{abf0}-\x{abf9}\x{fb1e}\x{fe00}-\x{fe0f}\x{fe20}-\x{fe26}\x{fe33}\x{fe34}\x{fe4d}-\x{fe4f}\x{ff10}-\x{ff19}\x{ff3f}]*\b';
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Full list of JavaScript reserved words.
|
38 |
-
* Will be loaded from /data/js/keywords_reserved.txt.
|
39 |
-
*
|
40 |
-
* @see https://mathiasbynens.be/notes/reserved-keywords
|
41 |
-
*
|
42 |
-
* @var string[]
|
43 |
-
*/
|
44 |
-
protected $keywordsReserved = array();
|
45 |
-
|
46 |
-
/**
|
47 |
-
* List of JavaScript reserved words that accept a <variable, value, ...>
|
48 |
-
* after them. Some end of lines are not the end of a statement, like with
|
49 |
-
* these keywords.
|
50 |
-
*
|
51 |
-
* E.g.: we shouldn't insert a ; after this else
|
52 |
-
* else
|
53 |
-
* console.log('this is quite fine')
|
54 |
-
*
|
55 |
-
* Will be loaded from /data/js/keywords_before.txt
|
56 |
-
*
|
57 |
-
* @var string[]
|
58 |
-
*/
|
59 |
-
protected $keywordsBefore = array();
|
60 |
-
|
61 |
-
/**
|
62 |
-
* List of JavaScript reserved words that accept a <variable, value, ...>
|
63 |
-
* before them. Some end of lines are not the end of a statement, like when
|
64 |
-
* continued by one of these keywords on the newline.
|
65 |
-
*
|
66 |
-
* E.g.: we shouldn't insert a ; before this instanceof
|
67 |
-
* variable
|
68 |
-
* instanceof String
|
69 |
-
*
|
70 |
-
* Will be loaded from /data/js/keywords_after.txt
|
71 |
-
*
|
72 |
-
* @var string[]
|
73 |
-
*/
|
74 |
-
protected $keywordsAfter = array();
|
75 |
-
|
76 |
-
/**
|
77 |
-
* List of all JavaScript operators.
|
78 |
-
*
|
79 |
-
* Will be loaded from /data/js/operators.txt
|
80 |
-
*
|
81 |
-
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
|
82 |
-
*
|
83 |
-
* @var string[]
|
84 |
-
*/
|
85 |
-
protected $operators = array();
|
86 |
-
|
87 |
-
/**
|
88 |
-
* List of JavaScript operators that accept a <variable, value, ...> after
|
89 |
-
* them. Some end of lines are not the end of a statement, like with these
|
90 |
-
* operators.
|
91 |
-
*
|
92 |
-
* Note: Most operators are fine, we've only removed ++ and --.
|
93 |
-
* ++ & -- have to be joined with the value they're in-/decrementing.
|
94 |
-
*
|
95 |
-
* Will be loaded from /data/js/operators_before.txt
|
96 |
-
*
|
97 |
-
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
|
98 |
-
*
|
99 |
-
* @var string[]
|
100 |
-
*/
|
101 |
-
protected $operatorsBefore = array();
|
102 |
-
|
103 |
-
/**
|
104 |
-
* List of JavaScript operators that accept a <variable, value, ...> before
|
105 |
-
* them. Some end of lines are not the end of a statement, like when
|
106 |
-
* continued by one of these operators on the newline.
|
107 |
-
*
|
108 |
-
* Note: Most operators are fine, we've only removed ), ], ++, --, ! and ~.
|
109 |
-
* There can't be a newline separating ! or ~ and whatever it is negating.
|
110 |
-
* ++ & -- have to be joined with the value they're in-/decrementing.
|
111 |
-
* ) & ] are "special" in that they have lots or usecases. () for example
|
112 |
-
* is used for function calls, for grouping, in if () and for (), ...
|
113 |
-
*
|
114 |
-
* Will be loaded from /data/js/operators_after.txt
|
115 |
-
*
|
116 |
-
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
|
117 |
-
*
|
118 |
-
* @var string[]
|
119 |
-
*/
|
120 |
-
protected $operatorsAfter = array();
|
121 |
-
|
122 |
-
/**
|
123 |
-
* {@inheritdoc}
|
124 |
-
*/
|
125 |
-
public function __construct()
|
126 |
-
{
|
127 |
-
call_user_func_array(array('parent', '__construct'), func_get_args());
|
128 |
-
|
129 |
-
$dataDir = __DIR__.'/../data/js/';
|
130 |
-
$options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES;
|
131 |
-
$this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options);
|
132 |
-
$this->keywordsBefore = file($dataDir.'keywords_before.txt', $options);
|
133 |
-
$this->keywordsAfter = file($dataDir.'keywords_after.txt', $options);
|
134 |
-
$this->operators = file($dataDir.'operators.txt', $options);
|
135 |
-
$this->operatorsBefore = file($dataDir.'operators_before.txt', $options);
|
136 |
-
$this->operatorsAfter = file($dataDir.'operators_after.txt', $options);
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Minify the data.
|
141 |
-
* Perform JS optimizations.
|
142 |
-
*
|
143 |
-
* @param string[optional] $path Path to write the data to
|
144 |
-
*
|
145 |
-
* @return string The minified data
|
146 |
-
*/
|
147 |
-
public function execute($path = null)
|
148 |
-
{
|
149 |
-
$content = '';
|
150 |
-
|
151 |
-
/*
|
152 |
-
* Let's first take out strings, comments and regular expressions.
|
153 |
-
* All of these can contain JS code-like characters, and we should make
|
154 |
-
* sure any further magic ignores anything inside of these.
|
155 |
-
*
|
156 |
-
* Consider this example, where we should not strip any whitespace:
|
157 |
-
* var str = "a test";
|
158 |
-
*
|
159 |
-
* Comments will be removed altogether, strings and regular expressions
|
160 |
-
* will be replaced by placeholder text, which we'll restore later.
|
161 |
-
*/
|
162 |
-
$this->extractStrings('\'"`');
|
163 |
-
$this->stripComments();
|
164 |
-
$this->extractRegex();
|
165 |
-
|
166 |
-
// loop files
|
167 |
-
foreach ($this->data as $source => $js) {
|
168 |
-
// take out strings, comments & regex (for which we've registered
|
169 |
-
// the regexes just a few lines earlier)
|
170 |
-
$js = $this->replace($js);
|
171 |
-
|
172 |
-
$js = $this->propertyNotation($js);
|
173 |
-
$js = $this->shortenBools($js);
|
174 |
-
$js = $this->stripWhitespace($js);
|
175 |
-
|
176 |
-
// combine js: separating the scripts by a ;
|
177 |
-
$content .= $js.";";
|
178 |
-
}
|
179 |
-
|
180 |
-
// clean up leftover `;`s from the combination of multiple scripts
|
181 |
-
$content = ltrim($content, ';');
|
182 |
-
$content = substr($content, 0, -1);
|
183 |
-
|
184 |
-
/*
|
185 |
-
* Earlier, we extracted strings & regular expressions and replaced them
|
186 |
-
* with placeholder text. This will restore them.
|
187 |
-
*/
|
188 |
-
$content = $this->restoreExtractedData($content);
|
189 |
-
|
190 |
-
return $content;
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* Strip comments from source code.
|
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 |
-
/**
|
206 |
-
* JS can have /-delimited regular expressions, like: /ab+c/.match(string).
|
207 |
-
*
|
208 |
-
* The content inside the regex can contain characters that may be confused
|
209 |
-
* for JS code: e.g. it could contain whitespace it needs to match & we
|
210 |
-
* don't want to strip whitespace in there.
|
211 |
-
*
|
212 |
-
* The regex can be pretty simple: we don't have to care about comments,
|
213 |
-
* (which also use slashes) because stripComments() will have stripped those
|
214 |
-
* already.
|
215 |
-
*
|
216 |
-
* This method will replace all string content with simple REGEX#
|
217 |
-
* placeholder text, so we've rid all regular expressions from characters
|
218 |
-
* that may be misinterpreted. Original regex content will be saved in
|
219 |
-
* $this->extracted and after doing all other minifying, we can restore the
|
220 |
-
* original content via restoreRegex()
|
221 |
-
*/
|
222 |
-
protected function extractRegex()
|
223 |
-
{
|
224 |
-
// PHP only supports $this inside anonymous functions since 5.4
|
225 |
-
$minifier = $this;
|
226 |
-
$callback = function ($match) use ($minifier) {
|
227 |
-
$count = count($minifier->extracted);
|
228 |
-
$placeholder = '"'.$count.'"';
|
229 |
-
$minifier->extracted[$placeholder] = $match[0];
|
230 |
-
|
231 |
-
return $placeholder;
|
232 |
-
};
|
233 |
-
|
234 |
-
// match all chars except `/` and `\`
|
235 |
-
// `\` is allowed though, along with whatever char follows (which is the
|
236 |
-
// one being escaped)
|
237 |
-
// this should allow all chars, except for an unescaped `/` (= the one
|
238 |
-
// closing the regex)
|
239 |
-
$pattern = '\\/([^\\/\\\\]*+|(\\\\.)*+)+\\/[gimy]*';
|
240 |
-
|
241 |
-
// a regular expression can only be followed by a few operators or some
|
242 |
-
// of the RegExp methods (a `\` followed by a variable or value is
|
243 |
-
// likely part of a division, not a regex)
|
244 |
-
$keywords = array('do', 'in', 'new', 'else', 'throw', 'yield', 'delete', 'return', 'typeof');
|
245 |
-
$before = '([=:,;\}\(\{\[&\|!\)]|^|'.implode('|', $keywords).')\s*';
|
246 |
-
$propertiesAndMethods = array(
|
247 |
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties_2
|
248 |
-
'constructor',
|
249 |
-
'flags',
|
250 |
-
'global',
|
251 |
-
'ignoreCase',
|
252 |
-
'multiline',
|
253 |
-
'source',
|
254 |
-
'sticky',
|
255 |
-
'unicode',
|
256 |
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Methods_2
|
257 |
-
'compile(',
|
258 |
-
'exec(',
|
259 |
-
'test(',
|
260 |
-
'toSource(',
|
261 |
-
'toString(',
|
262 |
-
);
|
263 |
-
$delimiters = array_fill(0, count($propertiesAndMethods), '/');
|
264 |
-
$propertiesAndMethods = array_map('preg_quote', $propertiesAndMethods, $delimiters);
|
265 |
-
$after = '(?=\s*[\.,;\)\}&\|+]|\/\/|$|\.('.implode('|', $propertiesAndMethods).'))';
|
266 |
-
$this->registerPattern('/'.$before.'\K'.$pattern.$after.'/', $callback);
|
267 |
-
|
268 |
-
// 1 more edge case: a regex can be followed by a lot more operators or
|
269 |
-
// keywords if there's a newline (ASI) in between, where the operator
|
270 |
-
// actually starts a new statement
|
271 |
-
// (https://github.com/matthiasmullie/minify/issues/56)
|
272 |
-
$operators = $this->getOperatorsForRegex($this->operatorsBefore, '/');
|
273 |
-
$operators += $this->getOperatorsForRegex($this->keywordsReserved, '/');
|
274 |
-
$after = '(?=\s*\n\s*('.implode('|', $operators).'))';
|
275 |
-
$this->registerPattern('/'.$pattern.$after.'/', $callback);
|
276 |
-
}
|
277 |
-
|
278 |
-
/**
|
279 |
-
* Strip whitespace.
|
280 |
-
*
|
281 |
-
* We won't strip *all* whitespace, but as much as possible. The thing that
|
282 |
-
* we'll preserve are newlines we're unsure about.
|
283 |
-
* JavaScript doesn't require statements to be terminated with a semicolon.
|
284 |
-
* It will automatically fix missing semicolons with ASI (automatic semi-
|
285 |
-
* colon insertion) at the end of line causing errors (without semicolon.)
|
286 |
-
*
|
287 |
-
* Because it's sometimes hard to tell if a newline is part of a statement
|
288 |
-
* that should be terminated or not, we'll just leave some of them alone.
|
289 |
-
*
|
290 |
-
* @param string $content The content to strip the whitespace for
|
291 |
-
*
|
292 |
-
* @return string
|
293 |
-
*/
|
294 |
-
protected function stripWhitespace($content)
|
295 |
-
{
|
296 |
-
// uniform line endings, make them all line feed
|
297 |
-
$content = str_replace(array("\r\n", "\r"), "\n", $content);
|
298 |
-
|
299 |
-
// collapse all non-line feed whitespace into a single space
|
300 |
-
$content = preg_replace('/[^\S\n]+/', ' ', $content);
|
301 |
-
|
302 |
-
// strip leading & trailing whitespace
|
303 |
-
$content = str_replace(array(" \n", "\n "), "\n", $content);
|
304 |
-
|
305 |
-
// collapse consecutive line feeds into just 1
|
306 |
-
$content = preg_replace('/\n+/', "\n", $content);
|
307 |
-
|
308 |
-
$operatorsBefore = $this->getOperatorsForRegex($this->operatorsBefore, '/');
|
309 |
-
$operatorsAfter = $this->getOperatorsForRegex($this->operatorsAfter, '/');
|
310 |
-
$operators = $this->getOperatorsForRegex($this->operators, '/');
|
311 |
-
$keywordsBefore = $this->getKeywordsForRegex($this->keywordsBefore, '/');
|
312 |
-
$keywordsAfter = $this->getKeywordsForRegex($this->keywordsAfter, '/');
|
313 |
-
|
314 |
-
// strip whitespace that ends in (or next line begin with) an operator
|
315 |
-
// that allows statements to be broken up over multiple lines
|
316 |
-
unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']);
|
317 |
-
$content = preg_replace(
|
318 |
-
array(
|
319 |
-
'/('.implode('|', $operatorsBefore).')\s+/',
|
320 |
-
'/\s+('.implode('|', $operatorsAfter).')/',
|
321 |
-
), '\\1', $content
|
322 |
-
);
|
323 |
-
|
324 |
-
// make sure + and - can't be mistaken for, or joined into ++ and --
|
325 |
-
$content = preg_replace(
|
326 |
-
array(
|
327 |
-
'/(?<![\+\-])\s*([\+\-])(?![\+\-])/',
|
328 |
-
'/(?<![\+\-])([\+\-])\s*(?![\+\-])/',
|
329 |
-
), '\\1', $content
|
330 |
-
);
|
331 |
-
|
332 |
-
// collapse whitespace around reserved words into single space
|
333 |
-
$content = preg_replace('/(^|[;\}\s])\K('.implode('|', $keywordsBefore).')\s+/', '\\2 ', $content);
|
334 |
-
$content = preg_replace('/\s+('.implode('|', $keywordsAfter).')(?=([;\{\s]|$))/', ' \\1', $content);
|
335 |
-
|
336 |
-
/*
|
337 |
-
* We didn't strip whitespace after a couple of operators because they
|
338 |
-
* could be used in different contexts and we can't be sure it's ok to
|
339 |
-
* strip the newlines. However, we can safely strip any non-line feed
|
340 |
-
* whitespace that follows them.
|
341 |
-
*/
|
342 |
-
$operatorsDiffBefore = array_diff($operators, $operatorsBefore);
|
343 |
-
$operatorsDiffAfter = array_diff($operators, $operatorsAfter);
|
344 |
-
$content = preg_replace('/('.implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content);
|
345 |
-
$content = preg_replace('/[^\S\n]+('.implode('|', $operatorsDiffAfter).')/', '\\1', $content);
|
346 |
-
|
347 |
-
/*
|
348 |
-
* Whitespace after `return` can be omitted in a few occasions
|
349 |
-
* (such as when followed by a string or regex)
|
350 |
-
*/
|
351 |
-
$content = preg_replace('/\breturn\s+(["\'\/\+\-])/', 'return$1', $content);
|
352 |
-
|
353 |
-
/*
|
354 |
-
* Get rid of double semicolons, except where they can be used like:
|
355 |
-
* "for(v=1,_=b;;)", "for(v=1;;v++)" or "for(;;ja||(ja=true))".
|
356 |
-
* I'll safeguard these double semicolons inside for-loops by
|
357 |
-
* temporarily replacing them with an invalid condition: they won't have
|
358 |
-
* a double semicolon and will be easy to spot to restore afterwards.
|
359 |
-
*/
|
360 |
-
$content = preg_replace('/\bfor\(([^;]*);;([^;]*)\)/', 'for(\\1;-;\\2)', $content);
|
361 |
-
$content = preg_replace('/;+/', ';', $content);
|
362 |
-
$content = preg_replace('/\bfor\(([^;]*);-;([^;]*)\)/', 'for(\\1;;\\2)', $content);
|
363 |
-
|
364 |
-
/*
|
365 |
-
* Next, we'll be removing all semicolons where ASI kicks in.
|
366 |
-
* for-loops however, can have an empty body (ending in only a
|
367 |
-
* semicolon), like: `for(i=1;i<3;i++);`, of `for(i in list);`
|
368 |
-
* Here, nothing happens during the loop; it's just used to keep
|
369 |
-
* increasing `i`. With that ; omitted, the next line would be expected
|
370 |
-
* to be the for-loop's body... Same goes for while loops.
|
371 |
-
* I'm going to double that semicolon (if any) so after the next line,
|
372 |
-
* which strips semicolons here & there, we're still left with this one.
|
373 |
-
*/
|
374 |
-
$content = preg_replace('/(for\([^;\{]*;[^;\{]*;[^;\{]*\));(\}|$)/s', '\\1;;\\2', $content);
|
375 |
-
$content = preg_replace('/(for\([^;\{]+\s+in\s+[^;\{]+\));(\}|$)/s', '\\1;;\\2', $content);
|
376 |
-
/*
|
377 |
-
* Below will also keep `;` after a `do{}while();` along with `while();`
|
378 |
-
* While these could be stripped after do-while, detecting this
|
379 |
-
* distinction is cumbersome, so I'll play it safe and make sure `;`
|
380 |
-
* after any kind of `while` is kept.
|
381 |
-
*/
|
382 |
-
$content = preg_replace('/(while\([^;\{]+\));(\}|$)/s', '\\1;;\\2', $content);
|
383 |
-
|
384 |
-
/*
|
385 |
-
* We also can't strip empty else-statements. Even though they're
|
386 |
-
* useless and probably shouldn't be in the code in the first place, we
|
387 |
-
* shouldn't be stripping the `;` that follows it as it breaks the code.
|
388 |
-
* We can just remove those useless else-statements completely.
|
389 |
-
*
|
390 |
-
* @see https://github.com/matthiasmullie/minify/issues/91
|
391 |
-
*/
|
392 |
-
$content = preg_replace('/else;/s', '', $content);
|
393 |
-
|
394 |
-
/*
|
395 |
-
* We also don't really want to terminate statements followed by closing
|
396 |
-
* curly braces (which we've ignored completely up until now) or end-of-
|
397 |
-
* script: ASI will kick in here & we're all about minifying.
|
398 |
-
* Semicolons at beginning of the file don't make any sense either.
|
399 |
-
*/
|
400 |
-
$content = preg_replace('/;(\}|$)/s', '\\1', $content);
|
401 |
-
$content = ltrim($content, ';');
|
402 |
-
|
403 |
-
// get rid of remaining whitespace af beginning/end
|
404 |
-
return trim($content);
|
405 |
-
}
|
406 |
-
|
407 |
-
/**
|
408 |
-
* We'll strip whitespace around certain operators with regular expressions.
|
409 |
-
* This will prepare the given array by escaping all characters.
|
410 |
-
*
|
411 |
-
* @param string[] $operators
|
412 |
-
* @param string $delimiter
|
413 |
-
*
|
414 |
-
* @return string[]
|
415 |
-
*/
|
416 |
-
protected function getOperatorsForRegex(array $operators, $delimiter = '/')
|
417 |
-
{
|
418 |
-
// escape operators for use in regex
|
419 |
-
$delimiters = array_fill(0, count($operators), $delimiter);
|
420 |
-
$escaped = array_map('preg_quote', $operators, $delimiters);
|
421 |
-
|
422 |
-
$operators = array_combine($operators, $escaped);
|
423 |
-
|
424 |
-
// ignore + & - for now, they'll get special treatment
|
425 |
-
unset($operators['+'], $operators['-']);
|
426 |
-
|
427 |
-
// dot can not just immediately follow a number; it can be confused for
|
428 |
-
// decimal point, or calling a method on it, e.g. 42 .toString()
|
429 |
-
$operators['.'] = '(?<![0-9]\s)\.';
|
430 |
-
|
431 |
-
// don't confuse = with other assignment shortcuts (e.g. +=)
|
432 |
-
$chars = preg_quote('+-*\=<>%&|', $delimiter);
|
433 |
-
$operators['='] = '(?<!['.$chars.'])\=';
|
434 |
-
|
435 |
-
return $operators;
|
436 |
-
}
|
437 |
-
|
438 |
-
/**
|
439 |
-
* We'll strip whitespace around certain keywords with regular expressions.
|
440 |
-
* This will prepare the given array by escaping all characters.
|
441 |
-
*
|
442 |
-
* @param string[] $keywords
|
443 |
-
* @param string $delimiter
|
444 |
-
*
|
445 |
-
* @return string[]
|
446 |
-
*/
|
447 |
-
protected function getKeywordsForRegex(array $keywords, $delimiter = '/')
|
448 |
-
{
|
449 |
-
// escape keywords for use in regex
|
450 |
-
$delimiter = array_fill(0, count($keywords), $delimiter);
|
451 |
-
$escaped = array_map('preg_quote', $keywords, $delimiter);
|
452 |
-
|
453 |
-
// add word boundaries
|
454 |
-
array_walk($keywords, function ($value) {
|
455 |
-
return '\b'.$value.'\b';
|
456 |
-
});
|
457 |
-
|
458 |
-
$keywords = array_combine($keywords, $escaped);
|
459 |
-
|
460 |
-
return $keywords;
|
461 |
-
}
|
462 |
-
|
463 |
-
/**
|
464 |
-
* Replaces all occurrences of array['key'] by array.key.
|
465 |
-
*
|
466 |
-
* @param string $content
|
467 |
-
*
|
468 |
-
* @return string
|
469 |
-
*/
|
470 |
-
protected function propertyNotation($content)
|
471 |
-
{
|
472 |
-
// PHP only supports $this inside anonymous functions since 5.4
|
473 |
-
$minifier = $this;
|
474 |
-
$keywords = $this->keywordsReserved;
|
475 |
-
$callback = function ($match) use ($minifier, $keywords) {
|
476 |
-
$property = trim($minifier->extracted[$match[1]], '\'"');
|
477 |
-
|
478 |
-
/*
|
479 |
-
* Check if the property is a reserved keyword. In this context (as
|
480 |
-
* property of an object literal/array) it shouldn't matter, but IE8
|
481 |
-
* freaks out with "Expected identifier".
|
482 |
-
*/
|
483 |
-
if (in_array($property, $keywords)) {
|
484 |
-
return $match[0];
|
485 |
-
}
|
486 |
-
|
487 |
-
/*
|
488 |
-
* See if the property is in a variable-like format (e.g.
|
489 |
-
* array['key-here'] can't be replaced by array.key-here since '-'
|
490 |
-
* is not a valid character there.
|
491 |
-
*/
|
492 |
-
if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) {
|
493 |
-
return $match[0];
|
494 |
-
}
|
495 |
-
|
496 |
-
return '.'.$property;
|
497 |
-
};
|
498 |
-
|
499 |
-
/*
|
500 |
-
* Figure out if previous character is a variable name (of the array
|
501 |
-
* we want to use property notation on) - this is to make sure
|
502 |
-
* standalone ['value'] arrays aren't confused for keys-of-an-array.
|
503 |
-
* We can (and only have to) check the last character, because PHP's
|
504 |
-
* regex implementation doesn't allow unfixed-length look-behind
|
505 |
-
* assertions.
|
506 |
-
*/
|
507 |
-
preg_match('/(\[[^\]]+\])[^\]]*$/', static::REGEX_VARIABLE, $previousChar);
|
508 |
-
$previousChar = $previousChar[1];
|
509 |
-
|
510 |
-
/*
|
511 |
-
* Make sure word preceding the ['value'] is not a keyword, e.g.
|
512 |
-
* return['x']. Because -again- PHP's regex implementation doesn't allow
|
513 |
-
* unfixed-length look-behind assertions, I'm just going to do a lot of
|
514 |
-
* separate look-behind assertions, one for each keyword.
|
515 |
-
*/
|
516 |
-
$keywords = $this->getKeywordsForRegex($keywords);
|
517 |
-
$keywords = '(?<!'.implode(')(?<!', $keywords).')';
|
518 |
-
|
519 |
-
return preg_replace_callback('/(?<='.$previousChar.'|\])'.$keywords.'\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content);
|
520 |
-
}
|
521 |
-
|
522 |
-
/**
|
523 |
-
* Replaces true & false by !0 and !1.
|
524 |
-
*
|
525 |
-
* @param string $content
|
526 |
-
*
|
527 |
-
* @return string
|
528 |
-
*/
|
529 |
-
protected function shortenBools($content)
|
530 |
-
{
|
531 |
-
/*
|
532 |
-
* 'true' or 'false' could be used as property names (which may be
|
533 |
-
* followed by whitespace) - we must not replace those!
|
534 |
-
* Since PHP doesn't allow variable-length (to account for the
|
535 |
-
* whitespace) lookbehind assertions, I need to capture the leading
|
536 |
-
* character and check if it's a `.`
|
537 |
-
*/
|
538 |
-
$callback = function ($match) {
|
539 |
-
if (trim($match[1]) === '.') {
|
540 |
-
return $match[0];
|
541 |
-
}
|
542 |
-
|
543 |
-
return $match[1].($match[2] === 'true' ? '!0' : '!1');
|
544 |
-
};
|
545 |
-
$content = preg_replace_callback('/(^|.\s*)\b(true|false)\b(?!:)/', $callback, $content);
|
546 |
-
|
547 |
-
// for(;;) is exactly the same as while(true), but shorter :)
|
548 |
-
$content = preg_replace('/\bwhile\(!0\){/', 'for(;;){', $content);
|
549 |
-
|
550 |
-
// now make sure we didn't turn any do ... while(true) into do ... for(;;)
|
551 |
-
preg_match_all('/\bdo\b/', $content, $dos, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
|
552 |
-
|
553 |
-
// go backward to make sure positional offsets aren't altered when $content changes
|
554 |
-
$dos = array_reverse($dos);
|
555 |
-
foreach ($dos as $do) {
|
556 |
-
$offsetDo = $do[0][1];
|
557 |
-
|
558 |
-
// find all `while` (now `for`) following `do`: one of those must be
|
559 |
-
// associated with the `do` and be turned back into `while`
|
560 |
-
preg_match_all('/\bfor\(;;\)/', $content, $whiles, PREG_OFFSET_CAPTURE | PREG_SET_ORDER, $offsetDo);
|
561 |
-
foreach ($whiles as $while) {
|
562 |
-
$offsetWhile = $while[0][1];
|
563 |
-
|
564 |
-
$open = substr_count($content, '{', $offsetDo, $offsetWhile - $offsetDo);
|
565 |
-
$close = substr_count($content, '}', $offsetDo, $offsetWhile - $offsetDo);
|
566 |
-
if ($open === $close) {
|
567 |
-
// only restore `while` if amount of `{` and `}` are the same;
|
568 |
-
// otherwise, that `for` isn't associated with this `do`
|
569 |
-
$content = substr_replace($content, 'while(!0)', $offsetWhile, strlen('for(;;)'));
|
570 |
-
break;
|
571 |
-
}
|
572 |
-
}
|
573 |
-
}
|
574 |
-
|
575 |
-
return $content;
|
576 |
-
}
|
577 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/src/Minify.php
DELETED
@@ -1,444 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Abstract minifier class
|
4 |
-
*
|
5 |
-
* Please report bugs on https://github.com/matthiasmullie/minify/issues
|
6 |
-
*
|
7 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
8 |
-
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
|
9 |
-
* @license MIT License
|
10 |
-
*/
|
11 |
-
namespace MatthiasMullie\Minify;
|
12 |
-
|
13 |
-
use MatthiasMullie\Minify\Exceptions\IOException;
|
14 |
-
use Psr\Cache\CacheItemInterface;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Abstract minifier class.
|
18 |
-
*
|
19 |
-
* Please report bugs on https://github.com/matthiasmullie/minify/issues
|
20 |
-
*
|
21 |
-
* @package Minify
|
22 |
-
* @author Matthias Mullie <minify@mullie.eu>
|
23 |
-
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
|
24 |
-
* @license MIT License
|
25 |
-
*/
|
26 |
-
abstract class Minify
|
27 |
-
{
|
28 |
-
/**
|
29 |
-
* The data to be minified.
|
30 |
-
*
|
31 |
-
* @var string[]
|
32 |
-
*/
|
33 |
-
protected $data = array();
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Array of patterns to match.
|
37 |
-
*
|
38 |
-
* @var string[]
|
39 |
-
*/
|
40 |
-
protected $patterns = array();
|
41 |
-
|
42 |
-
/**
|
43 |
-
* This array will hold content of strings and regular expressions that have
|
44 |
-
* been extracted from the JS source code, so we can reliably match "code",
|
45 |
-
* without having to worry about potential "code-like" characters inside.
|
46 |
-
*
|
47 |
-
* @var string[]
|
48 |
-
*/
|
49 |
-
public $extracted = array();
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Init the minify class - optionally, code may be passed along already.
|
53 |
-
*/
|
54 |
-
public function __construct(/* $data = null, ... */)
|
55 |
-
{
|
56 |
-
// it's possible to add the source through the constructor as well ;)
|
57 |
-
if (func_num_args()) {
|
58 |
-
call_user_func_array(array($this, 'add'), func_get_args());
|
59 |
-
}
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Add a file or straight-up code to be minified.
|
64 |
-
*
|
65 |
-
* @param string|string[] $data
|
66 |
-
*
|
67 |
-
* @return static
|
68 |
-
*/
|
69 |
-
public function add($data /* $data = null, ... */)
|
70 |
-
{
|
71 |
-
// bogus "usage" of parameter $data: scrutinizer warns this variable is
|
72 |
-
// not used (we're using func_get_args instead to support overloading),
|
73 |
-
// but it still needs to be defined because it makes no sense to have
|
74 |
-
// this function without argument :)
|
75 |
-
$args = array($data) + func_get_args();
|
76 |
-
|
77 |
-
// this method can be overloaded
|
78 |
-
foreach ($args as $data) {
|
79 |
-
if (is_array($data)) {
|
80 |
-
call_user_func_array(array($this, 'add'), $data);
|
81 |
-
continue;
|
82 |
-
}
|
83 |
-
|
84 |
-
// redefine var
|
85 |
-
$data = (string) $data;
|
86 |
-
|
87 |
-
// load data
|
88 |
-
$value = $this->load($data);
|
89 |
-
$key = ($data != $value) ? $data : count($this->data);
|
90 |
-
|
91 |
-
// replace CR linefeeds etc.
|
92 |
-
// @see https://github.com/matthiasmullie/minify/pull/139
|
93 |
-
$value = str_replace(array("\r\n", "\r"), "\n", $value);
|
94 |
-
|
95 |
-
// store data
|
96 |
-
$this->data[$key] = $value;
|
97 |
-
}
|
98 |
-
|
99 |
-
return $this;
|
100 |
-
}
|
101 |
-
|
102 |
-
/**
|
103 |
-
* Minify the data & (optionally) saves it to a file.
|
104 |
-
*
|
105 |
-
* @param string[optional] $path Path to write the data to
|
106 |
-
*
|
107 |
-
* @return string The minified data
|
108 |
-
*/
|
109 |
-
public function minify($path = null)
|
110 |
-
{
|
111 |
-
$content = $this->execute($path);
|
112 |
-
|
113 |
-
// save to path
|
114 |
-
if ($path !== null) {
|
115 |
-
$this->save($content, $path);
|
116 |
-
}
|
117 |
-
|
118 |
-
return $content;
|
119 |
-
}
|
120 |
-
|
121 |
-
/**
|
122 |
-
* Minify & gzip the data & (optionally) saves it to a file.
|
123 |
-
*
|
124 |
-
* @param string[optional] $path Path to write the data to
|
125 |
-
* @param int[optional] $level Compression level, from 0 to 9
|
126 |
-
*
|
127 |
-
* @return string The minified & gzipped data
|
128 |
-
*/
|
129 |
-
public function gzip($path = null, $level = 9)
|
130 |
-
{
|
131 |
-
$content = $this->execute($path);
|
132 |
-
$content = gzencode($content, $level, FORCE_GZIP);
|
133 |
-
|
134 |
-
// save to path
|
135 |
-
if ($path !== null) {
|
136 |
-
$this->save($content, $path);
|
137 |
-
}
|
138 |
-
|
139 |
-
return $content;
|
140 |
-
}
|
141 |
-
|
142 |
-
/**
|
143 |
-
* Minify the data & write it to a CacheItemInterface object.
|
144 |
-
*
|
145 |
-
* @param CacheItemInterface $item Cache item to write the data to
|
146 |
-
*
|
147 |
-
* @return CacheItemInterface Cache item with the minifier data
|
148 |
-
*/
|
149 |
-
public function cache(CacheItemInterface $item)
|
150 |
-
{
|
151 |
-
$content = $this->execute();
|
152 |
-
$item->set($content);
|
153 |
-
|
154 |
-
return $item;
|
155 |
-
}
|
156 |
-
|
157 |
-
/**
|
158 |
-
* Minify the data.
|
159 |
-
*
|
160 |
-
* @param string[optional] $path Path to write the data to
|
161 |
-
*
|
162 |
-
* @return string The minified data
|
163 |
-
*/
|
164 |
-
abstract public function execute($path = null);
|
165 |
-
|
166 |
-
/**
|
167 |
-
* Load data.
|
168 |
-
*
|
169 |
-
* @param string $data Either a path to a file or the content itself
|
170 |
-
*
|
171 |
-
* @return string
|
172 |
-
*/
|
173 |
-
protected function load($data)
|
174 |
-
{
|
175 |
-
// check if the data is a file
|
176 |
-
if ($this->canImportFile($data)) {
|
177 |
-
$data = file_get_contents($data);
|
178 |
-
|
179 |
-
// strip BOM, if any
|
180 |
-
if (substr($data, 0, 3) == "\xef\xbb\xbf") {
|
181 |
-
$data = substr($data, 3);
|
182 |
-
}
|
183 |
-
}
|
184 |
-
|
185 |
-
return $data;
|
186 |
-
}
|
187 |
-
|
188 |
-
/**
|
189 |
-
* Save to file.
|
190 |
-
*
|
191 |
-
* @param string $content The minified data
|
192 |
-
* @param string $path The path to save the minified data to
|
193 |
-
*
|
194 |
-
* @throws IOException
|
195 |
-
*/
|
196 |
-
protected function save($content, $path)
|
197 |
-
{
|
198 |
-
$handler = $this->openFileForWriting($path);
|
199 |
-
|
200 |
-
$this->writeToFile($handler, $content);
|
201 |
-
|
202 |
-
@fclose($handler);
|
203 |
-
}
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Register a pattern to execute against the source content.
|
207 |
-
*
|
208 |
-
* @param string $pattern PCRE pattern
|
209 |
-
* @param string|callable $replacement Replacement value for matched pattern
|
210 |
-
*/
|
211 |
-
protected function registerPattern($pattern, $replacement = '')
|
212 |
-
{
|
213 |
-
// study the pattern, we'll execute it more than once
|
214 |
-
$pattern .= 'S';
|
215 |
-
|
216 |
-
$this->patterns[] = array($pattern, $replacement);
|
217 |
-
}
|
218 |
-
|
219 |
-
/**
|
220 |
-
* We can't "just" run some regular expressions against JavaScript: it's a
|
221 |
-
* complex language. E.g. having an occurrence of // xyz would be a comment,
|
222 |
-
* unless it's used within a string. Of you could have something that looks
|
223 |
-
* like a 'string', but inside a comment.
|
224 |
-
* The only way to accurately replace these pieces is to traverse the JS one
|
225 |
-
* character at a time and try to find whatever starts first.
|
226 |
-
*
|
227 |
-
* @param string $content The content to replace patterns in
|
228 |
-
*
|
229 |
-
* @return string The (manipulated) content
|
230 |
-
*/
|
231 |
-
protected function replace($content)
|
232 |
-
{
|
233 |
-
$processed = '';
|
234 |
-
$positions = array_fill(0, count($this->patterns), -1);
|
235 |
-
$matches = array();
|
236 |
-
|
237 |
-
while ($content) {
|
238 |
-
// find first match for all patterns
|
239 |
-
foreach ($this->patterns as $i => $pattern) {
|
240 |
-
list($pattern, $replacement) = $pattern;
|
241 |
-
|
242 |
-
// no need to re-run matches that are still in the part of the
|
243 |
-
// content that hasn't been processed
|
244 |
-
if ($positions[$i] >= 0) {
|
245 |
-
continue;
|
246 |
-
}
|
247 |
-
|
248 |
-
$match = null;
|
249 |
-
if (preg_match($pattern, $content, $match)) {
|
250 |
-
$matches[$i] = $match;
|
251 |
-
|
252 |
-
// we'll store the match position as well; that way, we
|
253 |
-
// don't have to redo all preg_matches after changing only
|
254 |
-
// the first (we'll still know where those others are)
|
255 |
-
$positions[$i] = strpos($content, $match[0]);
|
256 |
-
} else {
|
257 |
-
// if the pattern couldn't be matched, there's no point in
|
258 |
-
// executing it again in later runs on this same content;
|
259 |
-
// ignore this one until we reach end of content
|
260 |
-
unset($matches[$i]);
|
261 |
-
$positions[$i] = strlen($content);
|
262 |
-
}
|
263 |
-
}
|
264 |
-
|
265 |
-
// no more matches to find: everything's been processed, break out
|
266 |
-
if (!$matches) {
|
267 |
-
$processed .= $content;
|
268 |
-
break;
|
269 |
-
}
|
270 |
-
|
271 |
-
// see which of the patterns actually found the first thing (we'll
|
272 |
-
// only want to execute that one, since we're unsure if what the
|
273 |
-
// other found was not inside what the first found)
|
274 |
-
$discardLength = min($positions);
|
275 |
-
$firstPattern = array_search($discardLength, $positions);
|
276 |
-
$match = $matches[$firstPattern][0];
|
277 |
-
|
278 |
-
// execute the pattern that matches earliest in the content string
|
279 |
-
list($pattern, $replacement) = $this->patterns[$firstPattern];
|
280 |
-
$replacement = $this->replacePattern($pattern, $replacement, $content);
|
281 |
-
|
282 |
-
// figure out which part of the string was unmatched; that's the
|
283 |
-
// part we'll execute the patterns on again next
|
284 |
-
$content = substr($content, $discardLength);
|
285 |
-
$unmatched = (string) substr($content, strpos($content, $match) + strlen($match));
|
286 |
-
|
287 |
-
// move the replaced part to $processed and prepare $content to
|
288 |
-
// again match batch of patterns against
|
289 |
-
$processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched));
|
290 |
-
$content = $unmatched;
|
291 |
-
|
292 |
-
// first match has been replaced & that content is to be left alone,
|
293 |
-
// the next matches will start after this replacement, so we should
|
294 |
-
// fix their offsets
|
295 |
-
foreach ($positions as $i => $position) {
|
296 |
-
$positions[$i] -= $discardLength + strlen($match);
|
297 |
-
}
|
298 |
-
}
|
299 |
-
|
300 |
-
return $processed;
|
301 |
-
}
|
302 |
-
|
303 |
-
/**
|
304 |
-
* This is where a pattern is matched against $content and the matches
|
305 |
-
* are replaced by their respective value.
|
306 |
-
* This function will be called plenty of times, where $content will always
|
307 |
-
* move up 1 character.
|
308 |
-
*
|
309 |
-
* @param string $pattern Pattern to match
|
310 |
-
* @param string|callable $replacement Replacement value
|
311 |
-
* @param string $content Content to match pattern against
|
312 |
-
*
|
313 |
-
* @return string
|
314 |
-
*/
|
315 |
-
protected function replacePattern($pattern, $replacement, $content)
|
316 |
-
{
|
317 |
-
if (is_callable($replacement)) {
|
318 |
-
return preg_replace_callback($pattern, $replacement, $content, 1, $count);
|
319 |
-
} else {
|
320 |
-
return preg_replace($pattern, $replacement, $content, 1, $count);
|
321 |
-
}
|
322 |
-
}
|
323 |
-
|
324 |
-
/**
|
325 |
-
* Strings are a pattern we need to match, in order to ignore potential
|
326 |
-
* code-like content inside them, but we just want all of the string
|
327 |
-
* content to remain untouched.
|
328 |
-
*
|
329 |
-
* This method will replace all string content with simple STRING#
|
330 |
-
* placeholder text, so we've rid all strings from characters that may be
|
331 |
-
* misinterpreted. Original string content will be saved in $this->extracted
|
332 |
-
* and after doing all other minifying, we can restore the original content
|
333 |
-
* via restoreStrings().
|
334 |
-
*
|
335 |
-
* @param string[optional] $chars
|
336 |
-
* @param string[optional] $placeholderPrefix
|
337 |
-
*/
|
338 |
-
protected function extractStrings($chars = '\'"', $placeholderPrefix = '')
|
339 |
-
{
|
340 |
-
// PHP only supports $this inside anonymous functions since 5.4
|
341 |
-
$minifier = $this;
|
342 |
-
$callback = function ($match) use ($minifier, $placeholderPrefix) {
|
343 |
-
// check the second index here, because the first always contains a quote
|
344 |
-
if ($match[2] === '') {
|
345 |
-
/*
|
346 |
-
* Empty strings need no placeholder; they can't be confused for
|
347 |
-
* anything else anyway.
|
348 |
-
* But we still needed to match them, for the extraction routine
|
349 |
-
* to skip over this particular string.
|
350 |
-
*/
|
351 |
-
return $match[0];
|
352 |
-
}
|
353 |
-
|
354 |
-
$count = count($minifier->extracted);
|
355 |
-
$placeholder = $match[1].$placeholderPrefix.$count.$match[1];
|
356 |
-
$minifier->extracted[$placeholder] = $match[1].$match[2].$match[1];
|
357 |
-
|
358 |
-
return $placeholder;
|
359 |
-
};
|
360 |
-
|
361 |
-
/*
|
362 |
-
* The \\ messiness explained:
|
363 |
-
* * Don't count ' or " as end-of-string if it's escaped (has backslash
|
364 |
-
* in front of it)
|
365 |
-
* * Unless... that backslash itself is escaped (another leading slash),
|
366 |
-
* in which case it's no longer escaping the ' or "
|
367 |
-
* * So there can be either no backslash, or an even number
|
368 |
-
* * multiply all of that times 4, to account for the escaping that has
|
369 |
-
* to be done to pass the backslash into the PHP string without it being
|
370 |
-
* considered as escape-char (times 2) and to get it in the regex,
|
371 |
-
* escaped (times 2)
|
372 |
-
*/
|
373 |
-
$this->registerPattern('/(['.$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback);
|
374 |
-
}
|
375 |
-
|
376 |
-
/**
|
377 |
-
* This method will restore all extracted data (strings, regexes) that were
|
378 |
-
* replaced with placeholder text in extract*(). The original content was
|
379 |
-
* saved in $this->extracted.
|
380 |
-
*
|
381 |
-
* @param string $content
|
382 |
-
*
|
383 |
-
* @return string
|
384 |
-
*/
|
385 |
-
protected function restoreExtractedData($content)
|
386 |
-
{
|
387 |
-
if (!$this->extracted) {
|
388 |
-
// nothing was extracted, nothing to restore
|
389 |
-
return $content;
|
390 |
-
}
|
391 |
-
|
392 |
-
$content = strtr($content, $this->extracted);
|
393 |
-
|
394 |
-
$this->extracted = array();
|
395 |
-
|
396 |
-
return $content;
|
397 |
-
}
|
398 |
-
|
399 |
-
/**
|
400 |
-
* Check if the path is a regular file and can be read.
|
401 |
-
*
|
402 |
-
* @param string $path
|
403 |
-
*
|
404 |
-
* @return bool
|
405 |
-
*/
|
406 |
-
protected function canImportFile($path)
|
407 |
-
{
|
408 |
-
return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path);
|
409 |
-
}
|
410 |
-
|
411 |
-
/**
|
412 |
-
* Attempts to open file specified by $path for writing.
|
413 |
-
*
|
414 |
-
* @param string $path The path to the file
|
415 |
-
*
|
416 |
-
* @return resource Specifier for the target file
|
417 |
-
*
|
418 |
-
* @throws IOException
|
419 |
-
*/
|
420 |
-
protected function openFileForWriting($path)
|
421 |
-
{
|
422 |
-
if (($handler = @fopen($path, 'w')) === false) {
|
423 |
-
throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.');
|
424 |
-
}
|
425 |
-
|
426 |
-
return $handler;
|
427 |
-
}
|
428 |
-
|
429 |
-
/**
|
430 |
-
* Attempts to write $content to the file specified by $handler. $path is used for printing exceptions.
|
431 |
-
*
|
432 |
-
* @param resource $handler The resource to write to
|
433 |
-
* @param string $content The content to write
|
434 |
-
* @param string $path The path to the file (for exception printing only)
|
435 |
-
*
|
436 |
-
* @throws IOException
|
437 |
-
*/
|
438 |
-
protected function writeToFile($handler, $content, $path = '')
|
439 |
-
{
|
440 |
-
if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) {
|
441 |
-
throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.');
|
442 |
-
}
|
443 |
-
}
|
444 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/minify/src/index.html
DELETED
File without changes
|
libs/matthiasmullie/path-converter/index.html
DELETED
File without changes
|
libs/matthiasmullie/path-converter/src/Converter.php
DELETED
@@ -1,195 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MatthiasMullie\PathConverter;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Convert paths relative from 1 file to another.
|
7 |
-
*
|
8 |
-
* E.g.
|
9 |
-
* ../../images/icon.jpg relative to /css/imports/icons.css
|
10 |
-
* becomes
|
11 |
-
* ../images/icon.jpg relative to /css/minified.css
|
12 |
-
*
|
13 |
-
* Please report bugs on https://github.com/matthiasmullie/path-converter/issues
|
14 |
-
*
|
15 |
-
* @author Matthias Mullie <pathconverter@mullie.eu>
|
16 |
-
* @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
|
17 |
-
* @license MIT License
|
18 |
-
*/
|
19 |
-
class Converter implements ConverterInterface
|
20 |
-
{
|
21 |
-
/**
|
22 |
-
* @var string
|
23 |
-
*/
|
24 |
-
protected $from;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* @var string
|
28 |
-
*/
|
29 |
-
protected $to;
|
30 |
-
|
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
|
47 |
-
$from = realpath($from) ?: $from;
|
48 |
-
$to = realpath($to) ?: $to;
|
49 |
-
}
|
50 |
-
|
51 |
-
$from = $this->dirname($from);
|
52 |
-
$to = $this->dirname($to);
|
53 |
-
|
54 |
-
$from = $this->normalize($from);
|
55 |
-
$to = $this->normalize($to);
|
56 |
-
|
57 |
-
$this->from = $from;
|
58 |
-
$this->to = $to;
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Normalize path.
|
63 |
-
*
|
64 |
-
* @param string $path
|
65 |
-
*
|
66 |
-
* @return string
|
67 |
-
*/
|
68 |
-
protected function normalize($path)
|
69 |
-
{
|
70 |
-
// deal with different operating systems' directory structure
|
71 |
-
$path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/');
|
72 |
-
|
73 |
-
/*
|
74 |
-
* Example:
|
75 |
-
* /home/forkcms/frontend/cache/compiled_templates/../../core/layout/css/../images/img.gif
|
76 |
-
* to
|
77 |
-
* /home/forkcms/frontend/core/layout/images/img.gif
|
78 |
-
*/
|
79 |
-
do {
|
80 |
-
$path = preg_replace('/[^\/]+(?<!\.\.)\/\.\.\//', '', $path, -1, $count);
|
81 |
-
} while ($count);
|
82 |
-
|
83 |
-
return $path;
|
84 |
-
}
|
85 |
-
|
86 |
-
/**
|
87 |
-
* Figure out the shared path of 2 locations.
|
88 |
-
*
|
89 |
-
* Example:
|
90 |
-
* /home/forkcms/frontend/core/layout/images/img.gif
|
91 |
-
* and
|
92 |
-
* /home/forkcms/frontend/cache/minified_css
|
93 |
-
* share
|
94 |
-
* /home/forkcms/frontend
|
95 |
-
*
|
96 |
-
* @param string $path1
|
97 |
-
* @param string $path2
|
98 |
-
*
|
99 |
-
* @return string
|
100 |
-
*/
|
101 |
-
protected function shared($path1, $path2)
|
102 |
-
{
|
103 |
-
// $path could theoretically be empty (e.g. no path is given), in which
|
104 |
-
// case it shouldn't expand to array(''), which would compare to one's
|
105 |
-
// root /
|
106 |
-
$path1 = $path1 ? explode('/', $path1) : array();
|
107 |
-
$path2 = $path2 ? explode('/', $path2) : array();
|
108 |
-
|
109 |
-
$shared = array();
|
110 |
-
|
111 |
-
// compare paths & strip identical ancestors
|
112 |
-
foreach ($path1 as $i => $chunk) {
|
113 |
-
if (isset($path2[$i]) && $path1[$i] == $path2[$i]) {
|
114 |
-
$shared[] = $chunk;
|
115 |
-
} else {
|
116 |
-
break;
|
117 |
-
}
|
118 |
-
}
|
119 |
-
|
120 |
-
return implode('/', $shared);
|
121 |
-
}
|
122 |
-
|
123 |
-
/**
|
124 |
-
* Convert paths relative from 1 file to another.
|
125 |
-
*
|
126 |
-
* E.g.
|
127 |
-
* ../images/img.gif relative to /home/forkcms/frontend/core/layout/css
|
128 |
-
* should become:
|
129 |
-
* ../../core/layout/images/img.gif relative to
|
130 |
-
* /home/forkcms/frontend/cache/minified_css
|
131 |
-
*
|
132 |
-
* @param string $path The relative path that needs to be converted
|
133 |
-
*
|
134 |
-
* @return string The new relative path
|
135 |
-
*/
|
136 |
-
public function convert($path)
|
137 |
-
{
|
138 |
-
// quit early if conversion makes no sense
|
139 |
-
if ($this->from === $this->to) {
|
140 |
-
return $path;
|
141 |
-
}
|
142 |
-
|
143 |
-
$path = $this->normalize($path);
|
144 |
-
// if we're not dealing with a relative path, just return absolute
|
145 |
-
if (strpos($path, '/') === 0) {
|
146 |
-
return $path;
|
147 |
-
}
|
148 |
-
|
149 |
-
// normalize paths
|
150 |
-
$path = $this->normalize($this->from.'/'.$path);
|
151 |
-
|
152 |
-
// strip shared ancestor paths
|
153 |
-
$shared = $this->shared($path, $this->to);
|
154 |
-
$path = mb_substr($path, mb_strlen($shared));
|
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 |
-
}
|
162 |
-
|
163 |
-
/**
|
164 |
-
* Attempt to get the directory name from a path.
|
165 |
-
*
|
166 |
-
* @param string $path
|
167 |
-
*
|
168 |
-
* @return string
|
169 |
-
*/
|
170 |
-
protected function dirname($path)
|
171 |
-
{
|
172 |
-
if (is_file($path)) {
|
173 |
-
return dirname($path);
|
174 |
-
}
|
175 |
-
|
176 |
-
if (is_dir($path)) {
|
177 |
-
return rtrim($path, '/');
|
178 |
-
}
|
179 |
-
|
180 |
-
// no known file/dir, start making assumptions
|
181 |
-
|
182 |
-
// ends in / = dir
|
183 |
-
if (mb_substr($path, -1) === '/') {
|
184 |
-
return rtrim($path, '/');
|
185 |
-
}
|
186 |
-
|
187 |
-
// has a dot in the name, likely a file
|
188 |
-
if (preg_match('/.*\..*$/', basename($path)) !== 0) {
|
189 |
-
return dirname($path);
|
190 |
-
}
|
191 |
-
|
192 |
-
// you're on your own here!
|
193 |
-
return $path;
|
194 |
-
}
|
195 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/path-converter/src/ConverterInterface.php
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MatthiasMullie\PathConverter;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Convert file paths.
|
7 |
-
*
|
8 |
-
* Please report bugs on https://github.com/matthiasmullie/path-converter/issues
|
9 |
-
*
|
10 |
-
* @author Matthias Mullie <pathconverter@mullie.eu>
|
11 |
-
* @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
|
12 |
-
* @license MIT License
|
13 |
-
*/
|
14 |
-
interface ConverterInterface
|
15 |
-
{
|
16 |
-
/**
|
17 |
-
* Convert file paths.
|
18 |
-
*
|
19 |
-
* @param string $path The path to be converted
|
20 |
-
*
|
21 |
-
* @return string The new path
|
22 |
-
*/
|
23 |
-
public function convert($path);
|
24 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/path-converter/src/NoConverter.php
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace MatthiasMullie\PathConverter;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Don't convert paths.
|
7 |
-
*
|
8 |
-
* Please report bugs on https://github.com/matthiasmullie/path-converter/issues
|
9 |
-
*
|
10 |
-
* @author Matthias Mullie <pathconverter@mullie.eu>
|
11 |
-
* @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
|
12 |
-
* @license MIT License
|
13 |
-
*/
|
14 |
-
class NoConverter implements ConverterInterface
|
15 |
-
{
|
16 |
-
/**
|
17 |
-
* {@inheritdoc}
|
18 |
-
*/
|
19 |
-
public function convert($path)
|
20 |
-
{
|
21 |
-
return $path;
|
22 |
-
}
|
23 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/matthiasmullie/path-converter/src/index.html
DELETED
File without changes
|
libs/mrclay/HTML.php
DELETED
@@ -1,241 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/* https://github.com/mrclay/minify/blob/2.x/min/lib/Minify/HTML.php - same as WP ROCKET v2.91 + custom changes */
|
4 |
-
# line:
|
5 |
-
|
6 |
-
class fastvelocity_min_Minify_HTML {
|
7 |
-
protected $_jsCleanComments = true;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* "Minify" an HTML page
|
11 |
-
*
|
12 |
-
* @param string $html
|
13 |
-
*
|
14 |
-
* @param array $options
|
15 |
-
*
|
16 |
-
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
17 |
-
* elements.
|
18 |
-
*
|
19 |
-
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
20 |
-
* elements. Note: the type attribute is ignored.
|
21 |
-
*
|
22 |
-
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
23 |
-
* unset, minify will sniff for an XHTML doctype.
|
24 |
-
*
|
25 |
-
* @return string
|
26 |
-
*/
|
27 |
-
public static function minify($html, $options = array()) {
|
28 |
-
$min = new self($html, $options);
|
29 |
-
return $min->process();
|
30 |
-
}
|
31 |
-
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Create a minifier object
|
35 |
-
*
|
36 |
-
* @param string $html
|
37 |
-
*
|
38 |
-
* @param array $options
|
39 |
-
*
|
40 |
-
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
41 |
-
* elements.
|
42 |
-
*
|
43 |
-
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
44 |
-
* elements. Note: the type attribute is ignored.
|
45 |
-
*
|
46 |
-
* 'jsCleanComments' : (optional) whether to remove HTML comments beginning and end of script block
|
47 |
-
*
|
48 |
-
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
49 |
-
* unset, minify will sniff for an XHTML doctype.
|
50 |
-
*/
|
51 |
-
public function __construct($html, $options = array())
|
52 |
-
{
|
53 |
-
$this->_html = str_replace("\r\n", "\n", trim($html));
|
54 |
-
if (isset($options['xhtml'])) {
|
55 |
-
$this->_isXhtml = (bool)$options['xhtml'];
|
56 |
-
}
|
57 |
-
if (isset($options['cssMinifier'])) {
|
58 |
-
$this->_cssMinifier = $options['cssMinifier'];
|
59 |
-
}
|
60 |
-
if (isset($options['jsMinifier'])) {
|
61 |
-
$this->_jsMinifier = $options['jsMinifier'];
|
62 |
-
}
|
63 |
-
if (isset($options['jsCleanComments'])) {
|
64 |
-
$this->_jsCleanComments = (bool)$options['jsCleanComments'];
|
65 |
-
}
|
66 |
-
}
|
67 |
-
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Minify the markeup given in the constructor
|
71 |
-
*
|
72 |
-
* @return string
|
73 |
-
*/
|
74 |
-
public function process()
|
75 |
-
{
|
76 |
-
if ($this->_isXhtml === null) {
|
77 |
-
$this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
|
78 |
-
}
|
79 |
-
|
80 |
-
$this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
|
81 |
-
$this->_placeholders = array();
|
82 |
-
|
83 |
-
// replace SCRIPTs (and minify) with placeholders
|
84 |
-
$this->_html = preg_replace_callback(
|
85 |
-
'/(\\s*)<script(\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
|
86 |
-
,array($this, '_removeScriptCB')
|
87 |
-
,$this->_html);
|
88 |
-
|
89 |
-
// replace STYLEs (and minify) with placeholders
|
90 |
-
$this->_html = preg_replace_callback(
|
91 |
-
'/\\s*<style(\\b[^>]*>)([\\s\\S]*?)<\\/style>\\s*/i'
|
92 |
-
,array($this, '_removeStyleCB')
|
93 |
-
,$this->_html);
|
94 |
-
|
95 |
-
// remove HTML comments (not containing IE conditional comments).
|
96 |
-
global $strip_htmlcomments;
|
97 |
-
if($strip_htmlcomments) {
|
98 |
-
$this->_html = preg_replace_callback('/<!--([\\s\\S]*?)-->/' ,array($this, '_commentCB') ,$this->_html);
|
99 |
-
}
|
100 |
-
|
101 |
-
// replace PREs with placeholders
|
102 |
-
$this->_html = preg_replace_callback('/\\s*<pre(\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
|
103 |
-
,array($this, '_removePreCB')
|
104 |
-
,$this->_html);
|
105 |
-
|
106 |
-
// replace TEXTAREAs with placeholders
|
107 |
-
$this->_html = preg_replace_callback(
|
108 |
-
'/\\s*<textarea(\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
109 |
-
,array($this, '_removeTextareaCB')
|
110 |
-
,$this->_html);
|
111 |
-
|
112 |
-
// trim each line.
|
113 |
-
// @todo take into account attribute values that span multiple lines.
|
114 |
-
$this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
|
115 |
-
|
116 |
-
// remove ws around block/undisplayed elements
|
117 |
-
$this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
|
118 |
-
.'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
|
119 |
-
.'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
|
120 |
-
.'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
|
121 |
-
.'|ul)\\b[^>]*>)/i', '$1', $this->_html);
|
122 |
-
|
123 |
-
// remove ws outside of all elements
|
124 |
-
$this->_html = preg_replace_callback(
|
125 |
-
'/>([^<]+)</'
|
126 |
-
,array($this, '_outsideTagCB')
|
127 |
-
,$this->_html);
|
128 |
-
|
129 |
-
// use newlines before 1st attribute in open tags (to limit line lengths)
|
130 |
-
//$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
|
131 |
-
|
132 |
-
// fill placeholders
|
133 |
-
$this->_html = str_replace(
|
134 |
-
array_keys($this->_placeholders)
|
135 |
-
,array_values($this->_placeholders)
|
136 |
-
,$this->_html
|
137 |
-
);
|
138 |
-
// issue 229: multi-pass to catch scripts that didn't get replaced in textareas
|
139 |
-
$this->_html = str_replace(
|
140 |
-
array_keys($this->_placeholders)
|
141 |
-
,array_values($this->_placeholders)
|
142 |
-
,$this->_html
|
143 |
-
);
|
144 |
-
return $this->_html;
|
145 |
-
}
|
146 |
-
|
147 |
-
protected function _commentCB($m)
|
148 |
-
{
|
149 |
-
return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<![') || 0 === strpos($m[1], 'esi')) ? $m[0] : '';
|
150 |
-
}
|
151 |
-
|
152 |
-
protected function _reservePlace($content)
|
153 |
-
{
|
154 |
-
$placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
|
155 |
-
$this->_placeholders[$placeholder] = $content;
|
156 |
-
return $placeholder;
|
157 |
-
}
|
158 |
-
|
159 |
-
protected $_isXhtml = null;
|
160 |
-
protected $_replacementHash = null;
|
161 |
-
protected $_placeholders = array();
|
162 |
-
protected $_cssMinifier = null;
|
163 |
-
protected $_jsMinifier = null;
|
164 |
-
|
165 |
-
protected function _outsideTagCB($m)
|
166 |
-
{
|
167 |
-
return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
|
168 |
-
}
|
169 |
-
|
170 |
-
protected function _removePreCB($m)
|
171 |
-
{
|
172 |
-
return $this->_reservePlace("<pre{$m[1]}");
|
173 |
-
}
|
174 |
-
|
175 |
-
protected function _removeTextareaCB($m)
|
176 |
-
{
|
177 |
-
return $this->_reservePlace("<textarea{$m[1]}");
|
178 |
-
}
|
179 |
-
|
180 |
-
protected function _removeStyleCB($m)
|
181 |
-
{
|
182 |
-
$openStyle = "<style{$m[1]}";
|
183 |
-
$css = $m[2];
|
184 |
-
// remove css comments
|
185 |
-
$css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
|
186 |
-
|
187 |
-
// remove CDATA section markers
|
188 |
-
$css = $this->_removeCdata($css);
|
189 |
-
|
190 |
-
// minify
|
191 |
-
$minifier = $this->_cssMinifier ? $this->_cssMinifier : 'trim';
|
192 |
-
$css = call_user_func($minifier, $css);
|
193 |
-
$css = preg_replace('/\s+/', ' ', $css);
|
194 |
-
|
195 |
-
return $this->_reservePlace($this->_needsCdata($css)
|
196 |
-
? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
|
197 |
-
: "{$openStyle}{$css}</style>"
|
198 |
-
);
|
199 |
-
}
|
200 |
-
|
201 |
-
protected function _removeScriptCB($m)
|
202 |
-
{
|
203 |
-
$openScript = "<script{$m[2]}";
|
204 |
-
$js = $m[3];
|
205 |
-
|
206 |
-
// whitespace surrounding? preserve at least one space
|
207 |
-
$ws1 = ($m[1] === '') ? '' : ' ';
|
208 |
-
$ws2 = ($m[4] === '') ? '' : ' ';
|
209 |
-
|
210 |
-
// remove HTML comments (and ending "//" if present)
|
211 |
-
if ($this->_jsCleanComments) {
|
212 |
-
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
|
213 |
-
}
|
214 |
-
|
215 |
-
// remove CDATA section markers
|
216 |
-
$js = $this->_removeCdata($js);
|
217 |
-
|
218 |
-
// minify
|
219 |
-
$minifier = $this->_jsMinifier
|
220 |
-
? $this->_jsMinifier
|
221 |
-
: 'trim';
|
222 |
-
$js = call_user_func($minifier, $js);
|
223 |
-
|
224 |
-
return $this->_reservePlace($this->_needsCdata($js)
|
225 |
-
? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
|
226 |
-
: "{$ws1}{$openScript}{$js}</script>{$ws2}"
|
227 |
-
);
|
228 |
-
}
|
229 |
-
|
230 |
-
protected function _removeCdata($str)
|
231 |
-
{
|
232 |
-
return (false !== strpos($str, '<![CDATA['))
|
233 |
-
? str_replace(array('<![CDATA[', ']]>'), '', $str)
|
234 |
-
: $str;
|
235 |
-
}
|
236 |
-
|
237 |
-
protected function _needsCdata($str)
|
238 |
-
{
|
239 |
-
return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
|
240 |
-
}
|
241 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libs/mrclay/index.html
DELETED
File without changes
|
readme.txt
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
=== Fast Velocity Minify ===
|
2 |
Contributors: Alignak
|
3 |
-
Tags:
|
4 |
Requires at least: 4.5
|
5 |
-
Stable tag: 2.2.
|
6 |
-
Tested up to: 4.9.
|
7 |
License: GPLv3 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
9 |
|
@@ -30,26 +30,25 @@ I can offer you aditional `custom made` optimization on top of this plugin. If y
|
|
30 |
* Handles scripts loaded both in the header & footer separately
|
31 |
* Keeps the order of the scripts even if you exclude some files from minification
|
32 |
* Supports localized scripts (https://codex.wordpress.org/Function_Reference/wp_localize_script)
|
33 |
-
* Minifies CSS and
|
34 |
-
* Option to use YUI Compressor
|
35 |
* Option to defer JavaScript and CSS files.
|
36 |
-
*
|
37 |
-
* View
|
38 |
-
*
|
39 |
-
* Ability to turn off minification
|
40 |
-
* Ability to turn off CSS or JS optimization seperatly (by disabling either css or js processing)
|
41 |
* Ability to manually ignore scripts or css
|
42 |
* Support for conditional scripts and styles
|
43 |
* Support for multisite installations
|
44 |
* Support for gzip_static on Nginx
|
45 |
-
*
|
46 |
* Auto purging of cache files on W3 Total Cache, WP Supercache, WP Rocket, Wp Fastest Cache, Cachify, Comet Cache, Zen Cache, LiteSpeed Cache, Nginx Cache (by Till Krüss ), SG Optimizer, Godaddy Managed WordPress Hosting and WP Engine (read the FAQs)
|
47 |
* Support for preconnect and preload headers
|
48 |
* and some more...
|
49 |
|
50 |
|
51 |
= Notes =
|
52 |
-
* The JavaScript minification is by
|
|
|
53 |
* The alternative JavaScript minification is by [YUI Compressor](http://yui.github.io/yuicompressor/)
|
54 |
* Compatible with Nginx, HHVM and PHP 7.
|
55 |
* Minimum requirements are PHP 5.5 and WP 4.4, from version 1.4.0 onwards
|
@@ -71,151 +70,111 @@ I can offer you aditional `custom made` optimization on top of this plugin. If y
|
|
71 |
== Frequently Asked Questions ==
|
72 |
|
73 |
= How can I exclude certain assets by wildcard? =
|
74 |
-
|
75 |
-
Each line on the ignore list will try to match a substring against all CSS or JS files, for example: `//yoursite.com/wp-content/plugins/some-plugin/js/` will ignore all files inside that directory. You can also shorten the url like `/some-plugin/js/` and then it will match any css or js url that has `/some-plugin/js/` on the path. Obviously, doing `/js/` would match any files inside any "/js/" directory and in any location, so to avoid unexpected situations please always use the longest, most specific path you can use.
|
76 |
-
|
77 |
...
|
78 |
|
79 |
= Why is the ignore list not working? =
|
80 |
-
|
81 |
-
The ignore list may be working, just try to use partial paths (see wildcard help above) and use relative urls only without any query vars.
|
82 |
-
|
83 |
...
|
84 |
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
Well, some sites and themes have a combined CSS size above 1+ MB, so when you have 200 files, that's 200+ MB.
|
89 |
-
Different pages may need different JS and CSS files per page, post, category, tag, homepage or even custom post types, but if the requirements never change and you always load the exact same files on every page, you won't see as many files. Likewise, if you have some dynamic url for CSS or JS that always changes in each pageview (the query var for example), you must add it to the ignore list (else it will generate a new cache file every pageview).
|
90 |
-
|
91 |
...
|
92 |
-
|
93 |
= Can I update plugins and themes? =
|
|
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
= Is it compatible with other caching plugins? =
|
100 |
-
|
101 |
-
You must disable any features on your theme or cache plugins, that perform minification of css, html and js.
|
102 |
-
The plugin will try to automatically purge several popular cache plugins, however we still recommend you to purge all caches (on whatever you use) if you also manually purge the cache on the plugin settings for some reason.
|
103 |
The automatic purge is active for the following plugins and hosting: W3 Total Cache, WP Supercache, WP Rocket, Wp Fastest Cache, Cachify, Comet Cache, Zen Cache, LiteSpeed Cache, SG Optimizer, Godaddy Managed WordPress Hosting and WP Engine
|
104 |
|
105 |
...
|
106 |
|
107 |
= Is it resource intensive, or will it use too much CPU on my shared hosting plan? =
|
108 |
-
|
109 |
-
No it's not. On the first run, each single file is minified into an intermediate cache. When a new group of files is found, it reuses those files and merges them into a new static cache file. All pages that request the same group of CSS or JS files will also make use of that file.
|
110 |
-
|
111 |
...
|
112 |
-
|
113 |
= Is it compatible with multisites? =
|
114 |
-
|
115 |
-
Yes, it generates a new cache file for every different set of JS and CSS requirements it finds.
|
116 |
-
|
117 |
...
|
118 |
-
|
119 |
= Is it compatible with Adsense and other ad networks? =
|
120 |
-
|
121 |
-
The plugin is compatible with any add network but also depends on how you're loading the ads into the site. We only merge and minify css and javascript files enqueued in the header and footer that match your own domain name... which would exclude any external ads. If you're using a plugin that uses JS to insert the ads on the page, there could be issues. Please report on the support forum if you found such case.
|
122 |
|
123 |
...
|
124 |
|
125 |
= After installing, why did my site feels slow to load? =
|
126 |
-
|
127 |
-
The cache regeration happen's once per url or if the included CSS + JS files change. If you need the same set of CSS and JS files in every page, the cache file will only be generated once and reused for all other pages, however if you have a CSS or JS that is generated dynamically and uses a time based query string, (url changes on every pageview), you must add it to the ignore list by wildcard.
|
128 |
|
129 |
...
|
130 |
|
131 |
-
= How do I use the
|
132 |
|
133 |
When we merge and minify the css and js files, we also create a `.gz` file to be used with `gzip_static` on Nginx. You need to enable this feature on your Nginx configuration file if you want to make use of it.
|
134 |
|
135 |
...
|
136 |
|
137 |
-
= Where is the YUI Compressor option
|
138 |
-
|
139 |
-
This functionality depends on wheter you have exec and java available on your system and PHP can detect it or not. It will be visible on the basic Settings page under the JavaScript Options section and it's available for JS files only.
|
140 |
|
141 |
...
|
142 |
|
143 |
= After installing, why are some images and sliders not working? =
|
144 |
|
145 |
-
a) You cannot do double minification as it will break things, so make sure you have disabled any features on your theme or other plugins,
|
146 |
|
147 |
b) Are you trying to use the defer JS or CSS options, without understanding exactly how it works? Be advised that most themes do not work properly with those options on.
|
148 |
|
149 |
-
c)
|
150 |
|
151 |
-
d) Sometimes a plugin conflicts with another when merged. Try to disable CSS processing first and see if it works. Try to disable JS processing second and see if it works. Try to disable HTML minification last and see if it works. If one of those work, you know
|
152 |
|
153 |
-
e) If you have a conflict, try to add each CSS and each JS to the ignore list, one by one until you find the one that causes the conflict. If you have no idea which files to add, check the log file on the status page for a list of files.
|
154 |
|
155 |
...
|
156 |
|
157 |
-
= Why are some of the CSS and JS files not being merged
|
158 |
|
159 |
The plugin only processes (same domain) JS and CSS files enqueued using the official method outlined here: https://developer.wordpress.org/themes/basics/including-css-javascript/
|
160 |
-
|
161 |
-
Some developers enqueue all files properly but may still "print" conditional tags directly in the header, while they should be following the example as explained on the codex: https://developer.wordpress.org/reference/functions/wp_script_add_data/
|
162 |
-
|
163 |
-
Because "printing CSS and JS tags on the header and footer is evil" (seriously), we cannot capture those files and merge them together.
|
164 |
-
|
165 |
-
There are also specific ways to enqueue files meant to be loaded for IE users only, mobile users, desktop users, printers, etc, else those may be merged together and break things. There is a blacklist and default ignore list on the PRO tab because of this.
|
166 |
|
167 |
...
|
168 |
|
169 |
= How can I load CSS async, get the critical path or why is there a flash of unstyle content when I enable this? =
|
170 |
-
|
171 |
This is an advanced option for highly skilled developers. Do not try to fiddle with these settings if you are not one, as it will almost certainly break your site layout and functionality.
|
172 |
-
|
173 |
Loading CSS async only works properly and consistently, when you have one single CSS file being generated and your critical path is generic enough to be common on all pages.
|
174 |
|
175 |
...
|
176 |
|
177 |
= How to undo all changes done by the plugin? =
|
178 |
-
|
179 |
-
The plugin itself doesn't do any "changes" to your site and all original files are untouched. It intercepts the enqueued CSS and JS files, processes and hides them, while enqueuing the newly optimized cached version of those files. As with any plugin, simply disable or uninstall the plugin, purge all caches you may have in use (plugins, server, cloudflare, etc) and the site will go back to what it was before installing it. The plugin doesn't delete anything from the database or modify any of your files.
|
180 |
-
|
181 |
...
|
182 |
|
183 |
= Why is it that even though I have disabled or deleted the plugin, the design is still broken? =
|
184 |
-
|
185 |
-
Some
|
186 |
-
|
187 |
-
Some providers use a "deploy system", where you upload / replace / delete the files via sftp, but those are not reflected on the live site immediatly. This means that in some cases, you can delete your whole wordpress instalation via sftp, and the site still works perfectly fine even after purging the cache.
|
188 |
-
|
189 |
-
You may have deleted the physical files from the disk, but that's either just some random storage they gave you and that they sync to the main server every few hours, or it may be the actual live server but with a file cache layer on top of it (so the old code keeps running even though you have deleted the files).
|
190 |
-
|
191 |
-
The only solution is to contact your hosting company and ask them why you have deleted the plugin and purged your cache, but the live site doesn't reflect the changes.
|
192 |
-
|
193 |
Providers well known to have this issue are hostgator and iPage (please report others if you find them).
|
194 |
-
|
195 |
...
|
196 |
|
197 |
-
=
|
198 |
-
|
199 |
-
Some plugins and themes need to edit the layout and styles on the frontend. When they need to do that, they enqueue several extra js and css files that are caught by this plugin and get merged together, when in fact those need to load seperatly. If you encounter such issue of your page editor not working on the frontend, kindly enable the "Fix Page Editors" and purge your caches.
|
200 |
-
|
201 |
-
This option hides all optimization from logged in users, so it's as iff the plugin has been disabled. Not logged in users and search engines, still see the optimized version.
|
202 |
-
|
203 |
...
|
204 |
|
205 |
-
=
|
|
|
|
|
|
|
206 |
|
207 |
-
|
|
|
208 |
|
209 |
-
|
210 |
|
211 |
-
Don't put too many images here as those are downloaded in high priority and it will slow down the rest of the page load.
|
212 |
|
|
|
|
|
213 |
...
|
214 |
|
215 |
= What are the recommended cloudflare settings for this plugin? =
|
216 |
-
|
217 |
On the "Speed" tab, deselect the Auto Minify for JavaScript, CSS and HTML as well as the Rocket Loader option as there is no benefit of using them with our plugin (we already minify things).
|
218 |
-
|
219 |
Those options can also break the design due to double minification or the fact that the Rocket Loader is still experimental (you can read about that on the "Help" link under each selected option on cloudflare).
|
220 |
|
221 |
...
|
@@ -226,7 +185,7 @@ Before getting angry because you have no answer within a few hours (even with pa
|
|
226 |
|
227 |
The plugins directory is an open source, free service where developers and programmers contribute (on their free time) with plugins that can be downloaded and installed by anyone "at their own risk" and are all released under the GPL license.
|
228 |
|
229 |
-
While all plugins have to be approved and reviewed by the
|
230 |
|
231 |
Support is provided by plugin authors on their free time and without warranty of a reply, so you can experience different levels of support level from plugin to plugin. As the author of this plugin I strive to provide support on a daily basis and I can take a look and help you with some issues related with my plugin, but please note that this is done out of my goodwill and in no way I have any legal or moral obligation for doing this. I'm also available for hiring if you need custom made speed optimizations (check my profile links).
|
232 |
|
@@ -236,18 +195,19 @@ For a full version of the license, please read: https://wordpress.org/about/gpl/
|
|
236 |
|
237 |
= Where can I get support or report bugs? =
|
238 |
|
239 |
-
You can get support on the official
|
240 |
-
You can also see my profile and check my links if you wish to hire me for custom speed optimization on
|
241 |
|
242 |
...
|
243 |
|
244 |
= How can I donate to the plugin author? =
|
245 |
|
246 |
-
If you would like to donate any amount to the plugin author (thank you in advance), you can do it via
|
247 |
|
248 |
...
|
249 |
|
250 |
|
|
|
251 |
== Upgrade Notice ==
|
252 |
|
253 |
= 2.2.4 =
|
@@ -256,6 +216,13 @@ Note: Kindly re-save all options and purge all caches (the plugin cache as well
|
|
256 |
|
257 |
== Changelog ==
|
258 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
= 2.2.6 [2018.01.06] =
|
260 |
* fixed a bug with html minification on some files that should not be minified
|
261 |
* fixed a bug with the defer for pagespeed insights
|
1 |
=== Fast Velocity Minify ===
|
2 |
Contributors: Alignak
|
3 |
+
Tags: CSSTidy, JSMin, YUI Compressor, GTmetrix, Pingdom, Pagespeed, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance
|
4 |
Requires at least: 4.5
|
5 |
+
Stable tag: 2.2.7
|
6 |
+
Tested up to: 4.9.4
|
7 |
License: GPLv3 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
9 |
|
30 |
* Handles scripts loaded both in the header & footer separately
|
31 |
* Keeps the order of the scripts even if you exclude some files from minification
|
32 |
* Supports localized scripts (https://codex.wordpress.org/Function_Reference/wp_localize_script)
|
33 |
+
* Minifies CSS, JS and HTML with PHP only
|
34 |
+
* Option to use YUI Compressor (you must have "exec" and "java" available on your system).
|
35 |
* Option to defer JavaScript and CSS files.
|
36 |
+
* Cache files are stored and served directly from the disk.
|
37 |
+
* View merging logs on the admin page.
|
38 |
+
* Ability to turn off CSS, JS or HTML processing
|
|
|
|
|
39 |
* Ability to manually ignore scripts or css
|
40 |
* Support for conditional scripts and styles
|
41 |
* Support for multisite installations
|
42 |
* Support for gzip_static on Nginx
|
43 |
+
* CDN support
|
44 |
* Auto purging of cache files on W3 Total Cache, WP Supercache, WP Rocket, Wp Fastest Cache, Cachify, Comet Cache, Zen Cache, LiteSpeed Cache, Nginx Cache (by Till Krüss ), SG Optimizer, Godaddy Managed WordPress Hosting and WP Engine (read the FAQs)
|
45 |
* Support for preconnect and preload headers
|
46 |
* and some more...
|
47 |
|
48 |
|
49 |
= Notes =
|
50 |
+
* The JavaScript minification is by JSMin](https://github.com/rgrove/jsmin-php/blob/master/jsmin.php)
|
51 |
+
* The CSS minification is by [CSSTidy](https://github.com/Cerdic/CSSTidy)
|
52 |
* The alternative JavaScript minification is by [YUI Compressor](http://yui.github.io/yuicompressor/)
|
53 |
* Compatible with Nginx, HHVM and PHP 7.
|
54 |
* Minimum requirements are PHP 5.5 and WP 4.4, from version 1.4.0 onwards
|
70 |
== Frequently Asked Questions ==
|
71 |
|
72 |
= How can I exclude certain assets by wildcard? =
|
73 |
+
Each line on the ignore list will try to match a substring against all CSS or JS files, for example: `//yoursite.com/wp-content/plugins/some-plugin/js/` will ignore all files that have this on the path. You can also shorten the url like `/some-plugin/js/` and then it will match any css or js url that has `/some-plugin/js/` on the path. Obviously, doing `/js/` would match any files inside any "/js/" directory and in any location, so to avoid unexpected situations please always use the longest, most specific path you can use.
|
|
|
|
|
74 |
...
|
75 |
|
76 |
= Why is the ignore list not working? =
|
77 |
+
The ignore list may be working, just try to use partial paths (see wildcard help above) and use relative urls only without any query vars. Example, if you want to exclude a file names `/jquery.js?v=1234` simply add the wildcard `/jquery.js` before the question mark.
|
|
|
|
|
78 |
...
|
79 |
|
80 |
+
= There are too many JS or CSS files generated, or the cache directory is taking too much space. =
|
81 |
+
a) Different pages may need different JS and CSS files per page, post, category, tag, homepage or even custom post types, therefore you need a file per requirement. b) If you have a dynamic CSS file that changes its name on each page view (the query var for example), you must add it by wildcard to the ignore list (else it will generate a new cache file every page view).
|
|
|
|
|
|
|
|
|
82 |
...
|
|
|
83 |
= Can I update plugins and themes? =
|
84 |
+
Yes, but it is recommended that you purge all caches in order. First from the plugin status page, then your cache plugin and finally your hosting provider cache system. This is to make sure that your update, is not breaking things, which you wouldn’t see until FVM cached files or the page cache expires.
|
85 |
|
86 |
+
= Is it compatible with other caching plugins, or other speed optimization plugins? =
|
87 |
+
Yes and No. You must disable any features on your theme or plugins, which perform minification of css, html and js, else double minification may break your layout. It’s also inefficient to do the same work twice.
|
88 |
+
The plugin will try to automatically purge several popular cache plugins, however we still recommend you to purge all caches (on whatever you use) if you also manually purge the cache on the plugin settings for some reason.
|
|
|
|
|
|
|
|
|
|
|
89 |
The automatic purge is active for the following plugins and hosting: W3 Total Cache, WP Supercache, WP Rocket, Wp Fastest Cache, Cachify, Comet Cache, Zen Cache, LiteSpeed Cache, SG Optimizer, Godaddy Managed WordPress Hosting and WP Engine
|
90 |
|
91 |
...
|
92 |
|
93 |
= Is it resource intensive, or will it use too much CPU on my shared hosting plan? =
|
94 |
+
No, it is not. Cache files are saved on your disk, so as long as you have a fast SSD disk, you have nothing to worry about.
|
|
|
|
|
95 |
...
|
|
|
96 |
= Is it compatible with multisites? =
|
97 |
+
Yes, it generates a new cache file for every different set of JS and CSS requirements it finds, but you need to setup the settings for each site individually (the settings may need to be different for each site).
|
|
|
|
|
98 |
...
|
|
|
99 |
= Is it compatible with Adsense and other ad networks? =
|
100 |
+
The plugin is compatible with any add network but also depends on how you are loading the ads into the site. We only merge and minify css and JavaScript files enqueued in the header and footer that match your own domain name... which would exclude any external ads. If you are using a plugin that uses JS to insert the ads on the page, there could be issues. Please report on the support forum if you found such case.
|
|
|
101 |
|
102 |
...
|
103 |
|
104 |
= After installing, why did my site feels slow to load? =
|
105 |
+
If you have a CSS or JS that is generated dynamically with PHP and uses a time based query string, (url changes on every page view), you must add it to the ignore list by wildcard. If you don’t do this, every single pageview will generate a new file cache, thus filling your storage very quickly.
|
|
|
106 |
|
107 |
...
|
108 |
|
109 |
+
= How do I use the pre-compressed files with gzip_static on Nginx? =
|
110 |
|
111 |
When we merge and minify the css and js files, we also create a `.gz` file to be used with `gzip_static` on Nginx. You need to enable this feature on your Nginx configuration file if you want to make use of it.
|
112 |
|
113 |
...
|
114 |
|
115 |
+
= Where is the YUI Compressor option? =
|
116 |
+
This functionality depends on whether you have exec and java available on your system and PHP can detect it or not. It will be visible on the basic Settings page under the JavaScript Options section and it is available for JS files only.
|
|
|
117 |
|
118 |
...
|
119 |
|
120 |
= After installing, why are some images and sliders not working? =
|
121 |
|
122 |
+
a) You cannot do double minification as it will break things, so make sure you have disabled any features on your theme or other plugins, which perform minification of css, html and js files.
|
123 |
|
124 |
b) Are you trying to use the defer JS or CSS options, without understanding exactly how it works? Be advised that most themes do not work properly with those options on.
|
125 |
|
126 |
+
c) Try to disable minification on JS and CSS files and purge the cache.
|
127 |
|
128 |
+
d) Sometimes a plugin conflicts with another when merged. Try to disable CSS processing first and see if it works. Try to disable JS processing second and see if it works. Try to disable HTML minification last and see if it works. If one of those work, you know where is a conflict.
|
129 |
|
130 |
+
e) If you have a conflict, try to add each CSS and each JS to the ignore list, one by one until you find the one that causes the conflict. If you have no idea, which files to add, check the log file on the status page for a list of files.
|
131 |
|
132 |
...
|
133 |
|
134 |
+
= Why are some of the CSS and JS files not being merged? =
|
135 |
|
136 |
The plugin only processes (same domain) JS and CSS files enqueued using the official method outlined here: https://developer.wordpress.org/themes/basics/including-css-javascript/
|
137 |
+
Furthermore, there is a blacklist, an ignore list and a default ignore list (check the Pro tab for a list of files). These are all known files, which cause trouble, but feel free to try again.
|
|
|
|
|
|
|
|
|
|
|
138 |
|
139 |
...
|
140 |
|
141 |
= How can I load CSS async, get the critical path or why is there a flash of unstyle content when I enable this? =
|
|
|
142 |
This is an advanced option for highly skilled developers. Do not try to fiddle with these settings if you are not one, as it will almost certainly break your site layout and functionality.
|
|
|
143 |
Loading CSS async only works properly and consistently, when you have one single CSS file being generated and your critical path is generic enough to be common on all pages.
|
144 |
|
145 |
...
|
146 |
|
147 |
= How to undo all changes done by the plugin? =
|
148 |
+
The plugin itself does not do any "changes" to your site and all original files are untouched. It also does not create or delete tables on the database. As with any plugin, simply disable or uninstall the plugin, purge all caches (plugins, server, cloudflare, etc.) and the site will go back to what it was before installing it. The plugin does not delete anything from the database or modify any of your files.
|
|
|
|
|
149 |
...
|
150 |
|
151 |
= Why is it that even though I have disabled or deleted the plugin, the design is still broken? =
|
152 |
+
Some hosting providers have very aggressive caches on their servers, and they will ignore your multiple cache purge requests if those are too frequent. Contact your hosting and have them purge varnish, object cache, memcached, redis, APC, or whatever system they may use.
|
153 |
+
Some providers also use a "deploy system" where you can upload / replace / delete the files via sftp, but those are not reflected on the live site immediately. It’s merely a copy, which will be synced sometime later automatically. The only solution is to contact your hosting company and ask them why you have deleted the plugin and purged your cache, but the live site does not reflect the changes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
Providers well known to have this issue are hostgator and iPage (please report others if you find them).
|
|
|
155 |
...
|
156 |
|
157 |
+
= My layout is broken if I disable the plugin, but works fine if I enable it. =
|
158 |
+
See the previous answer for the reason. As soon as you disable the plugin, the cache is purged and any references to `/wp-content/uploads/fvm/` on your html, must disappear. If it did not, there is a cache problem somewhere causing this. Contact your hosting company to manually purge your caches.
|
|
|
|
|
|
|
|
|
159 |
...
|
160 |
|
161 |
+
= Why is my Visual Composer or Page Editor not working? =
|
162 |
+
Kindly enable the "Fix Page Editors" and purge the cache.
|
163 |
+
This option hides all optimization from logged in users, so it is as if the plugin is disabled. Not logged in users and search engines, still see the optimized version. If this doesn’t work for you, please open a support request on the forum.
|
164 |
+
...
|
165 |
|
166 |
+
= Why is NextGEN Gallery not working? =
|
167 |
+
You need to have render blocking jQuery for this plugin (it's a requirement), so you must exclude the jquery library via the ignore list. NextGEN Gallery CSS files, for the majority cannot be merged (even if you copy paste manually one after the other), due to the lack of speceficity on CSS. I have reported this to the author on https://wordpress.org/support/topic/lack-of-css-specificity-and-conflict-when-merging/ so meanwhile, you can either inline all css or add their css files to the ignore list.
|
168 |
|
169 |
+
...
|
170 |
|
|
|
171 |
|
172 |
+
= How should I use the "Preload Images" and what is it for? =
|
173 |
+
You can use the "Preload Images" for the first relevant images that load above the fold on all pages, such as the logo or social icons. Do not put too many images here as those are downloaded in high priority and it will slow down the rest of the page load.
|
174 |
...
|
175 |
|
176 |
= What are the recommended cloudflare settings for this plugin? =
|
|
|
177 |
On the "Speed" tab, deselect the Auto Minify for JavaScript, CSS and HTML as well as the Rocket Loader option as there is no benefit of using them with our plugin (we already minify things).
|
|
|
178 |
Those options can also break the design due to double minification or the fact that the Rocket Loader is still experimental (you can read about that on the "Help" link under each selected option on cloudflare).
|
179 |
|
180 |
...
|
185 |
|
186 |
The plugins directory is an open source, free service where developers and programmers contribute (on their free time) with plugins that can be downloaded and installed by anyone "at their own risk" and are all released under the GPL license.
|
187 |
|
188 |
+
While all plugins have to be approved and reviewed by the WordPress team before being published ( for dangerous code, spam, etc. ) this doesn't change the license or add any warranty. All plugins are provided as they are, free of charge and should be used at your own risk (so you should make backups before installing any plugin or performing updates) and it's your sole responsibility if you break your site after installing a plugin from the plugins directory.
|
189 |
|
190 |
Support is provided by plugin authors on their free time and without warranty of a reply, so you can experience different levels of support level from plugin to plugin. As the author of this plugin I strive to provide support on a daily basis and I can take a look and help you with some issues related with my plugin, but please note that this is done out of my goodwill and in no way I have any legal or moral obligation for doing this. I'm also available for hiring if you need custom made speed optimizations (check my profile links).
|
191 |
|
195 |
|
196 |
= Where can I get support or report bugs? =
|
197 |
|
198 |
+
You can get support on the official WordPress plugin page at https://wordpress.org/support/plugin/fast-velocity-minify
|
199 |
+
You can also see my profile and check my links if you wish to hire me for custom speed optimization on WordPress or extra features.
|
200 |
|
201 |
...
|
202 |
|
203 |
= How can I donate to the plugin author? =
|
204 |
|
205 |
+
If you would like to donate any amount to the plugin author (thank you in advance), you can do it via PayPal at https://goo.gl/vpLrSV
|
206 |
|
207 |
...
|
208 |
|
209 |
|
210 |
+
|
211 |
== Upgrade Notice ==
|
212 |
|
213 |
= 2.2.4 =
|
216 |
|
217 |
== Changelog ==
|
218 |
|
219 |
+
= 2.2.7 [2018.02.19] =
|
220 |
+
* fixed a bug with the blacklist functionality
|
221 |
+
* replaced PHP Minify with JSMin as the default JS minification
|
222 |
+
* replaced PHP Minify with CSSTidy as the default CSS minification
|
223 |
+
* replaced PHP Minify with Minify HTML as the default HTML minification
|
224 |
+
* moved the intermediary cache from transients to disk files
|
225 |
+
|
226 |
= 2.2.6 [2018.01.06] =
|
227 |
* fixed a bug with html minification on some files that should not be minified
|
228 |
* fixed a bug with the defer for pagespeed insights
|