Fast Velocity Minify - Version 2.3.2

Version Description

[2018.06.03] = * added some compatibility fixes when merging and minifying JS files * added an option to enable an "FVM Purge" button on the admin bar * moved all large transients (cached css or js code) to temporary disk files to reduce the database load

Download this release

Release Info

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

Code changes from version 2.3.1 to 2.3.2

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.3.1
9
  License: GPL2
10
 
11
  ------------------------------------------------------------------------
@@ -102,6 +102,7 @@ $ignore = array_map('trim', explode("\n", get_option('fastvelocity_min_ignore',
102
  $blacklist = array_map('trim', explode("\n", get_option('fastvelocity_min_blacklist', '')));
103
  $ignorelist = array_map('trim', explode("\n", get_option('fastvelocity_min_ignorelist', '')));
104
  $merge_allowed_urls = array_map('trim', explode("\n", get_option('fastvelocity_min_merge_allowed_urls', '')));
 
105
  $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
106
  $disable_js_merge = get_option('fastvelocity_min_disable_js_merge');
107
  $disable_css_merge = get_option('fastvelocity_min_disable_css_merge');
@@ -132,6 +133,7 @@ $fvm_remove_css = get_option('fastvelocity_min_fvm_removecss');
132
  $critical_path_css = get_option('fastvelocity_min_critical_path_css');
133
  $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
134
 
 
135
  # default options
136
  $used_css_files = array();
137
 
@@ -140,7 +142,7 @@ $exc = array('/html5shiv.js', '/html5shiv-printshiv.min.js', '/excanvas.js', '/a
140
  if(!is_array($blacklist) || strlen(implode($blacklist)) == 0) { update_option('fastvelocity_min_blacklist', implode("\n", $exc)); }
141
 
142
  # default ignore list
143
- $exc = array('/Avada/assets/js/main.min.js', '/woocommerce-product-search/js/product-search.js', '/includes/builder/scripts/frontend-builder-scripts.js', '/assets/js/jquery.themepunch.tools.min.js', '/js/TweenMax.min.js');
144
  if(!is_array($ignorelist) || strlen(implode($ignorelist)) == 0) { update_option('fastvelocity_min_ignorelist', implode("\n", $exc)); }
145
 
146
 
@@ -221,6 +223,27 @@ add_options_page('Fast Velocity Minify Settings', 'Fast Velocity Minify', 'manag
221
  }
222
 
223
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  # function to list all cache files
225
  function fastvelocity_min_files_callback() {
226
  global $cachedir;
@@ -271,6 +294,7 @@ function fastvelocity_min_load_admin_jscss($hook) {
271
  # register plugin settings
272
  function fastvelocity_min_register_settings() {
273
  register_setting('fvm-group', 'fastvelocity_min_ignore');
 
274
  register_setting('fvm-group', 'fastvelocity_min_default_protocol');
275
  register_setting('fvm-group', 'fastvelocity_min_disable_js_merge');
276
  register_setting('fvm-group', 'fastvelocity_min_disable_css_merge');
@@ -314,10 +338,10 @@ function fastvelocity_min_register_settings() {
314
 
315
  # add settings link on plugin page
316
  function fastvelocity_min_settings_link($links) {
317
- if (is_plugin_active(plugin_basename( __FILE__ ))) {
318
- $settings_link = '<a href="options-general.php?page=fastvelocity-min&tab=settings">Settings</a>';
319
- array_unshift($links, $settings_link);
320
- }
321
  return $links;
322
  }
323
  add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
@@ -341,11 +365,14 @@ $active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'status';
341
  <?php
342
 
343
  # purge all caches
344
- if(isset($_POST['purgeall']) && $_POST['purgeall'] == 1) {
345
- fvm_purge_all(); # purge all
346
- echo __('<div class="notice notice-success is-dismissible"><p>The <strong>CSS and JS</strong> files have been purged!</p></div>');
347
- echo fastvelocity_purge_others(); # purge third party caches
 
 
348
  }
 
349
  ?>
350
 
351
  <h2 class="nav-tab-wrapper wp-clearfix">
@@ -412,6 +439,17 @@ echo fastvelocity_purge_others(); # purge third party caches
412
  <table class="form-table fvm-settings">
413
  <tbody>
414
 
 
 
 
 
 
 
 
 
 
 
 
415
  <tr>
416
  <th scope="row">Troubleshooting</th>
417
  <td>
@@ -796,7 +834,7 @@ Async CSS with LoadCSS<span class="note-info">[ Only works if "Inline all header
796
 
797
  <div style="height: 20px;"></div>
798
  <h2 class="title">Cache Location</h2>
799
- <p class="fvm-bold-green">Make sure you choose a publicly available directory and that there are writting permissions on that directory.</p>
800
  <table class="form-table fvm-settings">
801
  <tbody>
802
  <tr>
@@ -813,7 +851,7 @@ Async CSS with LoadCSS<span class="note-info">[ Only works if "Inline all header
813
  <td><fieldset>
814
  <label for="fastvelocity_min_change_cache_base_url">
815
  <p><input type="text" name="fastvelocity_min_change_cache_base_url" id="fastvelocity_min_change_cache_base_url" value="<?php echo get_option('fastvelocity_min_change_cache_base_url', ''); ?>" size="80" /></p>
816
- <p class="description">[ Default cache base url is: <?php echo trim(fvm_get_protocol(wp_upload_dir()['baseurl']), '/'); ?> ]</p>
817
  </label>
818
  </fieldset></td>
819
  </tr>
@@ -946,7 +984,7 @@ for($i=0,$l=count($header);$i<$l;$i++) {
946
 
947
  # get css from hurl, if available and valid
948
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
949
- $newcode = false; $newcode = get_transient($tkey);
950
  if ( $newcode === false) {
951
  $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
952
  if(is_array($res)) {
@@ -1079,7 +1117,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1079
 
1080
  # get css from hurl, if available and valid
1081
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1082
- $newcode = false; $newcode = get_transient($tkey);
1083
  if ( $newcode === false) {
1084
  $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
1085
  if(is_array($res)) {
@@ -1284,7 +1322,7 @@ if(!$skip_google_fonts && count($google_fonts) > 0) {
1284
 
1285
  # google fonts download and inlining, ignore logs
1286
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1287
- $newcode = false; $newcode = get_transient($tkey);
1288
  if ( $newcode === false) {
1289
  $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
1290
  if(is_array($res)) { $newcode = $res['code']; }
@@ -1412,7 +1450,7 @@ for($i=0,$l=count($header);$i<$l;$i++) {
1412
 
1413
  # get css from hurl, if available and valid
1414
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1415
- $newcode = false; $newcode = get_transient($tkey);
1416
  if ( $newcode === false) {
1417
  $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
1418
  if(is_array($res)) {
@@ -1548,7 +1586,7 @@ if(!$skip_google_fonts && count($google_fonts) > 0) {
1548
 
1549
  # google fonts download and inlining, ignore logs
1550
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1551
- $newcode = false; $newcode = get_transient($tkey);
1552
  if ( $newcode === false) {
1553
  $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
1554
  if(is_array($res)) { $newcode = $res['code']; }
@@ -1673,7 +1711,7 @@ for($i=0,$l=count($footer);$i<$l;$i++) {
1673
 
1674
  # get css from hurl, if available and valid
1675
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1676
- $newcode = false; $newcode = get_transient($tkey);
1677
  if ( $newcode === false) {
1678
  $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
1679
  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.3.2
9
  License: GPL2
10
 
11
  ------------------------------------------------------------------------
102
  $blacklist = array_map('trim', explode("\n", get_option('fastvelocity_min_blacklist', '')));
103
  $ignorelist = array_map('trim', explode("\n", get_option('fastvelocity_min_ignorelist', '')));
104
  $merge_allowed_urls = array_map('trim', explode("\n", get_option('fastvelocity_min_merge_allowed_urls', '')));
105
+ $fvm_enable_purgemenu = get_option('fastvelocity_min_enable_purgemenu');
106
  $default_protocol = get_option('fastvelocity_min_default_protocol', 'dynamic');
107
  $disable_js_merge = get_option('fastvelocity_min_disable_js_merge');
108
  $disable_css_merge = get_option('fastvelocity_min_disable_css_merge');
133
  $critical_path_css = get_option('fastvelocity_min_critical_path_css');
134
  $fvm_cdn_url = get_option('fastvelocity_min_fvm_cdn_url');
135
 
136
+
137
  # default options
138
  $used_css_files = array();
139
 
142
  if(!is_array($blacklist) || strlen(implode($blacklist)) == 0) { update_option('fastvelocity_min_blacklist', implode("\n", $exc)); }
143
 
144
  # default ignore list
145
+ $exc = array('/Avada/assets/js/main.min.js', '/woocommerce-product-search/js/product-search.js', '/includes/builder/scripts/frontend-builder-scripts.js', '/assets/js/jquery.themepunch.tools.min.js', '/js/TweenMax.min.js', '/jupiter/assets/js/min/full-scripts');
146
  if(!is_array($ignorelist) || strlen(implode($ignorelist)) == 0) { update_option('fastvelocity_min_ignorelist', implode("\n", $exc)); }
147
 
148
 
223
  }
224
 
225
 
226
+ # add admin toolbar
227
+ if($fvm_enable_purgemenu == true) {
228
+ add_action( 'admin_bar_menu', 'fastvelocity_admintoolbar', 100 );
229
+ }
230
+
231
+ # admin toolbar processing
232
+ function fastvelocity_admintoolbar() {
233
+ if(current_user_can('manage_options')) {
234
+ global $wp_admin_bar;
235
+
236
+ # Create or add new items into the Admin Toolbar.
237
+ $wp_admin_bar->add_node(array(
238
+ 'id' => 'fvm',
239
+ 'title' => '<span class="ab-icon"></span><span class="ab-label">' . __("FVM Purge",'fvm') . '</span>',
240
+ 'href' => admin_url( '/options-general.php?page=fastvelocity-min&fvm_flush=1' )
241
+ ));
242
+
243
+ }
244
+ }
245
+
246
+
247
  # function to list all cache files
248
  function fastvelocity_min_files_callback() {
249
  global $cachedir;
294
  # register plugin settings
295
  function fastvelocity_min_register_settings() {
296
  register_setting('fvm-group', 'fastvelocity_min_ignore');
297
+ register_setting('fvm-group', 'fastvelocity_min_enable_purgemenu');
298
  register_setting('fvm-group', 'fastvelocity_min_default_protocol');
299
  register_setting('fvm-group', 'fastvelocity_min_disable_js_merge');
300
  register_setting('fvm-group', 'fastvelocity_min_disable_css_merge');
338
 
339
  # add settings link on plugin page
340
  function fastvelocity_min_settings_link($links) {
341
+ if (is_plugin_active(plugin_basename( __FILE__ ))) {
342
+ $settings_link = '<a href="options-general.php?page=fastvelocity-min&tab=settings">Settings</a>';
343
+ array_unshift($links, $settings_link);
344
+ }
345
  return $links;
346
  }
347
  add_filter("plugin_action_links_".plugin_basename(__FILE__), 'fastvelocity_min_settings_link' );
365
  <?php
366
 
367
  # purge all caches
368
+ if(isset($_GET['page']) && $_GET['page'] == 'fastvelocity-min') {
369
+ if((isset($_POST['purgeall']) && $_POST['purgeall'] == 1) || isset($_GET['fvm_flush']) && $_GET['fvm_flush'] == 1) {
370
+ fvm_purge_all(); # purge all
371
+ echo __('<div class="notice notice-success is-dismissible"><p>All caches from <strong>FVM</strong> have been purged!</p></div>');
372
+ echo fastvelocity_purge_others(); # purge third party caches
373
+ }
374
  }
375
+
376
  ?>
377
 
378
  <h2 class="nav-tab-wrapper wp-clearfix">
439
  <table class="form-table fvm-settings">
440
  <tbody>
441
 
442
+ <tr>
443
+ <th scope="row">Admin Toolbar</th>
444
+ <td>
445
+ <p class="fvm-bold-green fvm-rowintro">Enable the "FVM purge" button on the admin bar.</p>
446
+ <fieldset>
447
+ <label for="fastvelocity_min_enable_purgemenu">
448
+ <input name="fastvelocity_min_enable_purgemenu" type="checkbox" id="fastvelocity_min_enable_purgemenu" value="1" <?php echo checked(1 == get_option('fastvelocity_min_enable_purgemenu'), true, false); ?>>
449
+ Admin Bar Purge <span class="note-info">[ If selected, a new option to purge FVM cache from the admin bar will show up. ]</span></label>
450
+ </fieldset></td>
451
+ </tr>
452
+
453
  <tr>
454
  <th scope="row">Troubleshooting</th>
455
  <td>
834
 
835
  <div style="height: 20px;"></div>
836
  <h2 class="title">Cache Location</h2>
837
+ <p class="fvm-bold-green">If your server blocks JavaScript on the uploads directory, you can change "wp-content/uploads" with "wp-content/cache" or other allowed public directory.</p>
838
  <table class="form-table fvm-settings">
839
  <tbody>
840
  <tr>
851
  <td><fieldset>
852
  <label for="fastvelocity_min_change_cache_base_url">
853
  <p><input type="text" name="fastvelocity_min_change_cache_base_url" id="fastvelocity_min_change_cache_base_url" value="<?php echo get_option('fastvelocity_min_change_cache_base_url', ''); ?>" size="80" /></p>
854
+ <p class="description">[ Default cache base url is: <?php echo rtrim(fvm_get_protocol(wp_upload_dir()['baseurl']), '/'); ?> ]</p>
855
  </label>
856
  </fieldset></td>
857
  </tr>
984
 
985
  # get css from hurl, if available and valid
986
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
987
+ $newcode = false; $newcode = fvm_get_transient($tkey);
988
  if ( $newcode === false) {
989
  $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
990
  if(is_array($res)) {
1117
 
1118
  # get css from hurl, if available and valid
1119
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1120
+ $newcode = false; $newcode = fvm_get_transient($tkey);
1121
  if ( $newcode === false) {
1122
  $res = fvm_download_and_cache($hurl, $tkey, null, $disable_js_minification, 'js', $handle);
1123
  if(is_array($res)) {
1322
 
1323
  # google fonts download and inlining, ignore logs
1324
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1325
+ $newcode = false; $newcode = fvm_get_transient($tkey);
1326
  if ( $newcode === false) {
1327
  $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
1328
  if(is_array($res)) { $newcode = $res['code']; }
1450
 
1451
  # get css from hurl, if available and valid
1452
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1453
+ $newcode = false; $newcode = fvm_get_transient($tkey);
1454
  if ( $newcode === false) {
1455
  $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
1456
  if(is_array($res)) {
1586
 
1587
  # google fonts download and inlining, ignore logs
1588
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $concat_google_fonts);
1589
+ $newcode = false; $newcode = fvm_get_transient($tkey);
1590
  if ( $newcode === false) {
1591
  $res = fvm_download_and_cache($concat_google_fonts, $tkey, null, $disable_css_minification, 'css');
1592
  if(is_array($res)) { $newcode = $res['code']; }
1711
 
1712
  # get css from hurl, if available and valid
1713
  $tkey = 'fvm-cache-'.$ctime.hash('adler32', $hurl);
1714
+ $newcode = false; $newcode = fvm_get_transient($tkey);
1715
  if ( $newcode === false) {
1716
  $res = fvm_download_and_cache($hurl, $tkey, null, $disable_css_minification, 'css', $handle);
1717
  if(is_array($res)) {
inc/functions-admin.php DELETED
@@ -1,75 +0,0 @@
1
- <?php
2
-
3
- /*
4
- in development...
5
- */
6
-
7
- # add admin toolbar
8
- add_action( 'admin_bar_menu', 'fastvelocity_add_toolbar', 100 );
9
-
10
-
11
- # admin toolbar processing
12
- function fastvelocity_add_toolbar() {
13
- if(current_user_can('manage_options')) {
14
- global $wp_admin_bar;
15
-
16
- # get cache size
17
- $stats = fastvelocity_get_cachestats();
18
- $count = $stats['count'];
19
- $size = $stats['size'];
20
-
21
- # Create or add new items into the Admin Toolbar.
22
- $wp_admin_bar->add_node( array(
23
- 'id' => 'fvm',
24
- 'title' => '<span class="ab-icon"></span><span class="ab-label">' . __("Fast Velocity",'fvm') . '</span>',
25
- 'href' => admin_url( 'options-general.php?page=fastvelocity-min' ),
26
- 'meta' => array( 'class' => 'bullet-green')
27
- ));
28
-
29
- # Cache Info node
30
- $wp_admin_bar->add_node( array(
31
- 'id' => 'fvm-cache-info',
32
- 'title' => '<p class="bold">' . __( "Cache Info", 'fvm' ) . '</p>' .
33
- '<table>' .
34
- '<tr><td>' . __( "Size", 'fvm' ) . ':</td><td class="size green">' . $size . '</td></tr>' .
35
- '<tr><td>' . __( "Files", 'fvm' ) . ':</td><td class="files white">' . $count . '</td></tr>' .
36
- '</table>',
37
- 'parent'=> 'fvm'
38
- ));
39
-
40
- # Delete Cache node
41
- $wp_admin_bar->add_node( array(
42
- 'id' => 'fvm-delete-cache',
43
- 'title' => __("Purge Cache",'fvm'),
44
- 'parent'=> 'fvm'
45
- ));
46
-
47
- }
48
- }
49
-
50
-
51
- /*
52
- # get cache size and count
53
- function fastvelocity_get_cachestats() {
54
-
55
- # info
56
- $cachepath = fvm_cachepath();
57
- $tmpdir = $cachepath['tmpdir'];
58
- $cachedir = $cachepath['cachedir'];
59
- $search = array($tmpdir, $cachedir);
60
- $size = 0;
61
- $count = 0;
62
-
63
- foreach ($search as $dir) {
64
- if(is_dir(rtrim($dir, '/'))) {
65
- if ($handle = opendir($dir.'/')) {
66
- while (false !== ($file = readdir($handle))) { $f = $dir.'/'.$file; $size = $size + filesize($f); $count++; }
67
- closedir($handle);
68
- }
69
- }
70
- }
71
-
72
- return array('size'=>fastvelocity_format_filesize($size), 'count'=>$count);
73
- }
74
- *(
75
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/functions.php CHANGED
@@ -190,7 +190,7 @@ function fvm_server_is_windows() {
190
  function fastvelocity_min_get_js($url, $js, $disable_js_minification) {
191
 
192
  # exclude minification on already minified files + jquery (because minification might break those)
193
- $excl = array('jquery.js', '.min.js', '-min.js', '/uploads/fusion-scripts/');
194
  foreach($excl as $e) { if (stripos(basename($url), $e) !== false) { $disable_js_minification = true; break; } }
195
 
196
  # remove BOM
@@ -271,14 +271,18 @@ return $html;
271
 
272
 
273
  # remove all cache files
274
- function fastvelocity_rrmdir($dir) {
275
- if(is_dir(rtrim($dir, '/'))) {
276
- if ($handle = opendir($dir.'/')) {
277
- while (false !== ($file = readdir($handle))) {
278
- @unlink($dir.'/'.$file);
279
- }
280
- closedir($handle); }
281
- }
 
 
 
 
282
  }
283
 
284
 
@@ -294,10 +298,13 @@ function fastvelocity_format_filesize($bytes, $decimals = 2) {
294
 
295
  # get cache size and count
296
  function fastvelocity_get_cachestats() {
297
- clearstatcache();
298
- $dir = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(fvm_cachepath()['cachebase'], FilesystemIterator::SKIP_DOTS));
299
- $size = 0; foreach ( $dir as $file ) { $size += $file->getSize(); }
300
- return fastvelocity_format_filesize($size);
 
 
 
301
  }
302
 
303
 
@@ -376,7 +383,6 @@ if (stripos($hurl, $wp_domain) !== false) {
376
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
377
  else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
378
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
379
- fvm_update_transient_keys($tkey); # keep track
380
  $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
381
  return array('log'=>$log, 'code'=>$code);
382
  }
@@ -389,7 +395,6 @@ if (stripos($hurl, $wp_domain) !== false) {
389
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
390
  else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
391
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
392
- fvm_update_transient_keys($tkey); # keep track
393
  $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
394
  return array('log'=>$log, 'code'=>$code);
395
  }
@@ -404,7 +409,6 @@ if($code !== false) {
404
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
405
  else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
406
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
407
- fvm_update_transient_keys($tkey); # keep track
408
  $log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
409
  return array('log'=>$log, 'code'=>$code);
410
  }
@@ -418,7 +422,6 @@ if(stripos($hurl, $wp_domain) !== false && home_url() != site_url()) {
418
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
419
  else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
420
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
421
- fvm_update_transient_keys($tkey); # keep track
422
  $log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
423
  return array('log'=>$log, 'code'=>$code);
424
  }
@@ -434,7 +437,6 @@ if (stripos($hurl, $wp_domain) !== false) {
434
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
435
  else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
436
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
437
- fvm_update_transient_keys($tkey); # keep track
438
  $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
439
  return array('log'=>$log, 'code'=>$code);
440
  }
@@ -447,7 +449,6 @@ if (stripos($hurl, $wp_domain) !== false) {
447
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
448
  else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
449
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
450
- fvm_update_transient_keys($tkey); # keep track
451
  $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
452
  return array('log'=>$log, 'code'=>$code);
453
  }
@@ -660,39 +661,88 @@ function fvm_get_protocol($url) {
660
  return $url;
661
  }
662
 
663
- # keep track of transients, whenever we save a transient.
664
- function fvm_update_transient_keys($new_transient_key) {
665
- $transient_keys = get_option('fvm_transient_keys'); # get
666
- $transient_keys[]= $new_transient_key; # append
667
- update_option( 'fvm_transient_keys', $transient_keys); # save
668
- }
669
 
670
  # keep track of transients, dump our plugin transients as needed
671
  function fvm_transients_purge() {
672
- update_option('fvm-last-cache-update', time()); # last cache update to now
673
- $transient_keys = get_option( 'fvm_transient_keys' ); # get
674
- update_option( 'fvm_transient_keys', array()); # reset
675
- foreach( $transient_keys as $t ) { delete_transient( $t ); } # delete
676
- }
677
-
 
 
 
 
 
 
 
 
 
678
 
679
  # purge all caches
680
  function fvm_purge_all() {
681
 
682
- # get cache directories and urls
683
- $cachepath = fvm_cachepath();
684
- $tmpdir = $cachepath['tmpdir'];
685
- $cachedir = $cachepath['cachedir'];
686
- $cachedirurl = $cachepath['cachedirurl'];
 
 
 
 
 
 
 
 
 
687
 
688
- # delete minification files and transients
689
- if(!is_dir($cachedir)) { return false; }
690
- fastvelocity_rrmdir($cachedir);
691
- fvm_transients_purge();
692
 
693
- return true;
 
 
 
 
 
 
 
 
 
 
694
  }
695
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
696
 
697
 
698
  # exclude processing from some pages / posts / contents
@@ -765,12 +815,12 @@ function fastvelocity_ie_blacklist($url) {
765
  function fastvelocity_download($url, $tkey, $ttl) {
766
 
767
  # rate limit requests, prevent slowdowns
768
- $rtlim = false; $rtlim = get_transient($tkey.'_access');
769
  if ( $rtlim !== false) { return false; }
770
 
771
  # info (needed for google fonts woff files + hinted fonts)
772
  $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';
773
- $data = false; $data = get_transient($tkey);
774
  if ( $data === false) {
775
 
776
  # get updated list from our api and cache it for 24 hours
@@ -779,8 +829,7 @@ function fastvelocity_download($url, $tkey, $ttl) {
779
  if($res_code == '200') {
780
  $data = wp_remote_retrieve_body($response);
781
  if(strlen($data) > 1 && $ttl > 0) {
782
- set_transient($tkey, $data, $ttl);
783
- fvm_update_transient_keys($tkey); # keep track
784
  return $data;
785
  }
786
  }
@@ -789,14 +838,13 @@ function fastvelocity_download($url, $tkey, $ttl) {
789
  if(function_exists('curl_version')) {
790
  $curl = fvm_file_get_contents_curl($url, $uagent);
791
  if(!empty($curl) && strlen($curl) > 1 && $ttl > 0) {
792
- set_transient($tkey, $data, $ttl);
793
- fvm_update_transient_keys($tkey); # keep track
794
  return $data;
795
  }
796
  }
797
 
798
  # error
799
- set_transient($tkey.'_access', "Failed to fetch: $url on ".current_time('timestamp'), $ttl);
800
  return false;
801
  }
802
 
@@ -894,3 +942,4 @@ if (method_exists('WpeCommon', 'purge_varnish_cache')) { WpeCommon::purge_varnis
894
  }
895
 
896
 
 
190
  function fastvelocity_min_get_js($url, $js, $disable_js_minification) {
191
 
192
  # exclude minification on already minified files + jquery (because minification might break those)
193
+ $excl = array('jquery.js', '.min.js', '-min.js', '/uploads/fusion-scripts/', '/min/');
194
  foreach($excl as $e) { if (stripos(basename($url), $e) !== false) { $disable_js_minification = true; break; } }
195
 
196
  # remove BOM
271
 
272
 
273
  # remove all cache files
274
+ function fastvelocity_rrmdir($path) {
275
+ clearstatcache();
276
+ if(is_dir($path)) {
277
+ $i = new DirectoryIterator($path);
278
+ foreach($i as $f){
279
+ if($f->isFile()){ unlink($f->getRealPath());
280
+ } else if(!$f->isDot() && $f->isDir()){
281
+ fastvelocity_rrmdir($f->getRealPath());
282
+ rmdir($f->getRealPath());
283
+ }
284
+ }
285
+ }
286
  }
287
 
288
 
298
 
299
  # get cache size and count
300
  function fastvelocity_get_cachestats() {
301
+ clearstatcache();
302
+ $dir = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(fvm_cachepath()['cachebase'], FilesystemIterator::SKIP_DOTS));
303
+ $size = 0;
304
+ foreach ($dir as $file) {
305
+ $size += $file->getSize();
306
+ }
307
+ return fastvelocity_format_filesize($size);
308
  }
309
 
310
 
383
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
384
  else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
385
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
 
386
  $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
387
  return array('log'=>$log, 'code'=>$code);
388
  }
395
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
396
  else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
397
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
 
398
  $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
399
  return array('log'=>$log, 'code'=>$code);
400
  }
409
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
410
  else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
411
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
 
412
  $log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
413
  return array('log'=>$log, 'code'=>$code);
414
  }
422
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, $code, $disable_minification); }
423
  else { $code = fastvelocity_min_get_css($hurl, $code.$inline, $disable_minification); }
424
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
 
425
  $log = "$printurl --- Debug: $printhandle Fetched url at $hurl \n";
426
  return array('log'=>$log, 'code'=>$code);
427
  }
437
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
438
  else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
439
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
 
440
  $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
441
  return array('log'=>$log, 'code'=>$code);
442
  }
449
  if($type == 'js') { $code = fastvelocity_min_get_js($hurl, file_get_contents($f), $disable_minification); }
450
  else { $code = fastvelocity_min_get_css($hurl, file_get_contents($f).$inline, $disable_minification); }
451
  set_transient($tkey, $code, 7 * DAY_IN_SECONDS );
 
452
  $log = "$printurl --- Debug: $printhandle File was opened from $f ---\n";
453
  return array('log'=>$log, 'code'=>$code);
454
  }
661
  return $url;
662
  }
663
 
 
 
 
 
 
 
664
 
665
  # keep track of transients, dump our plugin transients as needed
666
  function fvm_transients_purge() {
667
+
668
+ # last cache update to now
669
+ update_option('fvm-last-cache-update', time());
670
+
671
+ # delete legacy transients
672
+ $tk = get_option( 'fvm_transient_keys' );
673
+ if($tk !== false) {
674
+ delete_option('fvm_transient_keys');
675
+ if(is_array($tk)) {
676
+ foreach( $tk as $t ) {
677
+ delete_transient($t);
678
+ }
679
+ }
680
+ }
681
+ }
682
 
683
  # purge all caches
684
  function fvm_purge_all() {
685
 
686
+ # get cache directories and urls
687
+ $cachepath = fvm_cachepath();
688
+ $cachebase = $cachepath['cachebase'];
689
+
690
+ # delete minification files and transients
691
+ if(!is_dir($cachebase)) {
692
+ return false;
693
+ }
694
+
695
+ # remove cache files, set last update and clean legacy transients
696
+ fastvelocity_rrmdir($cachebase);
697
+ fvm_transients_purge();
698
+ return true;
699
+ }
700
 
 
 
 
 
701
 
702
+ # get transients on the disk
703
+ function fvm_get_transient($key) {
704
+ $cachepath = fvm_cachepath();
705
+ $tmpdir = $cachepath['tmpdir'];
706
+ $f = $tmpdir.'/'.$key.'.transient';
707
+ clearstatcache();
708
+ if(file_exists($tmpdir.'/'.$key)) {
709
+ return file_get_contents($f);
710
+ } else {
711
+ return false;
712
+ }
713
  }
714
 
715
+ # set transients on the disk
716
+ function fvm_set_transient($key, $code, $ttl) {
717
+ if(is_null($code) || empty($code)) { return false; }
718
+ $cachepath = fvm_cachepath();
719
+ $tmpdir = $cachepath['tmpdir'];
720
+ $f = $tmpdir.'/'.$key.'.transient';
721
+ $e = $tmpdir.'/'.$key.'.exp';
722
+ clearstatcache();
723
+
724
+ # update or not?
725
+ if(!file_exists($f)) {
726
+ $write = 1;
727
+ } else {
728
+ if(file_exists($e)) {
729
+ $t = file_get_contents($e);
730
+ if(is_numeric($t) && $t < time()) {
731
+ $write = 1;
732
+ }
733
+ }
734
+ }
735
+
736
+ # proceed
737
+ if(isset($write) && $write == 1) {
738
+ file_put_contents($f, $code);
739
+ file_put_contents($e, time()+$ttl);
740
+ return true;
741
+ }
742
+
743
+ # fallback
744
+ return false;
745
+ }
746
 
747
 
748
  # exclude processing from some pages / posts / contents
815
  function fastvelocity_download($url, $tkey, $ttl) {
816
 
817
  # rate limit requests, prevent slowdowns
818
+ $rtlim = false; $rtlim = fvm_get_transient($tkey.'_access');
819
  if ( $rtlim !== false) { return false; }
820
 
821
  # info (needed for google fonts woff files + hinted fonts)
822
  $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';
823
+ $data = false; $data = fvm_get_transient($tkey);
824
  if ( $data === false) {
825
 
826
  # get updated list from our api and cache it for 24 hours
829
  if($res_code == '200') {
830
  $data = wp_remote_retrieve_body($response);
831
  if(strlen($data) > 1 && $ttl > 0) {
832
+ fvm_set_transient($tkey, $data, $ttl);
 
833
  return $data;
834
  }
835
  }
838
  if(function_exists('curl_version')) {
839
  $curl = fvm_file_get_contents_curl($url, $uagent);
840
  if(!empty($curl) && strlen($curl) > 1 && $ttl > 0) {
841
+ fvm_set_transient($tkey, $data, $ttl);
 
842
  return $data;
843
  }
844
  }
845
 
846
  # error
847
+ fvm_set_transient($tkey.'_access', "Failed to fetch: $url on ".current_time('timestamp'), $ttl);
848
  return false;
849
  }
850
 
942
  }
943
 
944
 
945
+
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('&#160;', '', $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&#160;(code&#160;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 &#38; 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&#160;(Code&#160;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&#160;:';
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&#160;: <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&#160;:';
186
+ $lang['fr'][9] = 'Code CSS&#160;:';
187
+ $lang['fr'][10] = 'CSS en provenance d’une URL&#160;:<br />';
188
+ $lang['fr'][11] = 'Mise en page du code&#160;:';
189
+ $lang['fr'][12] = 'Compression (mise en page du code)&#160;:';
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&#160;:';
204
+ $lang['fr'][27] = 'Minuscule';
205
+ $lang['fr'][28] = 'CSS non valide ou URL incorrecte&#160;!';
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 &#38; 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&#160;: ceci peut changer le comportement de votre code CSS&#160;!';
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] = '由於比較少換行字元, 會有更大的壓縮比率(複製&#38;貼上沒有用)';
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
+ ?>
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: Alignak
3
  Tags: PHP Minify, YUI Compressor, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance
4
  Requires at least: 4.5
5
- Stable tag: 2.3.1
6
  Tested up to: 4.9.6
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -271,6 +271,11 @@ Note: Kindly re-save all options and purge all caches (the plugin cache as well
271
 
272
  == Changelog ==
273
 
 
 
 
 
 
274
  = 2.3.1 [2018.06.01] =
275
  * bug fixes and performance tweaks for the "fix page editors" option
276
 
2
  Contributors: Alignak
3
  Tags: PHP Minify, YUI Compressor, GTmetrix, Pingdom, Pagespeed, CSS Merging, JS Merging, CSS Minification, JS Minification, Speed Optimization, HTML Minification, Performance
4
  Requires at least: 4.5
5
+ Stable tag: 2.3.2
6
  Tested up to: 4.9.6
7
  License: GPLv3 or later
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
271
 
272
  == Changelog ==
273
 
274
+ = 2.3.2 [2018.06.03] =
275
+ * added some compatibility fixes when merging and minifying JS files
276
+ * added an option to enable an "FVM Purge" button on the admin bar
277
+ * moved all large transients (cached css or js code) to temporary disk files to reduce the database load
278
+
279
  = 2.3.1 [2018.06.01] =
280
  * bug fixes and performance tweaks for the "fix page editors" option
281