a3 Lazy Load - Version 1.4.1

Version Description

Major Maintenance Upgrade. 5 Code Tweaks plus 2 bug fixes for full compatibility with WordPress v 4.3.0

Download this release

Release Info

Developer a3rev
Plugin Icon 128x128 a3 Lazy Load
Version 1.4.1
Comparing to
See all releases

Code changes from version 1.4.0 to 1.4.1

a3-lazy-load.php CHANGED
@@ -2,11 +2,11 @@
2
  /*
3
  Plugin Name: a3 Lazy Load
4
  Description: Speed up your site and enhance frontend user's visual experience in PC's, Tablets and mobile with a3 Lazy Load.
5
- Version: 1.4.0
6
  Author: a3 Revolution
7
  Author URI: http://www.a3rev.com/
8
  Requires at least: 3.8
9
- Tested up to: 4.2.2
10
  License: GPLv2 or later
11
  Copyright © 2011 a3 Revolution Software Development team
12
  a3 Revolution Software Development team
2
  /*
3
  Plugin Name: a3 Lazy Load
4
  Description: Speed up your site and enhance frontend user's visual experience in PC's, Tablets and mobile with a3 Lazy Load.
5
+ Version: 1.4.1
6
  Author: a3 Revolution
7
  Author URI: http://www.a3rev.com/
8
  Requires at least: 3.8
9
+ Tested up to: 4.3
10
  License: GPLv2 or later
11
  Copyright © 2011 a3 Revolution Software Development team
12
  a3 Revolution Software Development team
admin/a3-lazy-load-admin.php CHANGED
@@ -2,7 +2,7 @@
2
  update_option('a3rev_lazy_load_plugin', 'a3_lazy_load');
3
 
4
  function a3_lazy_load_activated(){
5
- update_option('a3_lazy_load_version', '1.4.0');
6
 
7
  // Set Settings Default from Admin Init
8
  global $a3_lazy_load_admin_init;
@@ -59,6 +59,6 @@ function a3_lazy_load_upgrade_plugin() {
59
  include( A3_LAZY_LOAD_DIR. '/includes/updates/a3-lazy-load-update-1.1.0.php' );
60
  }
61
 
62
- update_option('a3_lazy_load_version', '1.4.0');
63
  }
64
  ?>
2
  update_option('a3rev_lazy_load_plugin', 'a3_lazy_load');
3
 
4
  function a3_lazy_load_activated(){
5
+ update_option('a3_lazy_load_version', '1.4.`');
6
 
7
  // Set Settings Default from Admin Init
8
  global $a3_lazy_load_admin_init;
59
  include( A3_LAZY_LOAD_DIR. '/includes/updates/a3-lazy-load-update-1.1.0.php' );
60
  }
61
 
62
+ update_option('a3_lazy_load_version', '1.4.1');
63
  }
64
  ?>
admin/admin-interface.php CHANGED
@@ -34,23 +34,23 @@ TABLE OF CONTENTS
34
 
35
  class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
36
  {
37
-
38
  /*-----------------------------------------------------------------------------------*/
39
  /* Admin Interface Constructor */
40
  /*-----------------------------------------------------------------------------------*/
41
  public function __construct() {
42
-
43
  $this->admin_includes();
44
-
45
  add_action( 'init', array( $this, 'init_scripts' ) );
46
  add_action( 'init', array( $this, 'init_styles' ) );
47
 
48
  // AJAX hide yellow message dontshow
49
  add_action( 'wp_ajax_'.$this->plugin_name.'_a3_admin_ui_event', array( $this, 'a3_admin_ui_event' ) );
50
  add_action( 'wp_ajax_nopriv_'.$this->plugin_name.'_a3_admin_ui_event', array( $this, 'a3_admin_ui_event' ) );
51
-
52
  }
53
-
54
  /*-----------------------------------------------------------------------------------*/
55
  /* Init scripts */
56
  /*-----------------------------------------------------------------------------------*/
@@ -683,7 +683,12 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
683
  }
684
  }
685
  }
686
-
 
 
 
 
 
687
  break;
688
 
689
  }
@@ -692,18 +697,19 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
692
  if ( strstr( $value['id'], '[' ) ) {
693
  // Set keys and value
694
  $key = key( $option_array[ $id_attribute ] );
695
-
696
- $update_options[ $id_attribute ][ $key ] = $option_value;
697
 
698
  if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
699
  $update_separate_options[ $id_attribute ][ $key ] = $option_value;
 
 
700
  }
701
 
702
  } else {
703
- $update_options[ $id_attribute ] = $option_value;
704
 
705
  if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
706
  $update_separate_options[ $id_attribute ] = $option_value;
 
 
707
  }
708
  }
709
  }
@@ -825,6 +831,7 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
825
  }
826
 
827
  // Remove [, ] characters from id argument
 
828
  if ( strstr( $text_field['id'], '[' ) ) {
829
  parse_str( esc_attr( $text_field['id'] ), $option_array );
830
 
@@ -833,17 +840,48 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
833
  $first_key = current( $option_keys );
834
 
835
  $id_attribute = $first_key;
 
 
836
  } else {
837
  $id_attribute = esc_attr( $text_field['id'] );
838
  }
839
 
840
  if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
841
  if ( $reset && $text_field['free_version'] && !$free_version ) {
842
- update_option( $id_attribute, $text_field['default'] );
 
 
 
 
 
 
 
 
 
843
  } elseif ( $reset && !$text_field['free_version'] ) {
844
- update_option( $id_attribute, $text_field['default'] );
 
 
 
 
 
 
 
 
 
845
  } else {
846
- add_option( $id_attribute, $text_field['default'] );
 
 
 
 
 
 
 
 
 
 
 
847
  }
848
  }
849
  }
@@ -852,6 +890,7 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
852
 
853
  default :
854
  // Remove [, ] characters from id argument
 
855
  if ( strstr( $value['id'], '[' ) ) {
856
  parse_str( esc_attr( $value['id'] ), $option_array );
857
 
@@ -860,17 +899,48 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
860
  $first_key = current( $option_keys );
861
 
862
  $id_attribute = $first_key;
 
 
863
  } else {
864
  $id_attribute = esc_attr( $value['id'] );
865
  }
866
 
867
  if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
868
  if ( $reset && $value['free_version'] && !$free_version ) {
869
- update_option( $id_attribute, $value['default'] );
 
 
 
 
 
 
 
 
 
870
  } elseif ( $reset && !$value['free_version'] ) {
871
- update_option( $id_attribute, $value['default'] );
 
 
 
 
 
 
 
 
 
872
  } else {
873
- add_option( $id_attribute, $value['default'] );
 
 
 
 
 
 
 
 
 
 
 
874
  }
875
  }
876
 
@@ -1203,7 +1273,7 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
1203
  }
1204
 
1205
  // Remove [, ] characters from id argument
1206
- $key = false;
1207
  if ( strstr( $value['id'], '[' ) ) {
1208
  parse_str( esc_attr( $value['id'] ), $option_array );
1209
 
@@ -1213,7 +1283,7 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
1213
 
1214
  $id_attribute = $first_key;
1215
 
1216
- $key = key( $option_array[ $id_attribute ] );
1217
  } else {
1218
  $id_attribute = esc_attr( $value['id'] );
1219
  }
@@ -1224,8 +1294,8 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
1224
  }
1225
  // Get option value when it's an element from option array
1226
  else {
1227
- if ( $key != false ) {
1228
- $option_value = ( isset( $option_values[ $id_attribute ][ $key ] ) ) ? $option_values[ $id_attribute ][ $key ] : $value['default'];
1229
  } else {
1230
  $option_value = ( isset( $option_values[ $id_attribute ] ) ) ? $option_values[ $id_attribute ] : $value['default'];
1231
  }
@@ -1498,7 +1568,8 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
1498
 
1499
  if ( trim( $value['default'] ) == '' ) $value['default'] = '#515151';
1500
  $default_color = ' data-default-color="' . esc_attr( $value['default'] ) . '"';
1501
-
 
1502
  ?><tr valign="top">
1503
  <th scope="row" class="titledesc">
1504
  <?php echo $tip; ?>
@@ -1790,15 +1861,9 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
1790
  // Image size settings
1791
  case 'image_size' :
1792
 
1793
- if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
1794
- $width = $this->settings_get_option( $value['id'] . '[width]', $value['default']['width'] );
1795
- $height = $this->settings_get_option( $value['id'] . '[height]', $value['default']['height'] );
1796
- $crop = checked( 1, $this->settings_get_option( $value['id'] . '[crop]', $value['default']['crop'] ), false );
1797
- } else {
1798
- $width = $option_value['width'];
1799
- $height = $option_value['height'];
1800
- $crop = checked( 1, $option_value['crop'], false );
1801
- }
1802
 
1803
  ?><tr valign="top">
1804
  <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
@@ -1848,17 +1913,10 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
1848
 
1849
  $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
1850
 
1851
- if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
1852
- $size = $this->settings_get_option( $value['id'] . '[size]', $value['default']['size'] );
1853
- $face = $this->settings_get_option( $value['id'] . '[face]', $value['default']['face'] );
1854
- $style = $this->settings_get_option( $value['id'] . '[style]', $value['default']['style'] );
1855
- $color = $this->settings_get_option( $value['id'] . '[color]', $value['default']['color'] );
1856
- } else {
1857
- $size = $option_value['size'];
1858
- $face = $option_value['face'];
1859
- $style = $option_value['style'];
1860
- $color = $option_value['color'];
1861
- }
1862
 
1863
  ?><tr valign="top">
1864
  <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
@@ -1957,57 +2015,32 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
1957
  // For Border Styles
1958
  $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
1959
 
1960
- if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
1961
- $width = $this->settings_get_option( $value['id'] . '[width]', $value['default']['width'] );
1962
- $style = $this->settings_get_option( $value['id'] . '[style]', $value['default']['style'] );
1963
- $color = $this->settings_get_option( $value['id'] . '[color]', $value['default']['color'] );
1964
- } else {
1965
- $width = $option_value['width'];
1966
- $style = $option_value['style'];
1967
- $color = $option_value['color'];
1968
- }
1969
 
1970
  // For Border Corner
1971
  if ( ! isset( $value['min'] ) ) $value['min'] = 0;
1972
  if ( ! isset( $value['max'] ) ) $value['max'] = 100;
1973
  if ( ! isset( $value['increment'] ) ) $value['increment'] = 1;
1974
 
1975
- if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
1976
- $corner = $this->settings_get_option( $value['id'] . '[corner]', $value['default']['corner'] );
1977
-
1978
- if ( ! isset( $value['default']['rounded_value'] ) ) $value['default']['rounded_value'] = 3;
1979
- $rounded_value = $this->settings_get_option( $value['id'] . '[rounded_value]', $value['default']['rounded_value'] );
1980
-
1981
- if ( ! isset( $value['default']['top_left_corner'] ) ) $value['default']['top_left_corner'] = 3;
1982
- $top_left_corner = $this->settings_get_option( $value['id'] . '[top_left_corner]', $value['default']['top_left_corner'] );
1983
-
1984
- if ( ! isset( $value['default']['top_right_corner'] ) ) $value['default']['top_right_corner'] = 3;
1985
- $top_right_corner = $this->settings_get_option( $value['id'] . '[top_right_corner]', $value['default']['top_right_corner'] );
1986
-
1987
- if ( ! isset( $value['default']['bottom_left_corner'] ) ) $value['default']['bottom_left_corner'] = 3;
1988
- $bottom_left_corner = $this->settings_get_option( $value['id'] . '[bottom_left_corner]', $value['default']['bottom_left_corner'] );
1989
-
1990
- if ( ! isset( $value['default']['bottom_right_corner'] ) ) $value['default']['bottom_right_corner'] = 3;
1991
- $bottom_right_corner = $this->settings_get_option( $value['id'] . '[bottom_right_corner]', $value['default']['bottom_right_corner'] );
1992
- } else {
1993
- if ( ! isset( $option_value['corner'] ) ) $option_value['corner'] = '';
1994
- $corner = $option_value['corner'];
1995
-
1996
- if ( ! isset( $option_value['rounded_value'] ) ) $option_value['rounded_value'] = 3;
1997
- $rounded_value = $option_value['rounded_value'];
1998
-
1999
- if ( ! isset( $option_value['top_left_corner'] ) ) $option_value['top_left_corner'] = 3;
2000
- $top_left_corner = $option_value['top_left_corner'];
2001
-
2002
- if ( ! isset( $option_value['top_right_corner'] ) ) $option_value['top_right_corner'] = 3;
2003
- $top_right_corner = $option_value['top_right_corner'];
2004
-
2005
- if ( ! isset( $option_value['bottom_left_corner'] ) ) $option_value['bottom_left_corner'] = 3;
2006
- $bottom_left_corner = $option_value['bottom_left_corner'];
2007
-
2008
- if ( ! isset( $option_value['bottom_right_corner'] ) ) $option_value['bottom_right_corner'] = 3;
2009
- $bottom_right_corner = $option_value['bottom_right_corner'];
2010
- }
2011
 
2012
  if ( trim( $rounded_value ) == '' || trim( $rounded_value ) <= 0 ) $rounded_value = $value['min'];
2013
  $rounded_value = intval( $rounded_value );
@@ -2187,15 +2220,9 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
2187
 
2188
  $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
2189
 
2190
- if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
2191
- $width = $this->settings_get_option( $value['id'] . '[width]', $value['default']['width'] );
2192
- $style = $this->settings_get_option( $value['id'] . '[style]', $value['default']['style'] );
2193
- $color = $this->settings_get_option( $value['id'] . '[color]', $value['default']['color'] );
2194
- } else {
2195
- $width = $option_value['width'];
2196
- $style = $option_value['style'];
2197
- $color = $option_value['color'];
2198
- }
2199
 
2200
  ?><tr valign="top">
2201
  <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
@@ -2262,42 +2289,23 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
2262
  if ( ! isset( $value['max'] ) ) $value['max'] = 100;
2263
  if ( ! isset( $value['increment'] ) ) $value['increment'] = 1;
2264
 
2265
- if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
2266
- $corner = $this->settings_get_option( $value['id'] . '[corner]', $value['default']['corner'] );
2267
-
2268
- if ( ! isset( $value['default']['rounded_value'] ) ) $value['default']['rounded_value'] = 3;
2269
- $rounded_value = $this->settings_get_option( $value['id'] . '[rounded_value]', $value['default']['rounded_value'] );
2270
-
2271
- if ( ! isset( $value['default']['top_left_corner'] ) ) $value['default']['top_left_corner'] = 3;
2272
- $top_left_corner = $this->settings_get_option( $value['id'] . '[top_left_corner]', $value['default']['top_left_corner'] );
2273
-
2274
- if ( ! isset( $value['default']['top_right_corner'] ) ) $value['default']['top_right_corner'] = 3;
2275
- $top_right_corner = $this->settings_get_option( $value['id'] . '[top_right_corner]', $value['default']['top_right_corner'] );
2276
-
2277
- if ( ! isset( $value['default']['bottom_left_corner'] ) ) $value['default']['bottom_left_corner'] = 3;
2278
- $bottom_left_corner = $this->settings_get_option( $value['id'] . '[bottom_left_corner]', $value['default']['bottom_left_corner'] );
2279
-
2280
- if ( ! isset( $value['default']['bottom_right_corner'] ) ) $value['default']['bottom_right_corner'] = 3;
2281
- $bottom_right_corner = $this->settings_get_option( $value['id'] . '[bottom_right_corner]', $value['default']['bottom_right_corner'] );
2282
- } else {
2283
- if ( ! isset( $option_value['corner'] ) ) $option_value['corner'] = '';
2284
- $corner = $option_value['corner'];
2285
-
2286
- if ( ! isset( $option_value['rounded_value'] ) ) $option_value['rounded_value'] = 3;
2287
- $rounded_value = $option_value['rounded_value'];
2288
-
2289
- if ( ! isset( $option_value['top_left_corner'] ) ) $option_value['top_left_corner'] = 3;
2290
- $top_left_corner = $option_value['top_left_corner'];
2291
-
2292
- if ( ! isset( $option_value['top_right_corner'] ) ) $option_value['top_right_corner'] = 3;
2293
- $top_right_corner = $option_value['top_right_corner'];
2294
-
2295
- if ( ! isset( $option_value['bottom_left_corner'] ) ) $option_value['bottom_left_corner'] = 3;
2296
- $bottom_left_corner = $option_value['bottom_left_corner'];
2297
-
2298
- if ( ! isset( $option_value['bottom_right_corner'] ) ) $option_value['bottom_right_corner'] = 3;
2299
- $bottom_right_corner = $option_value['bottom_right_corner'];
2300
- }
2301
 
2302
  if ( trim( $rounded_value ) == '' || trim( $rounded_value ) <= 0 ) $rounded_value = $value['min'];
2303
  $rounded_value = intval( $rounded_value );
@@ -2431,25 +2439,15 @@ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
2431
 
2432
  $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
2433
 
2434
- if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
2435
- $enable = $this->settings_get_option( $value['id'] . '[enable]', $value['default']['enable'] );
2436
- $h_shadow = $this->settings_get_option( $value['id'] . '[h_shadow]', $value['default']['h_shadow'] );
2437
- $v_shadow = $this->settings_get_option( $value['id'] . '[v_shadow]', $value['default']['v_shadow'] );
2438
- $blur = $this->settings_get_option( $value['id'] . '[blur]', $value['default']['blur'] );
2439
- $spread = $this->settings_get_option( $value['id'] . '[spread]', $value['default']['spread'] );
2440
- $color = $this->settings_get_option( $value['id'] . '[color]', $value['default']['color'] );
2441
- $inset = $this->settings_get_option( $value['id'] . '[inset]', $value['default']['inset'] );
2442
- } else {
2443
- if ( ! isset( $option_value['enable'] ) ) $option_value['enable'] = 0;
2444
- $enable = $option_value['enable'];
2445
- if ( ! isset( $option_value['inset'] ) ) $option_value['inset'] = '';
2446
- $h_shadow = $option_value['h_shadow'];
2447
- $v_shadow = $option_value['v_shadow'];
2448
- $blur = $option_value['blur'];
2449
- $spread = $option_value['spread'];
2450
- $color = $option_value['color'];
2451
- $inset = $option_value['inset'];
2452
- }
2453
 
2454
  ?><tr valign="top">
2455
  <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
34
 
35
  class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
36
  {
37
+
38
  /*-----------------------------------------------------------------------------------*/
39
  /* Admin Interface Constructor */
40
  /*-----------------------------------------------------------------------------------*/
41
  public function __construct() {
42
+
43
  $this->admin_includes();
44
+
45
  add_action( 'init', array( $this, 'init_scripts' ) );
46
  add_action( 'init', array( $this, 'init_styles' ) );
47
 
48
  // AJAX hide yellow message dontshow
49
  add_action( 'wp_ajax_'.$this->plugin_name.'_a3_admin_ui_event', array( $this, 'a3_admin_ui_event' ) );
50
  add_action( 'wp_ajax_nopriv_'.$this->plugin_name.'_a3_admin_ui_event', array( $this, 'a3_admin_ui_event' ) );
51
+
52
  }
53
+
54
  /*-----------------------------------------------------------------------------------*/
55
  /* Init scripts */
56
  /*-----------------------------------------------------------------------------------*/
683
  }
684
  }
685
  }
686
+
687
+ // Just for Color type
688
+ if ( 'color' == $value['type'] && '' == trim( $option_value ) ) {
689
+ $option_value = 'transparent';
690
+ }
691
+
692
  break;
693
 
694
  }
697
  if ( strstr( $value['id'], '[' ) ) {
698
  // Set keys and value
699
  $key = key( $option_array[ $id_attribute ] );
 
 
700
 
701
  if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
702
  $update_separate_options[ $id_attribute ][ $key ] = $option_value;
703
+ } else {
704
+ $update_options[ $id_attribute ][ $key ] = $option_value;
705
  }
706
 
707
  } else {
 
708
 
709
  if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
710
  $update_separate_options[ $id_attribute ] = $option_value;
711
+ } else {
712
+ $update_options[ $id_attribute ] = $option_value;
713
  }
714
  }
715
  }
831
  }
832
 
833
  // Remove [, ] characters from id argument
834
+ $key = false;
835
  if ( strstr( $text_field['id'], '[' ) ) {
836
  parse_str( esc_attr( $text_field['id'] ), $option_array );
837
 
840
  $first_key = current( $option_keys );
841
 
842
  $id_attribute = $first_key;
843
+
844
+ $key = key( $option_array[ $id_attribute ] );
845
  } else {
846
  $id_attribute = esc_attr( $text_field['id'] );
847
  }
848
 
849
  if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
850
  if ( $reset && $text_field['free_version'] && !$free_version ) {
851
+ if ( $key != false ) {
852
+ $current_settings = get_option( $id_attribute, array() );
853
+ if ( ! is_array( $current_settings) ) {
854
+ $current_settings = array();
855
+ }
856
+ $current_settings[$key] = $text_field['default'];
857
+ update_option( $id_attribute, $current_settings );
858
+ } else {
859
+ update_option( $id_attribute, $text_field['default'] );
860
+ }
861
  } elseif ( $reset && !$text_field['free_version'] ) {
862
+ if ( $key != false ) {
863
+ $current_settings = get_option( $id_attribute, array() );
864
+ if ( ! is_array( $current_settings) ) {
865
+ $current_settings = array();
866
+ }
867
+ $current_settings[$key] = $text_field['default'];
868
+ update_option( $id_attribute, $current_settings );
869
+ } else {
870
+ update_option( $id_attribute, $text_field['default'] );
871
+ }
872
  } else {
873
+ if ( $key != false ) {
874
+ $current_settings = get_option( $id_attribute, array() );
875
+ if ( ! is_array( $current_settings) ) {
876
+ $current_settings = array();
877
+ }
878
+ if ( ! isset( $current_settings[$key] ) ) {
879
+ $current_settings[$key] = $text_field['default'];
880
+ update_option( $id_attribute, $current_settings );
881
+ }
882
+ } else {
883
+ add_option( $id_attribute, $text_field['default'] );
884
+ }
885
  }
886
  }
887
  }
890
 
891
  default :
892
  // Remove [, ] characters from id argument
893
+ $key = false;
894
  if ( strstr( $value['id'], '[' ) ) {
895
  parse_str( esc_attr( $value['id'] ), $option_array );
896
 
899
  $first_key = current( $option_keys );
900
 
901
  $id_attribute = $first_key;
902
+
903
+ $key = key( $option_array[ $id_attribute ] );
904
  } else {
905
  $id_attribute = esc_attr( $value['id'] );
906
  }
907
 
908
  if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
909
  if ( $reset && $value['free_version'] && !$free_version ) {
910
+ if ( $key != false ) {
911
+ $current_settings = get_option( $id_attribute, array() );
912
+ if ( ! is_array( $current_settings) ) {
913
+ $current_settings = array();
914
+ }
915
+ $current_settings[$key] = $value['default'];
916
+ update_option( $id_attribute, $current_settings );
917
+ } else {
918
+ update_option( $id_attribute, $value['default'] );
919
+ }
920
  } elseif ( $reset && !$value['free_version'] ) {
921
+ if ( $key != false ) {
922
+ $current_settings = get_option( $id_attribute, array() );
923
+ if ( ! is_array( $current_settings) ) {
924
+ $current_settings = array();
925
+ }
926
+ $current_settings[$key] = $value['default'];
927
+ update_option( $id_attribute, $current_settings );
928
+ } else {
929
+ update_option( $id_attribute, $value['default'] );
930
+ }
931
  } else {
932
+ if ( $key != false ) {
933
+ $current_settings = get_option( $id_attribute, array() );
934
+ if ( ! is_array( $current_settings) ) {
935
+ $current_settings = array();
936
+ }
937
+ if ( ! isset( $current_settings[$key] ) ) {
938
+ $current_settings[$key] = $value['default'];
939
+ update_option( $id_attribute, $current_settings );
940
+ }
941
+ } else {
942
+ add_option( $id_attribute, $value['default'] );
943
+ }
944
  }
945
  }
946
 
1273
  }
1274
 
1275
  // Remove [, ] characters from id argument
1276
+ $child_key = false;
1277
  if ( strstr( $value['id'], '[' ) ) {
1278
  parse_str( esc_attr( $value['id'] ), $option_array );
1279
 
1283
 
1284
  $id_attribute = $first_key;
1285
 
1286
+ $child_key = key( $option_array[ $id_attribute ] );
1287
  } else {
1288
  $id_attribute = esc_attr( $value['id'] );
1289
  }
1294
  }
1295
  // Get option value when it's an element from option array
1296
  else {
1297
+ if ( $child_key != false ) {
1298
+ $option_value = ( isset( $option_values[ $id_attribute ][ $child_key ] ) ) ? $option_values[ $id_attribute ][ $child_key ] : $value['default'];
1299
  } else {
1300
  $option_value = ( isset( $option_values[ $id_attribute ] ) ) ? $option_values[ $id_attribute ] : $value['default'];
1301
  }
1568
 
1569
  if ( trim( $value['default'] ) == '' ) $value['default'] = '#515151';
1570
  $default_color = ' data-default-color="' . esc_attr( $value['default'] ) . '"';
1571
+ if ( '' == trim( $option_value ) ) $option_value = 'transparent';
1572
+
1573
  ?><tr valign="top">
1574
  <th scope="row" class="titledesc">
1575
  <?php echo $tip; ?>
1861
  // Image size settings
1862
  case 'image_size' :
1863
 
1864
+ $width = $option_value['width'];
1865
+ $height = $option_value['height'];
1866
+ $crop = checked( 1, $option_value['crop'], false );
 
 
 
 
 
 
1867
 
1868
  ?><tr valign="top">
1869
  <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
1913
 
1914
  $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
1915
 
1916
+ $size = $option_value['size'];
1917
+ $face = $option_value['face'];
1918
+ $style = $option_value['style'];
1919
+ $color = $option_value['color'];
 
 
 
 
 
 
 
1920
 
1921
  ?><tr valign="top">
1922
  <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
2015
  // For Border Styles
2016
  $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
2017
 
2018
+ $width = $option_value['width'];
2019
+ $style = $option_value['style'];
2020
+ $color = $option_value['color'];
 
 
 
 
 
 
2021
 
2022
  // For Border Corner
2023
  if ( ! isset( $value['min'] ) ) $value['min'] = 0;
2024
  if ( ! isset( $value['max'] ) ) $value['max'] = 100;
2025
  if ( ! isset( $value['increment'] ) ) $value['increment'] = 1;
2026
 
2027
+ if ( ! isset( $option_value['corner'] ) ) $option_value['corner'] = '';
2028
+ $corner = $option_value['corner'];
2029
+
2030
+ if ( ! isset( $option_value['rounded_value'] ) ) $option_value['rounded_value'] = 3;
2031
+ $rounded_value = $option_value['rounded_value'];
2032
+
2033
+ if ( ! isset( $option_value['top_left_corner'] ) ) $option_value['top_left_corner'] = 3;
2034
+ $top_left_corner = $option_value['top_left_corner'];
2035
+
2036
+ if ( ! isset( $option_value['top_right_corner'] ) ) $option_value['top_right_corner'] = 3;
2037
+ $top_right_corner = $option_value['top_right_corner'];
2038
+
2039
+ if ( ! isset( $option_value['bottom_left_corner'] ) ) $option_value['bottom_left_corner'] = 3;
2040
+ $bottom_left_corner = $option_value['bottom_left_corner'];
2041
+
2042
+ if ( ! isset( $option_value['bottom_right_corner'] ) ) $option_value['bottom_right_corner'] = 3;
2043
+ $bottom_right_corner = $option_value['bottom_right_corner'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2044
 
2045
  if ( trim( $rounded_value ) == '' || trim( $rounded_value ) <= 0 ) $rounded_value = $value['min'];
2046
  $rounded_value = intval( $rounded_value );
2220
 
2221
  $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
2222
 
2223
+ $width = $option_value['width'];
2224
+ $style = $option_value['style'];
2225
+ $color = $option_value['color'];
 
 
 
 
 
 
2226
 
2227
  ?><tr valign="top">
2228
  <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
2289
  if ( ! isset( $value['max'] ) ) $value['max'] = 100;
2290
  if ( ! isset( $value['increment'] ) ) $value['increment'] = 1;
2291
 
2292
+ if ( ! isset( $option_value['corner'] ) ) $option_value['corner'] = '';
2293
+ $corner = $option_value['corner'];
2294
+
2295
+ if ( ! isset( $option_value['rounded_value'] ) ) $option_value['rounded_value'] = 3;
2296
+ $rounded_value = $option_value['rounded_value'];
2297
+
2298
+ if ( ! isset( $option_value['top_left_corner'] ) ) $option_value['top_left_corner'] = 3;
2299
+ $top_left_corner = $option_value['top_left_corner'];
2300
+
2301
+ if ( ! isset( $option_value['top_right_corner'] ) ) $option_value['top_right_corner'] = 3;
2302
+ $top_right_corner = $option_value['top_right_corner'];
2303
+
2304
+ if ( ! isset( $option_value['bottom_left_corner'] ) ) $option_value['bottom_left_corner'] = 3;
2305
+ $bottom_left_corner = $option_value['bottom_left_corner'];
2306
+
2307
+ if ( ! isset( $option_value['bottom_right_corner'] ) ) $option_value['bottom_right_corner'] = 3;
2308
+ $bottom_right_corner = $option_value['bottom_right_corner'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2309
 
2310
  if ( trim( $rounded_value ) == '' || trim( $rounded_value ) <= 0 ) $rounded_value = $value['min'];
2311
  $rounded_value = intval( $rounded_value );
2439
 
2440
  $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
2441
 
2442
+ if ( ! isset( $option_value['enable'] ) ) $option_value['enable'] = 0;
2443
+ $enable = $option_value['enable'];
2444
+ if ( ! isset( $option_value['inset'] ) ) $option_value['inset'] = '';
2445
+ $h_shadow = $option_value['h_shadow'];
2446
+ $v_shadow = $option_value['v_shadow'];
2447
+ $blur = $option_value['blur'];
2448
+ $spread = $option_value['spread'];
2449
+ $color = $option_value['color'];
2450
+ $inset = $option_value['inset'];
 
 
 
 
 
 
 
 
 
 
2451
 
2452
  ?><tr valign="top">
2453
  <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
admin/less/compile_less_sass_class.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  class Compile_Less_Sass {
3
 
4
- public function Compile_Less_Sass(){
5
  $this->init();
6
  }
7
  public function init(){
@@ -20,23 +20,27 @@ class Compile_Less_Sass {
20
  // Write less file
21
  if ( is_writable( $css_file ) && is_writable( $css_min_file ) ) {
22
 
23
- if ( ! class_exists( 'lessc' ) ){
24
  include( dirname( __FILE__ ) . '/lib/lessc.inc.php' );
25
  }
26
- if ( ! class_exists( 'cssmin' ) ){
27
  include( dirname( __FILE__ ) . '/lib/cssmin.inc.php' );
28
  }
29
 
30
  try {
31
 
32
- $less = new lessc;
33
 
34
  $compiled_css = $less->compileFile( $less_file );
35
 
36
  if ( $compiled_css != '' ){
37
  $wp_filesystem->put_contents( $css_file, $compiled_css );
38
 
39
- $compiled_css_min = CssMin::minify( $compiled_css );
 
 
 
 
40
  if ( $compiled_css_min != '' )
41
  $wp_filesystem->put_contents( $css_min_file, $compiled_css_min );
42
  }
1
  <?php
2
  class Compile_Less_Sass {
3
 
4
+ public function __construct(){
5
  $this->init();
6
  }
7
  public function init(){
20
  // Write less file
21
  if ( is_writable( $css_file ) && is_writable( $css_min_file ) ) {
22
 
23
+ if ( ! class_exists( 'a3_lessc' ) ){
24
  include( dirname( __FILE__ ) . '/lib/lessc.inc.php' );
25
  }
26
+ if ( ! class_exists( 'a3_CSSmin' ) ){
27
  include( dirname( __FILE__ ) . '/lib/cssmin.inc.php' );
28
  }
29
 
30
  try {
31
 
32
+ $less = new a3_lessc();
33
 
34
  $compiled_css = $less->compileFile( $less_file );
35
 
36
  if ( $compiled_css != '' ){
37
  $wp_filesystem->put_contents( $css_file, $compiled_css );
38
 
39
+ $compressor = new a3_CSSmin();
40
+ $compressor->set_memory_limit( '512M' );
41
+ $compressor->set_max_execution_time( 120 );
42
+
43
+ $compiled_css_min = $compressor->run( $compiled_css );
44
  if ( $compiled_css_min != '' )
45
  $wp_filesystem->put_contents( $css_min_file, $compiled_css_min );
46
  }
admin/less/lib/cssmin.inc.php CHANGED
@@ -1,5082 +1,777 @@
1
  <?php
2
- /**
3
- * CssMin - A (simple) css minifier with benefits
4
- *
5
- * --
6
- * Copyright (c) 2011 Joe Scylla <joe.scylla@gmail.com>
7
- *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
14
- *
15
- * The above copyright notice and this permission notice shall be included in
16
- * all copies or substantial portions of the Software.
17
- *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
- * THE SOFTWARE.
25
- * --
26
- *
27
- * @package CssMin
28
- * @link http://code.google.com/p/cssmin/
29
- * @author Joe Scylla <joe.scylla@gmail.com>
30
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
31
- * @license http://opensource.org/licenses/mit-license.php MIT License
32
- * @version 3.0.1
33
- */
34
- /**
35
- * Abstract definition of a CSS token class.
36
- *
37
- * Every token has to extend this class.
38
- *
39
- * @package CssMin/Tokens
40
- * @link http://code.google.com/p/cssmin/
41
- * @author Joe Scylla <joe.scylla@gmail.com>
42
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
43
- * @license http://opensource.org/licenses/mit-license.php MIT License
44
- * @version 3.0.1
45
- */
46
- abstract class aCssToken
47
- {
48
- /**
49
- * Returns the token as string.
50
- *
51
- * @return string
52
- */
53
- abstract public function __toString();
54
- }
55
-
56
- /**
57
- * Abstract definition of a for a ruleset start token.
58
- *
59
- * @package CssMin/Tokens
60
- * @link http://code.google.com/p/cssmin/
61
- * @author Joe Scylla <joe.scylla@gmail.com>
62
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
63
- * @license http://opensource.org/licenses/mit-license.php MIT License
64
- * @version 3.0.1
65
- */
66
- abstract class aCssRulesetStartToken extends aCssToken
67
- {
68
-
69
- }
70
-
71
- /**
72
- * Abstract definition of a for ruleset end token.
73
- *
74
- * @package CssMin/Tokens
75
- * @link http://code.google.com/p/cssmin/
76
- * @author Joe Scylla <joe.scylla@gmail.com>
77
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
78
- * @license http://opensource.org/licenses/mit-license.php MIT License
79
- * @version 3.0.1
80
- */
81
- abstract class aCssRulesetEndToken extends aCssToken
82
- {
83
- /**
84
- * Implements {@link aCssToken::__toString()}.
85
- *
86
- * @return string
87
- */
88
- public function __toString()
89
- {
90
- return "}";
91
- }
92
- }
93
-
94
- /**
95
- * Abstract definition of a parser plugin.
96
- *
97
- * Every parser plugin have to extend this class. A parser plugin contains the logic to parse one or aspects of a
98
- * stylesheet.
99
- *
100
- * @package CssMin/Parser/Plugins
101
- * @link http://code.google.com/p/cssmin/
102
- * @author Joe Scylla <joe.scylla@gmail.com>
103
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
104
- * @license http://opensource.org/licenses/mit-license.php MIT License
105
- * @version 3.0.1
106
- */
107
- abstract class aCssParserPlugin
108
- {
109
- /**
110
- * Plugin configuration.
111
- *
112
- * @var array
113
- */
114
- protected $configuration = array();
115
- /**
116
- * The CssParser of the plugin.
117
- *
118
- * @var CssParser
119
- */
120
- protected $parser = null;
121
- /**
122
- * Plugin buffer.
123
- *
124
- * @var string
125
- */
126
- protected $buffer = "";
127
- /**
128
- * Constructor.
129
- *
130
- * @param CssParser $parser The CssParser object of this plugin.
131
- * @param array $configuration Plugin configuration [optional]
132
- * @return void
133
- */
134
- public function __construct(CssParser $parser, array $configuration = null)
135
- {
136
- $this->configuration = $configuration;
137
- $this->parser = $parser;
138
- }
139
- /**
140
- * Returns the array of chars triggering the parser plugin.
141
- *
142
- * @return array
143
- */
144
- abstract public function getTriggerChars();
145
- /**
146
- * Returns the array of states triggering the parser plugin or FALSE if every state will trigger the parser plugin.
147
- *
148
- * @return array
149
- */
150
- abstract public function getTriggerStates();
151
- /**
152
- * Parser routine of the plugin.
153
- *
154
- * @param integer $index Current index
155
- * @param string $char Current char
156
- * @param string $previousChar Previous char
157
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
158
- */
159
- abstract public function parse($index, $char, $previousChar, $state);
160
- }
161
-
162
- /**
163
- * Abstract definition of a minifier plugin class.
164
- *
165
- * Minifier plugin process the parsed tokens one by one to apply changes to the token. Every minifier plugin has to
166
- * extend this class.
167
- *
168
- * @package CssMin/Minifier/Plugins
169
- * @link http://code.google.com/p/cssmin/
170
- * @author Joe Scylla <joe.scylla@gmail.com>
171
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
172
- * @license http://opensource.org/licenses/mit-license.php MIT License
173
- * @version 3.0.1
174
- */
175
- abstract class aCssMinifierPlugin
176
- {
177
- /**
178
- * Plugin configuration.
179
- *
180
- * @var array
181
- */
182
- protected $configuration = array();
183
- /**
184
- * The CssMinifier of the plugin.
185
- *
186
- * @var CssMinifier
187
- */
188
- protected $minifier = null;
189
- /**
190
- * Constructor.
191
- *
192
- * @param CssMinifier $minifier The CssMinifier object of this plugin.
193
- * @param array $configuration Plugin configuration [optional]
194
- * @return void
195
- */
196
- public function __construct(CssMinifier $minifier, array $configuration = array())
197
- {
198
- $this->configuration = $configuration;
199
- $this->minifier = $minifier;
200
- }
201
- /**
202
- * Apply the plugin to the token.
203
- *
204
- * @param aCssToken $token Token to process
205
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
206
- */
207
- abstract public function apply(aCssToken &$token);
208
- /**
209
- * --
210
- *
211
- * @return array
212
- */
213
- abstract public function getTriggerTokens();
214
- }
215
-
216
- /**
217
- * Abstract definition of a minifier filter class.
218
- *
219
- * Minifier filters allows a pre-processing of the parsed token to add, edit or delete tokens. Every minifier filter
220
- * has to extend this class.
221
- *
222
- * @package CssMin/Minifier/Filters
223
- * @link http://code.google.com/p/cssmin/
224
- * @author Joe Scylla <joe.scylla@gmail.com>
225
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
226
- * @license http://opensource.org/licenses/mit-license.php MIT License
227
- * @version 3.0.1
228
- */
229
- abstract class aCssMinifierFilter
230
- {
231
- /**
232
- * Filter configuration.
233
- *
234
- * @var array
235
- */
236
- protected $configuration = array();
237
- /**
238
- * The CssMinifier of the filter.
239
- *
240
- * @var CssMinifier
241
- */
242
- protected $minifier = null;
243
- /**
244
- * Constructor.
245
- *
246
- * @param CssMinifier $minifier The CssMinifier object of this plugin.
247
- * @param array $configuration Filter configuration [optional]
248
- * @return void
249
- */
250
- public function __construct(CssMinifier $minifier, array $configuration = array())
251
- {
252
- $this->configuration = $configuration;
253
- $this->minifier = $minifier;
254
- }
255
- /**
256
- * Filter the tokens.
257
- *
258
- * @param array $tokens Array of objects of type aCssToken
259
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
260
- */
261
- abstract public function apply(array &$tokens);
262
- }
263
-
264
- /**
265
- * Abstract formatter definition.
266
- *
267
- * Every formatter have to extend this class.
268
- *
269
- * @package CssMin/Formatter
270
- * @link http://code.google.com/p/cssmin/
271
- * @author Joe Scylla <joe.scylla@gmail.com>
272
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
273
- * @license http://opensource.org/licenses/mit-license.php MIT License
274
- * @version 3.0.1
275
- */
276
- abstract class aCssFormatter
277
- {
278
- /**
279
- * Indent string.
280
- *
281
- * @var string
282
- */
283
- protected $indent = " ";
284
- /**
285
- * Declaration padding.
286
- *
287
- * @var integer
288
- */
289
- protected $padding = 0;
290
- /**
291
- * Tokens.
292
- *
293
- * @var array
294
- */
295
- protected $tokens = array();
296
- /**
297
- * Constructor.
298
- *
299
- * @param array $tokens Array of CssToken
300
- * @param string $indent Indent string [optional]
301
- * @param integer $padding Declaration value padding [optional]
302
- */
303
- public function __construct(array $tokens, $indent = null, $padding = null)
304
- {
305
- $this->tokens = $tokens;
306
- $this->indent = !is_null($indent) ? $indent : $this->indent;
307
- $this->padding = !is_null($padding) ? $padding : $this->padding;
308
- }
309
- /**
310
- * Returns the array of aCssToken as formatted string.
311
- *
312
- * @return string
313
- */
314
- abstract public function __toString();
315
- }
316
-
317
- /**
318
- * Abstract definition of a ruleset declaration token.
319
- *
320
- * @package CssMin/Tokens
321
- * @link http://code.google.com/p/cssmin/
322
- * @author Joe Scylla <joe.scylla@gmail.com>
323
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
324
- * @license http://opensource.org/licenses/mit-license.php MIT License
325
- * @version 3.0.1
326
- */
327
- abstract class aCssDeclarationToken extends aCssToken
328
- {
329
- /**
330
- * Is the declaration flagged as important?
331
- *
332
- * @var boolean
333
- */
334
- public $IsImportant = false;
335
- /**
336
- * Is the declaration flagged as last one of the ruleset?
337
- *
338
- * @var boolean
339
- */
340
- public $IsLast = false;
341
- /**
342
- * Property name of the declaration.
343
- *
344
- * @var string
345
- */
346
- public $Property = "";
347
- /**
348
- * Value of the declaration.
349
- *
350
- * @var string
351
- */
352
- public $Value = "";
353
- /**
354
- * Set the properties of the @font-face declaration.
355
- *
356
- * @param string $property Property of the declaration
357
- * @param string $value Value of the declaration
358
- * @param boolean $isImportant Is the !important flag is set?
359
- * @param boolean $IsLast Is the declaration the last one of the block?
360
- * @return void
361
- */
362
- public function __construct($property, $value, $isImportant = false, $isLast = false)
363
- {
364
- $this->Property = $property;
365
- $this->Value = $value;
366
- $this->IsImportant = $isImportant;
367
- $this->IsLast = $isLast;
368
- }
369
- /**
370
- * Implements {@link aCssToken::__toString()}.
371
- *
372
- * @return string
373
- */
374
- public function __toString()
375
- {
376
- return $this->Property . ":" . $this->Value . ($this->IsImportant ? " !important" : "") . ($this->IsLast ? "" : ";");
377
- }
378
- }
379
-
380
- /**
381
- * Abstract definition of a for at-rule block start token.
382
- *
383
- * @package CssMin/Tokens
384
- * @link http://code.google.com/p/cssmin/
385
- * @author Joe Scylla <joe.scylla@gmail.com>
386
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
387
- * @license http://opensource.org/licenses/mit-license.php MIT License
388
- * @version 3.0.1
389
- */
390
- abstract class aCssAtBlockStartToken extends aCssToken
391
- {
392
-
393
- }
394
-
395
- /**
396
- * Abstract definition of a for at-rule block end token.
397
- *
398
- * @package CssMin/Tokens
399
- * @link http://code.google.com/p/cssmin/
400
- * @author Joe Scylla <joe.scylla@gmail.com>
401
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
402
- * @license http://opensource.org/licenses/mit-license.php MIT License
403
- * @version 3.0.1
404
- */
405
- abstract class aCssAtBlockEndToken extends aCssToken
406
- {
407
- /**
408
- * Implements {@link aCssToken::__toString()}.
409
- *
410
- * @return string
411
- */
412
- public function __toString()
413
- {
414
- return "}";
415
- }
416
- }
417
-
418
- /**
419
- * {@link aCssFromatter Formatter} returning the CSS source in {@link http://goo.gl/etzLs Whitesmiths indent style}.
420
- *
421
- * @package CssMin/Formatter
422
- * @link http://code.google.com/p/cssmin/
423
- * @author Joe Scylla <joe.scylla@gmail.com>
424
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
425
- * @license http://opensource.org/licenses/mit-license.php MIT License
426
- * @version 3.0.1
427
- */
428
- class CssWhitesmithsFormatter extends aCssFormatter
429
- {
430
- /**
431
- * Implements {@link aCssFormatter::__toString()}.
432
- *
433
- * @return string
434
- */
435
- public function __toString()
436
- {
437
- $r = array();
438
- $level = 0;
439
- for ($i = 0, $l = count($this->tokens); $i < $l; $i++)
440
- {
441
- $token = $this->tokens[$i];
442
- $class = get_class($token);
443
- $indent = str_repeat($this->indent, $level);
444
- if ($class === "CssCommentToken")
445
- {
446
- $lines = array_map("trim", explode("\n", $token->Comment));
447
- for ($ii = 0, $ll = count($lines); $ii < $ll; $ii++)
448
- {
449
- $r[] = $indent . (substr($lines[$ii], 0, 1) == "*" ? " " : "") . $lines[$ii];
450
- }
451
- }
452
- elseif ($class === "CssAtCharsetToken")
453
- {
454
- $r[] = $indent . "@charset " . $token->Charset . ";";
455
- }
456
- elseif ($class === "CssAtFontFaceStartToken")
457
- {
458
- $r[] = $indent . "@font-face";
459
- $r[] = $this->indent . $indent . "{";
460
- $level++;
461
- }
462
- elseif ($class === "CssAtImportToken")
463
- {
464
- $r[] = $indent . "@import " . $token->Import . " " . implode(", ", $token->MediaTypes) . ";";
465
- }
466
- elseif ($class === "CssAtKeyframesStartToken")
467
- {
468
- $r[] = $indent . "@keyframes \"" . $token->Name . "\"";
469
- $r[] = $this->indent . $indent . "{";
470
- $level++;
471
- }
472
- elseif ($class === "CssAtMediaStartToken")
473
- {
474
- $r[] = $indent . "@media " . implode(", ", $token->MediaTypes);
475
- $r[] = $this->indent . $indent . "{";
476
- $level++;
477
- }
478
- elseif ($class === "CssAtPageStartToken")
479
- {
480
- $r[] = $indent . "@page";
481
- $r[] = $this->indent . $indent . "{";
482
- $level++;
483
- }
484
- elseif ($class === "CssAtVariablesStartToken")
485
- {
486
- $r[] = $indent . "@variables " . implode(", ", $token->MediaTypes);
487
- $r[] = $this->indent . $indent . "{";
488
- $level++;
489
- }
490
- elseif ($class === "CssRulesetStartToken" || $class === "CssAtKeyframesRulesetStartToken")
491
- {
492
- $r[] = $indent . implode(", ", $token->Selectors);
493
- $r[] = $this->indent . $indent . "{";
494
- $level++;
495
- }
496
- elseif ($class == "CssAtFontFaceDeclarationToken"
497
- || $class === "CssAtKeyframesRulesetDeclarationToken"
498
- || $class === "CssAtPageDeclarationToken"
499
- || $class == "CssAtVariablesDeclarationToken"
500
- || $class === "CssRulesetDeclarationToken"
501
- )
502
- {
503
- $declaration = $indent . $token->Property . ": ";
504
- if ($this->padding)
505
- {
506
- $declaration = str_pad($declaration, $this->padding, " ", STR_PAD_RIGHT);
507
- }
508
- $r[] = $declaration . $token->Value . ($token->IsImportant ? " !important" : "") . ";";
509
- }
510
- elseif ($class === "CssAtFontFaceEndToken"
511
- || $class === "CssAtMediaEndToken"
512
- || $class === "CssAtKeyframesEndToken"
513
- || $class === "CssAtKeyframesRulesetEndToken"
514
- || $class === "CssAtPageEndToken"
515
- || $class === "CssAtVariablesEndToken"
516
- || $class === "CssRulesetEndToken"
517
- )
518
- {
519
- $r[] = $indent . "}";
520
- $level--;
521
- }
522
- }
523
- return implode("\n", $r);
524
- }
525
- }
526
-
527
- /**
528
- * This {@link aCssMinifierPlugin} will process var-statement and sets the declaration value to the variable value.
529
- *
530
- * This plugin only apply the variable values. The variable values itself will get parsed by the
531
- * {@link CssVariablesMinifierFilter}.
532
- *
533
- * Example:
534
- * <code>
535
- * @variables
536
- * {
537
- * defaultColor: black;
538
- * }
539
- * color: var(defaultColor);
540
- * </code>
541
- *
542
- * Will get converted to:
543
- * <code>
544
- * color:black;
545
- * </code>
546
- *
547
- * @package CssMin/Minifier/Plugins
548
- * @link http://code.google.com/p/cssmin/
549
- * @author Joe Scylla <joe.scylla@gmail.com>
550
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
551
- * @license http://opensource.org/licenses/mit-license.php MIT License
552
- * @version 3.0.1
553
- */
554
- class CssVariablesMinifierPlugin extends aCssMinifierPlugin
555
- {
556
- /**
557
- * Regular expression matching a value.
558
- *
559
- * @var string
560
- */
561
- private $reMatch = "/var\((.+)\)/iSU";
562
- /**
563
- * Parsed variables.
564
- *
565
- * @var array
566
- */
567
- private $variables = null;
568
- /**
569
- * Returns the variables.
570
- *
571
- * @return array
572
- */
573
- public function getVariables()
574
- {
575
- return $this->variables;
576
- }
577
- /**
578
- * Implements {@link aCssMinifierPlugin::minify()}.
579
- *
580
- * @param aCssToken $token Token to process
581
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
582
- */
583
- public function apply(aCssToken &$token)
584
- {
585
- if (stripos($token->Value, "var") !== false && preg_match_all($this->reMatch, $token->Value, $m))
586
- {
587
- $mediaTypes = $token->MediaTypes;
588
- if (!in_array("all", $mediaTypes))
589
- {
590
- $mediaTypes[] = "all";
591
- }
592
- for ($i = 0, $l = count($m[0]); $i < $l; $i++)
593
- {
594
- $variable = trim($m[1][$i]);
595
- foreach ($mediaTypes as $mediaType)
596
- {
597
- if (isset($this->variables[$mediaType], $this->variables[$mediaType][$variable]))
598
- {
599
- // Variable value found => set the declaration value to the variable value and return
600
- $token->Value = str_replace($m[0][$i], $this->variables[$mediaType][$variable], $token->Value);
601
- continue 2;
602
- }
603
- }
604
- // If no value was found trigger an error and replace the token with a CssNullToken
605
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": No value found for variable <code>" . $variable . "</code> in media types <code>" . implode(", ", $mediaTypes) . "</code>", (string) $token));
606
- $token = new CssNullToken();
607
- return true;
608
- }
609
- }
610
- return false;
611
- }
612
- /**
613
- * Implements {@link aMinifierPlugin::getTriggerTokens()}
614
- *
615
- * @return array
616
- */
617
- public function getTriggerTokens()
618
- {
619
- return array
620
- (
621
- "CssAtFontFaceDeclarationToken",
622
- "CssAtPageDeclarationToken",
623
- "CssRulesetDeclarationToken"
624
- );
625
- }
626
- /**
627
- * Sets the variables.
628
- *
629
- * @param array $variables Variables to set
630
- * @return void
631
- */
632
- public function setVariables(array $variables)
633
- {
634
- $this->variables = $variables;
635
- }
636
- }
637
-
638
- /**
639
- * This {@link aCssMinifierFilter minifier filter} will parse the variable declarations out of @variables at-rule
640
- * blocks. The variables will get store in the {@link CssVariablesMinifierPlugin} that will apply the variables to
641
- * declaration.
642
- *
643
- * @package CssMin/Minifier/Filters
644
- * @link http://code.google.com/p/cssmin/
645
- * @author Joe Scylla <joe.scylla@gmail.com>
646
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
647
- * @license http://opensource.org/licenses/mit-license.php MIT License
648
- * @version 3.0.1
649
- */
650
- class CssVariablesMinifierFilter extends aCssMinifierFilter
651
- {
652
- /**
653
- * Implements {@link aCssMinifierFilter::filter()}.
654
- *
655
- * @param array $tokens Array of objects of type aCssToken
656
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
657
- */
658
- public function apply(array &$tokens)
659
- {
660
- $variables = array();
661
- $defaultMediaTypes = array("all");
662
- $mediaTypes = array();
663
- $remove = array();
664
- for($i = 0, $l = count($tokens); $i < $l; $i++)
665
- {
666
- // @variables at-rule block found
667
- if (get_class($tokens[$i]) === "CssAtVariablesStartToken")
668
- {
669
- $remove[] = $i;
670
- $mediaTypes = (count($tokens[$i]->MediaTypes) == 0 ? $defaultMediaTypes : $tokens[$i]->MediaTypes);
671
- foreach ($mediaTypes as $mediaType)
672
- {
673
- if (!isset($variables[$mediaType]))
674
- {
675
- $variables[$mediaType] = array();
676
- }
677
- }
678
- // Read the variable declaration tokens
679
- for($i = $i; $i < $l; $i++)
680
- {
681
- // Found a variable declaration => read the variable values
682
- if (get_class($tokens[$i]) === "CssAtVariablesDeclarationToken")
683
- {
684
- foreach ($mediaTypes as $mediaType)
685
- {
686
- $variables[$mediaType][$tokens[$i]->Property] = $tokens[$i]->Value;
687
- }
688
- $remove[] = $i;
689
- }
690
- // Found the variables end token => break;
691
- elseif (get_class($tokens[$i]) === "CssAtVariablesEndToken")
692
- {
693
- $remove[] = $i;
694
- break;
695
- }
696
- }
697
- }
698
- }
699
- // Variables in @variables at-rule blocks
700
- foreach($variables as $mediaType => $null)
701
- {
702
- foreach($variables[$mediaType] as $variable => $value)
703
- {
704
- // If a var() statement in a variable value found...
705
- if (stripos($value, "var") !== false && preg_match_all("/var\((.+)\)/iSU", $value, $m))
706
- {
707
- // ... then replace the var() statement with the variable values.
708
- for ($i = 0, $l = count($m[0]); $i < $l; $i++)
709
- {
710
- $variables[$mediaType][$variable] = str_replace($m[0][$i], (isset($variables[$mediaType][$m[1][$i]]) ? $variables[$mediaType][$m[1][$i]] : ""), $variables[$mediaType][$variable]);
711
- }
712
- }
713
- }
714
- }
715
- // Remove the complete @variables at-rule block
716
- foreach ($remove as $i)
717
- {
718
- $tokens[$i] = null;
719
- }
720
- if (!($plugin = $this->minifier->getPlugin("CssVariablesMinifierPlugin")))
721
- {
722
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>CssVariablesMinifierPlugin</code> was not found but is required for <code>" . __CLASS__ . "</code>"));
723
- }
724
- else
725
- {
726
- $plugin->setVariables($variables);
727
- }
728
- return count($remove);
729
- }
730
- }
731
-
732
- /**
733
- * {@link aCssParserPlugin Parser plugin} for preserve parsing url() values.
734
- *
735
- * This plugin return no {@link aCssToken CssToken} but ensures that url() values will get parsed properly.
736
- *
737
- * @package CssMin/Parser/Plugins
738
- * @link http://code.google.com/p/cssmin/
739
- * @author Joe Scylla <joe.scylla@gmail.com>
740
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
741
- * @license http://opensource.org/licenses/mit-license.php MIT License
742
- * @version 3.0.1
743
- */
744
- class CssUrlParserPlugin extends aCssParserPlugin
745
- {
746
- /**
747
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
748
- *
749
- * @return array
750
- */
751
- public function getTriggerChars()
752
- {
753
- return array("(", ")");
754
- }
755
- /**
756
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
757
- *
758
- * @return array
759
- */
760
- public function getTriggerStates()
761
- {
762
- return false;
763
- }
764
- /**
765
- * Implements {@link aCssParserPlugin::parse()}.
766
- *
767
- * @param integer $index Current index
768
- * @param string $char Current char
769
- * @param string $previousChar Previous char
770
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
771
- */
772
- public function parse($index, $char, $previousChar, $state)
773
- {
774
- // Start of string
775
- if ($char === "(" && strtolower(substr($this->parser->getSource(), $index - 3, 4)) === "url(" && $state !== "T_URL")
776
- {
777
- $this->parser->pushState("T_URL");
778
- $this->parser->setExclusive(__CLASS__);
779
- }
780
- // Escaped LF in url => remove escape backslash and LF
781
- elseif ($char === "\n" && $previousChar === "\\" && $state === "T_URL")
782
- {
783
- $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2));
784
- }
785
- // Parse error: Unescaped LF in string literal
786
- elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_URL")
787
- {
788
- $line = $this->parser->getBuffer();
789
- $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . ")"); // Replace the LF with the url string delimiter
790
- $this->parser->popState();
791
- $this->parser->unsetExclusive();
792
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_"));
793
- }
794
- // End of string
795
- elseif ($char === ")" && $state === "T_URL")
796
- {
797
- $this->parser->popState();
798
- $this->parser->unsetExclusive();
799
- }
800
- else
801
- {
802
- return false;
803
- }
804
- return true;
805
- }
806
- }
807
-
808
- /**
809
- * {@link aCssParserPlugin Parser plugin} for preserve parsing string values.
810
- *
811
- * This plugin return no {@link aCssToken CssToken} but ensures that string values will get parsed properly.
812
- *
813
- * @package CssMin/Parser/Plugins
814
- * @link http://code.google.com/p/cssmin/
815
- * @author Joe Scylla <joe.scylla@gmail.com>
816
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
817
- * @license http://opensource.org/licenses/mit-license.php MIT License
818
- * @version 3.0.1
819
- */
820
- class CssStringParserPlugin extends aCssParserPlugin
821
- {
822
- /**
823
- * Current string delimiter char.
824
- *
825
- * @var string
826
- */
827
- private $delimiterChar = null;
828
- /**
829
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
830
- *
831
- * @return array
832
- */
833
- public function getTriggerChars()
834
- {
835
- return array("\"", "'", "\n");
836
- }
837
- /**
838
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
839
- *
840
- * @return array
841
- */
842
- public function getTriggerStates()
843
- {
844
- return false;
845
- }
846
- /**
847
- * Implements {@link aCssParserPlugin::parse()}.
848
- *
849
- * @param integer $index Current index
850
- * @param string $char Current char
851
- * @param string $previousChar Previous char
852
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
853
- */
854
- public function parse($index, $char, $previousChar, $state)
855
- {
856
- // Start of string
857
- if (($char === "\"" || $char === "'") && $state !== "T_STRING")
858
- {
859
- $this->delimiterChar = $char;
860
- $this->parser->pushState("T_STRING");
861
- $this->parser->setExclusive(__CLASS__);
862
- }
863
- // Escaped LF in string => remove escape backslash and LF
864
- elseif ($char === "\n" && $previousChar === "\\" && $state === "T_STRING")
865
- {
866
- $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2));
867
- }
868
- // Parse error: Unescaped LF in string literal
869
- elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_STRING")
870
- {
871
- $line = $this->parser->getBuffer();
872
- $this->parser->popState();
873
- $this->parser->unsetExclusive();
874
- $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . $this->delimiterChar); // Replace the LF with the current string char
875
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_"));
876
- $this->delimiterChar = null;
877
- }
878
- // End of string
879
- elseif ($char === $this->delimiterChar && $state === "T_STRING")
880
- {
881
- // If the Previous char is a escape char count the amount of the previous escape chars. If the amount of
882
- // escape chars is uneven do not end the string
883
- if ($previousChar == "\\")
884
- {
885
- $source = $this->parser->getSource();
886
- $c = 1;
887
- $i = $index - 2;
888
- while (substr($source, $i, 1) === "\\")
889
- {
890
- $c++; $i--;
891
- }
892
- if ($c % 2)
893
- {
894
- return false;
895
- }
896
- }
897
- $this->parser->popState();
898
- $this->parser->unsetExclusive();
899
- $this->delimiterChar = null;
900
- }
901
- else
902
- {
903
- return false;
904
- }
905
- return true;
906
- }
907
- }
908
-
909
- /**
910
- * This {@link aCssMinifierFilter minifier filter} sorts the ruleset declarations of a ruleset by name.
911
- *
912
- * @package CssMin/Minifier/Filters
913
- * @link http://code.google.com/p/cssmin/
914
- * @author Rowan Beentje <http://assanka.net>
915
- * @copyright Rowan Beentje <http://assanka.net>
916
- * @license http://opensource.org/licenses/mit-license.php MIT License
917
- * @version 3.0.1
918
- */
919
- class CssSortRulesetPropertiesMinifierFilter extends aCssMinifierFilter
920
- {
921
- /**
922
- * Implements {@link aCssMinifierFilter::filter()}.
923
- *
924
- * @param array $tokens Array of objects of type aCssToken
925
- * @return integer Count of added, changed or removed tokens; a return value larger than 0 will rebuild the array
926
- */
927
- public function apply(array &$tokens)
928
- {
929
- $r = 0;
930
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
931
- {
932
- // Only look for ruleset start rules
933
- if (get_class($tokens[$i]) !== "CssRulesetStartToken") { continue; }
934
- // Look for the corresponding ruleset end
935
- $endIndex = false;
936
- for ($ii = $i + 1; $ii < $l; $ii++)
937
- {
938
- if (get_class($tokens[$ii]) !== "CssRulesetEndToken") { continue; }
939
- $endIndex = $ii;
940
- break;
941
- }
942
- if (!$endIndex) { break; }
943
- $startIndex = $i;
944
- $i = $endIndex;
945
- // Skip if there's only one token in this ruleset
946
- if ($endIndex - $startIndex <= 2) { continue; }
947
- // Ensure that everything between the start and end is a declaration token, for safety
948
- for ($ii = $startIndex + 1; $ii < $endIndex; $ii++)
949
- {
950
- if (get_class($tokens[$ii]) !== "CssRulesetDeclarationToken") { continue(2); }
951
- }
952
- $declarations = array_slice($tokens, $startIndex + 1, $endIndex - $startIndex - 1);
953
- // Check whether a sort is required
954
- $sortRequired = $lastPropertyName = false;
955
- foreach ($declarations as $declaration)
956
- {
957
- if ($lastPropertyName)
958
- {
959
- if (strcmp($lastPropertyName, $declaration->Property) > 0)
960
- {
961
- $sortRequired = true;
962
- break;
963
- }
964
- }
965
- $lastPropertyName = $declaration->Property;
966
- }
967
- if (!$sortRequired) { continue; }
968
- // Arrange the declarations alphabetically by name
969
- usort($declarations, array(__CLASS__, "userDefinedSort1"));
970
- // Update "IsLast" property
971
- for ($ii = 0, $ll = count($declarations) - 1; $ii <= $ll; $ii++)
972
- {
973
- if ($ii == $ll)
974
- {
975
- $declarations[$ii]->IsLast = true;
976
- }
977
- else
978
- {
979
- $declarations[$ii]->IsLast = false;
980
- }
981
- }
982
- // Splice back into the array.
983
- array_splice($tokens, $startIndex + 1, $endIndex - $startIndex - 1, $declarations);
984
- $r += $endIndex - $startIndex - 1;
985
- }
986
- return $r;
987
- }
988
- /**
989
- * User defined sort function.
990
- *
991
- * @return integer
992
- */
993
- public static function userDefinedSort1($a, $b)
994
- {
995
- return strcmp($a->Property, $b->Property);
996
- }
997
- }
998
-
999
- /**
1000
- * This {@link aCssToken CSS token} represents the start of a ruleset.
1001
- *
1002
- * @package CssMin/Tokens
1003
- * @link http://code.google.com/p/cssmin/
1004
- * @author Joe Scylla <joe.scylla@gmail.com>
1005
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1006
- * @license http://opensource.org/licenses/mit-license.php MIT License
1007
- * @version 3.0.1
1008
- */
1009
- class CssRulesetStartToken extends aCssRulesetStartToken
1010
- {
1011
- /**
1012
- * Array of selectors.
1013
- *
1014
- * @var array
1015
- */
1016
- public $Selectors = array();
1017
- /**
1018
- * Set the properties of a ruleset token.
1019
- *
1020
- * @param array $selectors Selectors of the ruleset
1021
- * @return void
1022
- */
1023
- public function __construct(array $selectors = array())
1024
- {
1025
- $this->Selectors = $selectors;
1026
- }
1027
- /**
1028
- * Implements {@link aCssToken::__toString()}.
1029
- *
1030
- * @return string
1031
- */
1032
- public function __toString()
1033
- {
1034
- return implode(",", $this->Selectors) . "{";
1035
- }
1036
- }
1037
-
1038
- /**
1039
- * {@link aCssParserPlugin Parser plugin} for parsing ruleset block with including declarations.
1040
- *
1041
- * Found rulesets will add a {@link CssRulesetStartToken} and {@link CssRulesetEndToken} to the
1042
- * parser; including declarations as {@link CssRulesetDeclarationToken}.
1043
- *
1044
- * @package CssMin/Parser/Plugins
1045
- * @link http://code.google.com/p/cssmin/
1046
- * @author Joe Scylla <joe.scylla@gmail.com>
1047
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1048
- * @license http://opensource.org/licenses/mit-license.php MIT License
1049
- * @version 3.0.1
1050
- */
1051
- class CssRulesetParserPlugin extends aCssParserPlugin
1052
- {
1053
- /**
1054
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
1055
- *
1056
- * @return array
1057
- */
1058
- public function getTriggerChars()
1059
- {
1060
- return array(",", "{", "}", ":", ";");
1061
- }
1062
- /**
1063
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
1064
- *
1065
- * @return array
1066
- */
1067
- public function getTriggerStates()
1068
- {
1069
- return array("T_DOCUMENT", "T_AT_MEDIA", "T_RULESET::SELECTORS", "T_RULESET", "T_RULESET_DECLARATION");
1070
- }
1071
- /**
1072
- * Selectors.
1073
- *
1074
- * @var array
1075
- */
1076
- private $selectors = array();
1077
- /**
1078
- * Implements {@link aCssParserPlugin::parse()}.
1079
- *
1080
- * @param integer $index Current index
1081
- * @param string $char Current char
1082
- * @param string $previousChar Previous char
1083
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
1084
- */
1085
- public function parse($index, $char, $previousChar, $state)
1086
- {
1087
- // Start of Ruleset and selectors
1088
- if ($char === "," && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS"))
1089
- {
1090
- if ($state !== "T_RULESET::SELECTORS")
1091
- {
1092
- $this->parser->pushState("T_RULESET::SELECTORS");
1093
- }
1094
- $this->selectors[] = $this->parser->getAndClearBuffer(",{");
1095
- }
1096
- // End of selectors and start of declarations
1097
- elseif ($char === "{" && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS"))
1098
- {
1099
- if ($this->parser->getBuffer() !== "")
1100
- {
1101
- $this->selectors[] = $this->parser->getAndClearBuffer(",{");
1102
- if ($state == "T_RULESET::SELECTORS")
1103
- {
1104
- $this->parser->popState();
1105
- }
1106
- $this->parser->pushState("T_RULESET");
1107
- $this->parser->appendToken(new CssRulesetStartToken($this->selectors));
1108
- $this->selectors = array();
1109
- }
1110
- }
1111
- // Start of declaration
1112
- elseif ($char === ":" && $state === "T_RULESET")
1113
- {
1114
- $this->parser->pushState("T_RULESET_DECLARATION");
1115
- $this->buffer = $this->parser->getAndClearBuffer(":;", true);
1116
- }
1117
- // Unterminated ruleset declaration
1118
- elseif ($char === ":" && $state === "T_RULESET_DECLARATION")
1119
- {
1120
- // Ignore Internet Explorer filter declarations
1121
- if ($this->buffer === "filter")
1122
- {
1123
- return false;
1124
- }
1125
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
1126
- }
1127
- // End of declaration
1128
- elseif (($char === ";" || $char === "}") && $state === "T_RULESET_DECLARATION")
1129
- {
1130
- $value = $this->parser->getAndClearBuffer(";}");
1131
- if (strtolower(substr($value, -10, 10)) === "!important")
1132
- {
1133
- $value = trim(substr($value, 0, -10));
1134
- $isImportant = true;
1135
- }
1136
- else
1137
- {
1138
- $isImportant = false;
1139
- }
1140
- $this->parser->popState();
1141
- $this->parser->appendToken(new CssRulesetDeclarationToken($this->buffer, $value, $this->parser->getMediaTypes(), $isImportant));
1142
- // Declaration ends with a right curly brace; so we have to end the ruleset
1143
- if ($char === "}")
1144
- {
1145
- $this->parser->appendToken(new CssRulesetEndToken());
1146
- $this->parser->popState();
1147
- }
1148
- $this->buffer = "";
1149
- }
1150
- // End of ruleset
1151
- elseif ($char === "}" && $state === "T_RULESET")
1152
- {
1153
- $this->parser->popState();
1154
- $this->parser->clearBuffer();
1155
- $this->parser->appendToken(new CssRulesetEndToken());
1156
- $this->buffer = "";
1157
- $this->selectors = array();
1158
- }
1159
- else
1160
- {
1161
- return false;
1162
- }
1163
- return true;
1164
- }
1165
- }
1166
-
1167
- /**
1168
- * This {@link aCssToken CSS token} represents the end of a ruleset.
1169
- *
1170
- * @package CssMin/Tokens
1171
- * @link http://code.google.com/p/cssmin/
1172
- * @author Joe Scylla <joe.scylla@gmail.com>
1173
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1174
- * @license http://opensource.org/licenses/mit-license.php MIT License
1175
- * @version 3.0.1
1176
- */
1177
- class CssRulesetEndToken extends aCssRulesetEndToken
1178
- {
1179
-
1180
- }
1181
 
1182
- /**
1183
- * This {@link aCssToken CSS token} represents a ruleset declaration.
1184
- *
1185
- * @package CssMin/Tokens
1186
- * @link http://code.google.com/p/cssmin/
1187
- * @author Joe Scylla <joe.scylla@gmail.com>
1188
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1189
- * @license http://opensource.org/licenses/mit-license.php MIT License
1190
- * @version 3.0.1
1191
- */
1192
- class CssRulesetDeclarationToken extends aCssDeclarationToken
1193
- {
1194
- /**
1195
- * Media types of the declaration.
1196
- *
1197
- * @var array
1198
- */
1199
- public $MediaTypes = array("all");
1200
- /**
1201
- * Set the properties of a ddocument- or at-rule @media level declaration.
1202
- *
1203
- * @param string $property Property of the declaration
1204
- * @param string $value Value of the declaration
1205
- * @param mixed $mediaTypes Media types of the declaration
1206
- * @param boolean $isImportant Is the !important flag is set
1207
- * @param boolean $isLast Is the declaration the last one of the ruleset
1208
- * @return void
1209
- */
1210
- public function __construct($property, $value, $mediaTypes = null, $isImportant = false, $isLast = false)
1211
- {
1212
- parent::__construct($property, $value, $isImportant, $isLast);
1213
- $this->MediaTypes = $mediaTypes ? $mediaTypes : array("all");
1214
- }
1215
- }
1216
-
1217
- /**
1218
- * This {@link aCssMinifierFilter minifier filter} sets the IsLast property of any last declaration in a ruleset,
1219
- * @font-face at-rule or @page at-rule block. If the property IsLast is TRUE the decrations will get stringified
1220
- * without tailing semicolon.
1221
- *
1222
- * @package CssMin/Minifier/Filters
1223
- * @link http://code.google.com/p/cssmin/
1224
- * @author Joe Scylla <joe.scylla@gmail.com>
1225
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1226
- * @license http://opensource.org/licenses/mit-license.php MIT License
1227
- * @version 3.0.1
1228
- */
1229
- class CssRemoveLastDelarationSemiColonMinifierFilter extends aCssMinifierFilter
1230
- {
1231
- /**
1232
- * Implements {@link aCssMinifierFilter::filter()}.
1233
- *
1234
- * @param array $tokens Array of objects of type aCssToken
1235
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
1236
- */
1237
- public function apply(array &$tokens)
1238
- {
1239
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
1240
- {
1241
- $current = get_class($tokens[$i]);
1242
- $next = isset($tokens[$i+1]) ? get_class($tokens[$i+1]) : false;
1243
- if (($current === "CssRulesetDeclarationToken" && $next === "CssRulesetEndToken") ||
1244
- ($current === "CssAtFontFaceDeclarationToken" && $next === "CssAtFontFaceEndToken") ||
1245
- ($current === "CssAtPageDeclarationToken" && $next === "CssAtPageEndToken"))
1246
- {
1247
- $tokens[$i]->IsLast = true;
1248
- }
1249
- }
1250
- return 0;
1251
- }
1252
- }
1253
-
1254
- /**
1255
- * This {@link aCssMinifierFilter minifier filter} will remove any empty rulesets (including @keyframes at-rule block
1256
- * rulesets).
1257
- *
1258
- * @package CssMin/Minifier/Filters
1259
- * @link http://code.google.com/p/cssmin/
1260
- * @author Joe Scylla <joe.scylla@gmail.com>
1261
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1262
- * @license http://opensource.org/licenses/mit-license.php MIT License
1263
- * @version 3.0.1
1264
- */
1265
- class CssRemoveEmptyRulesetsMinifierFilter extends aCssMinifierFilter
1266
- {
1267
- /**
1268
- * Implements {@link aCssMinifierFilter::filter()}.
1269
- *
1270
- * @param array $tokens Array of objects of type aCssToken
1271
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
1272
- */
1273
- public function apply(array &$tokens)
1274
- {
1275
- $r = 0;
1276
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
1277
- {
1278
- $current = get_class($tokens[$i]);
1279
- $next = isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false;
1280
- if (($current === "CssRulesetStartToken" && $next === "CssRulesetEndToken") ||
1281
- ($current === "CssAtKeyframesRulesetStartToken" && $next === "CssAtKeyframesRulesetEndToken" && !array_intersect(array("from", "0%", "to", "100%"), array_map("strtolower", $tokens[$i]->Selectors)))
1282
- )
1283
- {
1284
- $tokens[$i] = null;
1285
- $tokens[$i + 1] = null;
1286
- $i++;
1287
- $r = $r + 2;
1288
- }
1289
- }
1290
- return $r;
1291
- }
1292
- }
1293
-
1294
- /**
1295
- * This {@link aCssMinifierFilter minifier filter} will remove any empty @font-face, @keyframes, @media and @page
1296
- * at-rule blocks.
1297
- *
1298
- * @package CssMin/Minifier/Filters
1299
- * @link http://code.google.com/p/cssmin/
1300
- * @author Joe Scylla <joe.scylla@gmail.com>
1301
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1302
- * @license http://opensource.org/licenses/mit-license.php MIT License
1303
- * @version 3.0.1
1304
- */
1305
- class CssRemoveEmptyAtBlocksMinifierFilter extends aCssMinifierFilter
1306
- {
1307
- /**
1308
- * Implements {@link aCssMinifierFilter::filter()}.
1309
- *
1310
- * @param array $tokens Array of objects of type aCssToken
1311
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
1312
- */
1313
- public function apply(array &$tokens)
1314
- {
1315
- $r = 0;
1316
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
1317
- {
1318
- $current = get_class($tokens[$i]);
1319
- $next = isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false;
1320
- if (($current === "CssAtFontFaceStartToken" && $next === "CssAtFontFaceEndToken") ||
1321
- ($current === "CssAtKeyframesStartToken" && $next === "CssAtKeyframesEndToken") ||
1322
- ($current === "CssAtPageStartToken" && $next === "CssAtPageEndToken") ||
1323
- ($current === "CssAtMediaStartToken" && $next === "CssAtMediaEndToken"))
1324
- {
1325
- $tokens[$i] = null;
1326
- $tokens[$i + 1] = null;
1327
- $i++;
1328
- $r = $r + 2;
1329
- }
1330
- }
1331
- return $r;
1332
- }
1333
- }
1334
-
1335
- /**
1336
- * This {@link aCssMinifierFilter minifier filter} will remove any comments from the array of parsed tokens.
1337
- *
1338
- * @package CssMin/Minifier/Filters
1339
- * @link http://code.google.com/p/cssmin/
1340
- * @author Joe Scylla <joe.scylla@gmail.com>
1341
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1342
- * @license http://opensource.org/licenses/mit-license.php MIT License
1343
- * @version 3.0.1
1344
- */
1345
- class CssRemoveCommentsMinifierFilter extends aCssMinifierFilter
1346
- {
1347
- /**
1348
- * Implements {@link aCssMinifierFilter::filter()}.
1349
- *
1350
- * @param array $tokens Array of objects of type aCssToken
1351
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
1352
- */
1353
- public function apply(array &$tokens)
1354
- {
1355
- $r = 0;
1356
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
1357
- {
1358
- if (get_class($tokens[$i]) === "CssCommentToken")
1359
- {
1360
- $tokens[$i] = null;
1361
- $r++;
1362
- }
1363
- }
1364
- return $r;
1365
- }
1366
- }
1367
-
1368
- /**
1369
- * CSS Parser.
1370
- *
1371
- * @package CssMin/Parser
1372
- * @link http://code.google.com/p/cssmin/
1373
- * @author Joe Scylla <joe.scylla@gmail.com>
1374
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1375
- * @license http://opensource.org/licenses/mit-license.php MIT License
1376
- * @version 3.0.1
1377
- */
1378
- class CssParser
1379
- {
1380
- /**
1381
- * Parse buffer.
1382
- *
1383
- * @var string
1384
- */
1385
- private $buffer = "";
1386
- /**
1387
- * {@link aCssParserPlugin Plugins}.
1388
- *
1389
- * @var array
1390
- */
1391
- private $plugins = array();
1392
- /**
1393
- * Source to parse.
1394
- *
1395
- * @var string
1396
- */
1397
- private $source = "";
1398
- /**
1399
- * Current state.
1400
- *
1401
- * @var integer
1402
- */
1403
- private $state = "T_DOCUMENT";
1404
- /**
1405
- * Exclusive state.
1406
- *
1407
- * @var string
1408
- */
1409
- private $stateExclusive = false;
1410
- /**
1411
- * Media types state.
1412
- *
1413
- * @var mixed
1414
- */
1415
- private $stateMediaTypes = false;
1416
- /**
1417
- * State stack.
1418
- *
1419
- * @var array
1420
- */
1421
- private $states = array("T_DOCUMENT");
1422
- /**
1423
- * Parsed tokens.
1424
- *
1425
- * @var array
1426
- */
1427
- private $tokens = array();
1428
- /**
1429
- * Constructer.
1430
- *
1431
- * Create instances of the used {@link aCssParserPlugin plugins}.
1432
- *
1433
- * @param string $source CSS source [optional]
1434
- * @param array $plugins Plugin configuration [optional]
1435
- * @return void
1436
- */
1437
- public function __construct($source = null, array $plugins = null)
1438
- {
1439
- $plugins = array_merge(array
1440
- (
1441
- "Comment" => true,
1442
- "String" => true,
1443
- "Url" => true,
1444
- "Expression" => true,
1445
- "Ruleset" => true,
1446
- "AtCharset" => true,
1447
- "AtFontFace" => true,
1448
- "AtImport" => true,
1449
- "AtKeyframes" => true,
1450
- "AtMedia" => true,
1451
- "AtPage" => true,
1452
- "AtVariables" => true
1453
- ), is_array($plugins) ? $plugins : array());
1454
- // Create plugin instances
1455
- foreach ($plugins as $name => $config)
1456
- {
1457
- if ($config !== false)
1458
- {
1459
- $class = "Css" . $name . "ParserPlugin";
1460
- $config = is_array($config) ? $config : array();
1461
- if (class_exists($class))
1462
- {
1463
- $this->plugins[] = new $class($this, $config);
1464
- }
1465
- else
1466
- {
1467
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));
1468
- }
1469
- }
1470
- }
1471
- if (!is_null($source))
1472
- {
1473
- $this->parse($source);
1474
- }
1475
- }
1476
- /**
1477
- * Append a token to the array of tokens.
1478
- *
1479
- * @param aCssToken $token Token to append
1480
- * @return void
1481
- */
1482
- public function appendToken(aCssToken $token)
1483
- {
1484
- $this->tokens[] = $token;
1485
- }
1486
- /**
1487
- * Clears the current buffer.
1488
- *
1489
- * @return void
1490
- */
1491
- public function clearBuffer()
1492
- {
1493
- $this->buffer = "";
1494
- }
1495
- /**
1496
- * Returns and clear the current buffer.
1497
- *
1498
- * @param string $trim Chars to use to trim the returned buffer
1499
- * @param boolean $tolower if TRUE the returned buffer will get converted to lower case
1500
- * @return string
1501
- */
1502
- public function getAndClearBuffer($trim = "", $tolower = false)
1503
- {
1504
- $r = $this->getBuffer($trim, $tolower);
1505
- $this->buffer = "";
1506
- return $r;
1507
- }
1508
- /**
1509
- * Returns the current buffer.
1510
- *
1511
- * @param string $trim Chars to use to trim the returned buffer
1512
- * @param boolean $tolower if TRUE the returned buffer will get converted to lower case
1513
- * @return string
1514
- */
1515
- public function getBuffer($trim = "", $tolower = false)
1516
- {
1517
- $r = $this->buffer;
1518
- if ($trim)
1519
- {
1520
- $r = trim($r, " \t\n\r\0\x0B" . $trim);
1521
- }
1522
- if ($tolower)
1523
- {
1524
- $r = strtolower($r);
1525
- }
1526
- return $r;
1527
- }
1528
- /**
1529
- * Returns the current media types state.
1530
- *
1531
- * @return array
1532
- */
1533
- public function getMediaTypes()
1534
- {
1535
- return $this->stateMediaTypes;
1536
- }
1537
- /**
1538
- * Returns the CSS source.
1539
- *
1540
- * @return string
1541
- */
1542
- public function getSource()
1543
- {
1544
- return $this->source;
1545
- }
1546
- /**
1547
- * Returns the current state.
1548
- *
1549
- * @return integer The current state
1550
- */
1551
- public function getState()
1552
- {
1553
- return $this->state;
1554
- }
1555
- /**
1556
- * Returns a plugin by class name.
1557
- *
1558
- * @param string $name Class name of the plugin
1559
- * @return aCssParserPlugin
1560
- */
1561
- public function getPlugin($class)
1562
- {
1563
- static $index = null;
1564
- if (is_null($index))
1565
- {
1566
- $index = array();
1567
- for ($i = 0, $l = count($this->plugins); $i < $l; $i++)
1568
- {
1569
- $index[get_class($this->plugins[$i])] = $i;
1570
- }
1571
- }
1572
- return isset($index[$class]) ? $this->plugins[$index[$class]] : false;
1573
- }
1574
- /**
1575
- * Returns the parsed tokens.
1576
- *
1577
- * @return array
1578
- */
1579
- public function getTokens()
1580
- {
1581
- return $this->tokens;
1582
- }
1583
- /**
1584
- * Returns if the current state equals the passed state.
1585
- *
1586
- * @param integer $state State to compare with the current state
1587
- * @return boolean TRUE is the state equals to the passed state; FALSE if not
1588
- */
1589
- public function isState($state)
1590
- {
1591
- return ($this->state == $state);
1592
- }
1593
- /**
1594
- * Parse the CSS source and return a array with parsed tokens.
1595
- *
1596
- * @param string $source CSS source
1597
- * @return array Array with tokens
1598
- */
1599
- public function parse($source)
1600
- {
1601
- // Reset
1602
- $this->source = "";
1603
- $this->tokens = array();
1604
- // Create a global and plugin lookup table for trigger chars; set array of plugins as local variable and create
1605
- // several helper variables for plugin handling
1606
- $globalTriggerChars = "";
1607
- $plugins = $this->plugins;
1608
- $pluginCount = count($plugins);
1609
- $pluginIndex = array();
1610
- $pluginTriggerStates = array();
1611
- $pluginTriggerChars = array();
1612
- for ($i = 0, $l = count($plugins); $i < $l; $i++)
1613
- {
1614
- $tPluginClassName = get_class($plugins[$i]);
1615
- $pluginTriggerChars[$i] = implode("", $plugins[$i]->getTriggerChars());
1616
- $tPluginTriggerStates = $plugins[$i]->getTriggerStates();
1617
- $pluginTriggerStates[$i] = $tPluginTriggerStates === false ? false : "|" . implode("|", $tPluginTriggerStates) . "|";
1618
- $pluginIndex[$tPluginClassName] = $i;
1619
- for ($ii = 0, $ll = strlen($pluginTriggerChars[$i]); $ii < $ll; $ii++)
1620
- {
1621
- $c = substr($pluginTriggerChars[$i], $ii, 1);
1622
- if (strpos($globalTriggerChars, $c) === false)
1623
- {
1624
- $globalTriggerChars .= $c;
1625
- }
1626
- }
1627
- }
1628
- // Normalise line endings
1629
- $source = str_replace("\r\n", "\n", $source); // Windows to Unix line endings
1630
- $source = str_replace("\r", "\n", $source); // Mac to Unix line endings
1631
- $this->source = $source;
1632
- // Variables
1633
- $buffer = &$this->buffer;
1634
- $exclusive = &$this->stateExclusive;
1635
- $state = &$this->state;
1636
- $c = $p = null;
1637
- // --
1638
- for ($i = 0, $l = strlen($source); $i < $l; $i++)
1639
- {
1640
- // Set the current Char
1641
- $c = $source[$i]; // Is faster than: $c = substr($source, $i, 1);
1642
- // Normalize and filter double whitespace characters
1643
- if ($exclusive === false)
1644
- {
1645
- if ($c === "\n" || $c === "\t")
1646
- {
1647
- $c = " ";
1648
- }
1649
- if ($c === " " && $p === " ")
1650
- {
1651
- continue;
1652
- }
1653
- }
1654
- $buffer .= $c;
1655
- // Extended processing only if the current char is a global trigger char
1656
- if (strpos($globalTriggerChars, $c) !== false)
1657
- {
1658
- // Exclusive state is set; process with the exclusive plugin
1659
- if ($exclusive)
1660
- {
1661
- $tPluginIndex = $pluginIndex[$exclusive];
1662
- if (strpos($pluginTriggerChars[$tPluginIndex], $c) !== false && ($pluginTriggerStates[$tPluginIndex] === false || strpos($pluginTriggerStates[$tPluginIndex], $state) !== false))
1663
- {
1664
- $r = $plugins[$tPluginIndex]->parse($i, $c, $p, $state);
1665
- // Return value is TRUE => continue with next char
1666
- if ($r === true)
1667
- {
1668
- continue;
1669
- }
1670
- // Return value is numeric => set new index and continue with next char
1671
- elseif ($r !== false && $r != $i)
1672
- {
1673
- $i = $r;
1674
- continue;
1675
- }
1676
- }
1677
- }
1678
- // Else iterate through the plugins
1679
- else
1680
- {
1681
- $triggerState = "|" . $state . "|";
1682
- for ($ii = 0, $ll = $pluginCount; $ii < $ll; $ii++)
1683
- {
1684
- // Only process if the current char is one of the plugin trigger chars
1685
- if (strpos($pluginTriggerChars[$ii], $c) !== false && ($pluginTriggerStates[$ii] === false || strpos($pluginTriggerStates[$ii], $triggerState) !== false))
1686
- {
1687
- // Process with the plugin
1688
- $r = $plugins[$ii]->parse($i, $c, $p, $state);
1689
- // Return value is TRUE => break the plugin loop and and continue with next char
1690
- if ($r === true)
1691
- {
1692
- break;
1693
- }
1694
- // Return value is numeric => set new index, break the plugin loop and and continue with next char
1695
- elseif ($r !== false && $r != $i)
1696
- {
1697
- $i = $r;
1698
- break;
1699
- }
1700
- }
1701
- }
1702
- }
1703
- }
1704
- $p = $c; // Set the parent char
1705
- }
1706
- return $this->tokens;
1707
- }
1708
- /**
1709
- * Remove the last state of the state stack and return the removed stack value.
1710
- *
1711
- * @return integer Removed state value
1712
- */
1713
- public function popState()
1714
- {
1715
- $r = array_pop($this->states);
1716
- $this->state = $this->states[count($this->states) - 1];
1717
- return $r;
1718
- }
1719
- /**
1720
- * Adds a new state onto the state stack.
1721
- *
1722
- * @param integer $state State to add onto the state stack.
1723
- * @return integer The index of the added state in the state stacks
1724
- */
1725
- public function pushState($state)
1726
- {
1727
- $r = array_push($this->states, $state);
1728
- $this->state = $this->states[count($this->states) - 1];
1729
- return $r;
1730
- }
1731
- /**
1732
- * Sets/restores the buffer.
1733
- *
1734
- * @param string $buffer Buffer to set
1735
- * @return void
1736
- */
1737
- public function setBuffer($buffer)
1738
- {
1739
- $this->buffer = $buffer;
1740
- }
1741
- /**
1742
- * Set the exclusive state.
1743
- *
1744
- * @param string $exclusive Exclusive state
1745
- * @return void
1746
- */
1747
- public function setExclusive($exclusive)
1748
- {
1749
- $this->stateExclusive = $exclusive;
1750
- }
1751
- /**
1752
- * Set the media types state.
1753
- *
1754
- * @param array $mediaTypes Media types state
1755
- * @return void
1756
- */
1757
- public function setMediaTypes(array $mediaTypes)
1758
- {
1759
- $this->stateMediaTypes = $mediaTypes;
1760
- }
1761
- /**
1762
- * Sets the current state in the state stack; equals to {@link CssParser::popState()} + {@link CssParser::pushState()}.
1763
- *
1764
- * @param integer $state State to set
1765
- * @return integer
1766
- */
1767
- public function setState($state)
1768
- {
1769
- $r = array_pop($this->states);
1770
- array_push($this->states, $state);
1771
- $this->state = $this->states[count($this->states) - 1];
1772
- return $r;
1773
- }
1774
- /**
1775
- * Removes the exclusive state.
1776
- *
1777
- * @return void
1778
- */
1779
- public function unsetExclusive()
1780
- {
1781
- $this->stateExclusive = false;
1782
- }
1783
- /**
1784
- * Removes the media types state.
1785
- *
1786
- * @return void
1787
- */
1788
- public function unsetMediaTypes()
1789
- {
1790
- $this->stateMediaTypes = false;
1791
- }
1792
- }
1793
-
1794
- /**
1795
- * {@link aCssFromatter Formatter} returning the CSS source in {@link http://goo.gl/j4XdU OTBS indent style} (The One True Brace Style).
1796
- *
1797
- * @package CssMin/Formatter
1798
- * @link http://code.google.com/p/cssmin/
1799
- * @author Joe Scylla <joe.scylla@gmail.com>
1800
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1801
- * @license http://opensource.org/licenses/mit-license.php MIT License
1802
- * @version 3.0.1
1803
- */
1804
- class CssOtbsFormatter extends aCssFormatter
1805
- {
1806
- /**
1807
- * Implements {@link aCssFormatter::__toString()}.
1808
- *
1809
- * @return string
1810
- */
1811
- public function __toString()
1812
- {
1813
- $r = array();
1814
- $level = 0;
1815
- for ($i = 0, $l = count($this->tokens); $i < $l; $i++)
1816
- {
1817
- $token = $this->tokens[$i];
1818
- $class = get_class($token);
1819
- $indent = str_repeat($this->indent, $level);
1820
- if ($class === "CssCommentToken")
1821
- {
1822
- $lines = array_map("trim", explode("\n", $token->Comment));
1823
- for ($ii = 0, $ll = count($lines); $ii < $ll; $ii++)
1824
- {
1825
- $r[] = $indent . (substr($lines[$ii], 0, 1) == "*" ? " " : "") . $lines[$ii];
1826
- }
1827
- }
1828
- elseif ($class === "CssAtCharsetToken")
1829
- {
1830
- $r[] = $indent . "@charset " . $token->Charset . ";";
1831
- }
1832
- elseif ($class === "CssAtFontFaceStartToken")
1833
- {
1834
- $r[] = $indent . "@font-face {";
1835
- $level++;
1836
- }
1837
- elseif ($class === "CssAtImportToken")
1838
- {
1839
- $r[] = $indent . "@import " . $token->Import . " " . implode(", ", $token->MediaTypes) . ";";
1840
- }
1841
- elseif ($class === "CssAtKeyframesStartToken")
1842
- {
1843
- $r[] = $indent . "@keyframes \"" . $token->Name . "\" {";
1844
- $level++;
1845
- }
1846
- elseif ($class === "CssAtMediaStartToken")
1847
- {
1848
- $r[] = $indent . "@media " . implode(", ", $token->MediaTypes) . " {";
1849
- $level++;
1850
- }
1851
- elseif ($class === "CssAtPageStartToken")
1852
- {
1853
- $r[] = $indent . "@page {";
1854
- $level++;
1855
- }
1856
- elseif ($class === "CssAtVariablesStartToken")
1857
- {
1858
- $r[] = $indent . "@variables " . implode(", ", $token->MediaTypes) . " {";
1859
- $level++;
1860
- }
1861
- elseif ($class === "CssRulesetStartToken" || $class === "CssAtKeyframesRulesetStartToken")
1862
- {
1863
- $r[] = $indent . implode(", ", $token->Selectors) . " {";
1864
- $level++;
1865
- }
1866
- elseif ($class == "CssAtFontFaceDeclarationToken"
1867
- || $class === "CssAtKeyframesRulesetDeclarationToken"
1868
- || $class === "CssAtPageDeclarationToken"
1869
- || $class == "CssAtVariablesDeclarationToken"
1870
- || $class === "CssRulesetDeclarationToken"
1871
- )
1872
- {
1873
- $declaration = $indent . $token->Property . ": ";
1874
- if ($this->padding)
1875
- {
1876
- $declaration = str_pad($declaration, $this->padding, " ", STR_PAD_RIGHT);
1877
- }
1878
- $r[] = $declaration . $token->Value . ($token->IsImportant ? " !important" : "") . ";";
1879
- }
1880
- elseif ($class === "CssAtFontFaceEndToken"
1881
- || $class === "CssAtMediaEndToken"
1882
- || $class === "CssAtKeyframesEndToken"
1883
- || $class === "CssAtKeyframesRulesetEndToken"
1884
- || $class === "CssAtPageEndToken"
1885
- || $class === "CssAtVariablesEndToken"
1886
- || $class === "CssRulesetEndToken"
1887
- )
1888
- {
1889
- $level--;
1890
- $r[] = str_repeat($indent, $level) . "}";
1891
- }
1892
- }
1893
- return implode("\n", $r);
1894
- }
1895
- }
1896
-
1897
- /**
1898
- * This {@link aCssToken CSS token} is a utility token that extends {@link aNullToken} and returns only a empty string.
1899
- *
1900
- * @package CssMin/Tokens
1901
- * @link http://code.google.com/p/cssmin/
1902
- * @author Joe Scylla <joe.scylla@gmail.com>
1903
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1904
- * @license http://opensource.org/licenses/mit-license.php MIT License
1905
- * @version 3.0.1
1906
- */
1907
- class CssNullToken extends aCssToken
1908
- {
1909
- /**
1910
- * Implements {@link aCssToken::__toString()}.
1911
- *
1912
- * @return string
1913
- */
1914
- public function __toString()
1915
- {
1916
- return "";
1917
- }
1918
- }
1919
-
1920
- /**
1921
- * CSS Minifier.
1922
- *
1923
- * @package CssMin/Minifier
1924
- * @link http://code.google.com/p/cssmin/
1925
- * @author Joe Scylla <joe.scylla@gmail.com>
1926
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1927
- * @license http://opensource.org/licenses/mit-license.php MIT License
1928
- * @version 3.0.1
1929
- */
1930
- class CssMinifier
1931
- {
1932
- /**
1933
- * {@link aCssMinifierFilter Filters}.
1934
- *
1935
- * @var array
1936
- */
1937
- private $filters = array();
1938
- /**
1939
- * {@link aCssMinifierPlugin Plugins}.
1940
- *
1941
- * @var array
1942
- */
1943
- private $plugins = array();
1944
- /**
1945
- * Minified source.
1946
- *
1947
- * @var string
1948
- */
1949
- private $minified = "";
1950
- /**
1951
- * Constructer.
1952
- *
1953
- * Creates instances of {@link aCssMinifierFilter filters} and {@link aCssMinifierPlugin plugins}.
1954
- *
1955
- * @param string $source CSS source [optional]
1956
- * @param array $filters Filter configuration [optional]
1957
- * @param array $plugins Plugin configuration [optional]
1958
- * @return void
1959
- */
1960
- public function __construct($source = null, array $filters = null, array $plugins = null)
1961
- {
1962
- $filters = array_merge(array
1963
- (
1964
- "ImportImports" => false,
1965
- "RemoveComments" => true,
1966
- "RemoveEmptyRulesets" => true,
1967
- "RemoveEmptyAtBlocks" => true,
1968
- "ConvertLevel3Properties" => false,
1969
- "ConvertLevel3AtKeyframes" => false,
1970
- "Variables" => true,
1971
- "RemoveLastDelarationSemiColon" => true
1972
- ), is_array($filters) ? $filters : array());
1973
- $plugins = array_merge(array
1974
- (
1975
- "Variables" => true,
1976
- "ConvertFontWeight" => false,
1977
- "ConvertHslColors" => false,
1978
- "ConvertRgbColors" => false,
1979
- "ConvertNamedColors" => false,
1980
- "CompressColorValues" => false,
1981
- "CompressUnitValues" => false,
1982
- "CompressExpressionValues" => false
1983
- ), is_array($plugins) ? $plugins : array());
1984
- // Filters
1985
- foreach ($filters as $name => $config)
1986
- {
1987
- if ($config !== false)
1988
- {
1989
- $class = "Css" . $name . "MinifierFilter";
1990
- $config = is_array($config) ? $config : array();
1991
- if (class_exists($class))
1992
- {
1993
- $this->filters[] = new $class($this, $config);
1994
- }
1995
- else
1996
- {
1997
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The filter <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));
1998
- }
1999
- }
2000
- }
2001
- // Plugins
2002
- foreach ($plugins as $name => $config)
2003
- {
2004
- if ($config !== false)
2005
- {
2006
- $class = "Css" . $name . "MinifierPlugin";
2007
- $config = is_array($config) ? $config : array();
2008
- if (class_exists($class))
2009
- {
2010
- $this->plugins[] = new $class($this, $config);
2011
- }
2012
- else
2013
- {
2014
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));
2015
- }
2016
- }
2017
- }
2018
- // --
2019
- if (!is_null($source))
2020
- {
2021
- $this->minify($source);
2022
- }
2023
- }
2024
- /**
2025
- * Returns the minified Source.
2026
- *
2027
- * @return string
2028
- */
2029
- public function getMinified()
2030
- {
2031
- return $this->minified;
2032
- }
2033
- /**
2034
- * Returns a plugin by class name.
2035
- *
2036
- * @param string $name Class name of the plugin
2037
- * @return aCssMinifierPlugin
2038
- */
2039
- public function getPlugin($class)
2040
- {
2041
- static $index = null;
2042
- if (is_null($index))
2043
- {
2044
- $index = array();
2045
- for ($i = 0, $l = count($this->plugins); $i < $l; $i++)
2046
- {
2047
- $index[get_class($this->plugins[$i])] = $i;
2048
- }
2049
- }
2050
- return isset($index[$class]) ? $this->plugins[$index[$class]] : false;
2051
- }
2052
- /**
2053
- * Minifies the CSS source.
2054
- *
2055
- * @param string $source CSS source
2056
- * @return string
2057
- */
2058
- public function minify($source)
2059
- {
2060
- // Variables
2061
- $r = "";
2062
- $parser = new CssParser($source);
2063
- $tokens = $parser->getTokens();
2064
- $filters = $this->filters;
2065
- $filterCount = count($this->filters);
2066
- $plugins = $this->plugins;
2067
- $pluginCount = count($plugins);
2068
- $pluginIndex = array();
2069
- $pluginTriggerTokens = array();
2070
- $globalTriggerTokens = array();
2071
- for ($i = 0, $l = count($plugins); $i < $l; $i++)
2072
- {
2073
- $tPluginClassName = get_class($plugins[$i]);
2074
- $pluginTriggerTokens[$i] = $plugins[$i]->getTriggerTokens();
2075
- foreach ($pluginTriggerTokens[$i] as $v)
2076
- {
2077
- if (!in_array($v, $globalTriggerTokens))
2078
- {
2079
- $globalTriggerTokens[] = $v;
2080
- }
2081
- }
2082
- $pluginTriggerTokens[$i] = "|" . implode("|", $pluginTriggerTokens[$i]) . "|";
2083
- $pluginIndex[$tPluginClassName] = $i;
2084
- }
2085
- $globalTriggerTokens = "|" . implode("|", $globalTriggerTokens) . "|";
2086
- /*
2087
- * Apply filters
2088
- */
2089
- for($i = 0; $i < $filterCount; $i++)
2090
- {
2091
- // Apply the filter; if the return value is larger than 0...
2092
- if ($filters[$i]->apply($tokens) > 0)
2093
- {
2094
- // ...then filter null values and rebuild the token array
2095
- $tokens = array_values(array_filter($tokens));
2096
- }
2097
- }
2098
- $tokenCount = count($tokens);
2099
- /*
2100
- * Apply plugins
2101
- */
2102
- for($i = 0; $i < $tokenCount; $i++)
2103
- {
2104
- $triggerToken = "|" . get_class($tokens[$i]) . "|";
2105
- if (strpos($globalTriggerTokens, $triggerToken) !== false)
2106
- {
2107
- for($ii = 0; $ii < $pluginCount; $ii++)
2108
- {
2109
- if (strpos($pluginTriggerTokens[$ii], $triggerToken) !== false || $pluginTriggerTokens[$ii] === false)
2110
- {
2111
- // Apply the plugin; if the return value is TRUE continue to the next token
2112
- if ($plugins[$ii]->apply($tokens[$i]) === true)
2113
- {
2114
- continue 2;
2115
- }
2116
- }
2117
- }
2118
- }
2119
- }
2120
- // Stringify the tokens
2121
- for($i = 0; $i < $tokenCount; $i++)
2122
- {
2123
- $r .= (string) $tokens[$i];
2124
- }
2125
- $this->minified = $r;
2126
- return $r;
2127
- }
2128
- }
2129
-
2130
- /**
2131
- * CssMin - A (simple) css minifier with benefits
2132
- *
2133
- * --
2134
- * Copyright (c) 2011 Joe Scylla <joe.scylla@gmail.com>
2135
- *
2136
- * Permission is hereby granted, free of charge, to any person obtaining a copy
2137
- * of this software and associated documentation files (the "Software"), to deal
2138
- * in the Software without restriction, including without limitation the rights
2139
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2140
- * copies of the Software, and to permit persons to whom the Software is
2141
- * furnished to do so, subject to the following conditions:
2142
- *
2143
- * The above copyright notice and this permission notice shall be included in
2144
- * all copies or substantial portions of the Software.
2145
- *
2146
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2147
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2148
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2149
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2150
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2151
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2152
- * THE SOFTWARE.
2153
- * --
2154
- *
2155
- * @package CssMin
2156
- * @link http://code.google.com/p/cssmin/
2157
- * @author Joe Scylla <joe.scylla@gmail.com>
2158
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2159
- * @license http://opensource.org/licenses/mit-license.php MIT License
2160
- * @version 3.0.1
2161
- */
2162
- class CssMin
2163
- {
2164
- /**
2165
- * Index of classes
2166
- *
2167
- * @var array
2168
- */
2169
- private static $classIndex = array();
2170
- /**
2171
- * Parse/minify errors
2172
- *
2173
- * @var array
2174
- */
2175
- private static $errors = array();
2176
- /**
2177
- * Verbose output.
2178
- *
2179
- * @var boolean
2180
- */
2181
- private static $isVerbose = false;
2182
- /**
2183
- * {@link http://goo.gl/JrW54 Autoload} function of CssMin.
2184
- *
2185
- * @param string $class Name of the class
2186
- * @return void
2187
- */
2188
- public static function autoload($class)
2189
- {
2190
- if (isset(self::$classIndex[$class]))
2191
- {
2192
- require(self::$classIndex[$class]);
2193
- }
2194
- }
2195
- /**
2196
- * Return errors
2197
- *
2198
- * @return array of {CssError}.
2199
- */
2200
- public static function getErrors()
2201
- {
2202
- return self::$errors;
2203
- }
2204
- /**
2205
- * Returns if there were errors.
2206
- *
2207
- * @return boolean
2208
- */
2209
- public static function hasErrors()
2210
- {
2211
- return count(self::$errors) > 0;
2212
- }
2213
- /**
2214
- * Initialises CssMin.
2215
- *
2216
- * @return void
2217
- */
2218
- public static function initialise()
2219
- {
2220
- // Create the class index for autoloading or including
2221
- $paths = array(dirname(__FILE__));
2222
- while (list($i, $path) = each($paths))
2223
- {
2224
- $subDirectorys = glob($path . "*", GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT);
2225
- if (is_array($subDirectorys))
2226
- {
2227
- foreach ($subDirectorys as $subDirectory)
2228
- {
2229
- $paths[] = $subDirectory;
2230
- }
2231
- }
2232
- $files = glob($path . "*.php", 0);
2233
- if (is_array($files))
2234
- {
2235
- foreach ($files as $file)
2236
- {
2237
- $class = substr(basename($file), 0, -4);
2238
- self::$classIndex[$class] = $file;
2239
- }
2240
- }
2241
- }
2242
- krsort(self::$classIndex);
2243
- // Only use autoloading if spl_autoload_register() is available and no __autoload() is defined (because
2244
- // __autoload() breaks if spl_autoload_register() is used.
2245
- if (function_exists("spl_autoload_register") && !is_callable("__autoload"))
2246
- {
2247
- spl_autoload_register(array(__CLASS__, "autoload"));
2248
- }
2249
- // Otherwise include all class files
2250
- else
2251
- {
2252
- foreach (self::$classIndex as $class => $file)
2253
- {
2254
- if (!class_exists($class))
2255
- {
2256
- require_once($file);
2257
- }
2258
- }
2259
- }
2260
- }
2261
- /**
2262
- * Minifies CSS source.
2263
- *
2264
- * @param string $source CSS source
2265
- * @param array $filters Filter configuration [optional]
2266
- * @param array $plugins Plugin configuration [optional]
2267
- * @return string Minified CSS
2268
- */
2269
- public static function minify($source, array $filters = null, array $plugins = null)
2270
- {
2271
- self::$errors = array();
2272
- $minifier = new CssMinifier($source, $filters, $plugins);
2273
- return $minifier->getMinified();
2274
- }
2275
- /**
2276
- * Parse the CSS source.
2277
- *
2278
- * @param string $source CSS source
2279
- * @param array $plugins Plugin configuration [optional]
2280
- * @return array Array of aCssToken
2281
- */
2282
- public static function parse($source, array $plugins = null)
2283
- {
2284
- self::$errors = array();
2285
- $parser = new CssParser($source, $plugins);
2286
- return $parser->getTokens();
2287
- }
2288
- /**
2289
- * --
2290
- *
2291
- * @param boolean $to
2292
- * @return boolean
2293
- */
2294
- public static function setVerbose($to)
2295
- {
2296
- self::$isVerbose = (boolean) $to;
2297
- return self::$isVerbose;
2298
- }
2299
- /**
2300
- * --
2301
- *
2302
- * @param CssError $error
2303
- * @return void
2304
- */
2305
- public static function triggerError(CssError $error)
2306
- {
2307
- self::$errors[] = $error;
2308
- if (self::$isVerbose)
2309
- {
2310
- trigger_error((string) $error, E_USER_WARNING);
2311
- }
2312
- }
2313
- }
2314
- // Initialises CssMin
2315
- CssMin::initialise();
2316
-
2317
- /**
2318
- * This {@link aCssMinifierFilter minifier filter} import external css files defined with the @import at-rule into the
2319
- * current stylesheet.
2320
- *
2321
- * @package CssMin/Minifier/Filters
2322
- * @link http://code.google.com/p/cssmin/
2323
- * @author Joe Scylla <joe.scylla@gmail.com>
2324
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2325
- * @license http://opensource.org/licenses/mit-license.php MIT License
2326
- * @version 3.0.1
2327
- */
2328
- class CssImportImportsMinifierFilter extends aCssMinifierFilter
2329
- {
2330
- /**
2331
- * Array with already imported external stylesheets.
2332
- *
2333
- * @var array
2334
- */
2335
- private $imported = array();
2336
- /**
2337
- * Implements {@link aCssMinifierFilter::filter()}.
2338
- *
2339
- * @param array $tokens Array of objects of type aCssToken
2340
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
2341
- */
2342
- public function apply(array &$tokens)
2343
- {
2344
- if (!isset($this->configuration["BasePath"]) || !is_dir($this->configuration["BasePath"]))
2345
- {
2346
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Base path <code>" . ($this->configuration["BasePath"] ? $this->configuration["BasePath"] : "null"). "</code> is not a directory"));
2347
- return 0;
2348
- }
2349
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
2350
- {
2351
- if (get_class($tokens[$i]) === "CssAtImportToken")
2352
- {
2353
- $import = $this->configuration["BasePath"] . "/" . $tokens[$i]->Import;
2354
- // Import file was not found/is not a file
2355
- if (!is_file($import))
2356
- {
2357
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Import file <code>" . $import. "</code> was not found.", (string) $tokens[$i]));
2358
- }
2359
- // Import file already imported; remove this @import at-rule to prevent recursions
2360
- elseif (in_array($import, $this->imported))
2361
- {
2362
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Import file <code>" . $import. "</code> was already imported.", (string) $tokens[$i]));
2363
- $tokens[$i] = null;
2364
- }
2365
- else
2366
- {
2367
- $this->imported[] = $import;
2368
- $parser = new CssParser(file_get_contents($import));
2369
- $import = $parser->getTokens();
2370
- // The @import at-rule has media types defined requiring special handling
2371
- if (count($tokens[$i]->MediaTypes) > 0 && !(count($tokens[$i]->MediaTypes) == 1 && $tokens[$i]->MediaTypes[0] == "all"))
2372
- {
2373
- $blocks = array();
2374
- /*
2375
- * Filter or set media types of @import at-rule or remove the @import at-rule if no media type is matching the parent @import at-rule
2376
- */
2377
- for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2378
- {
2379
- if (get_class($import[$ii]) === "CssAtImportToken")
2380
- {
2381
- // @import at-rule defines no media type or only the "all" media type; set the media types to the one defined in the parent @import at-rule
2382
- if (count($import[$ii]->MediaTypes) == 0 || (count($import[$ii]->MediaTypes) == 1 && $import[$ii]->MediaTypes[0] == "all"))
2383
- {
2384
- $import[$ii]->MediaTypes = $tokens[$i]->MediaTypes;
2385
- }
2386
- // @import at-rule defineds one or more media types; filter out media types not matching with the parent @import at-rule
2387
- elseif (count($import[$ii]->MediaTypes > 0))
2388
- {
2389
- foreach ($import[$ii]->MediaTypes as $index => $mediaType)
2390
- {
2391
- if (!in_array($mediaType, $tokens[$i]->MediaTypes))
2392
- {
2393
- unset($import[$ii]->MediaTypes[$index]);
2394
- }
2395
- }
2396
- $import[$ii]->MediaTypes = array_values($import[$ii]->MediaTypes);
2397
- // If there are no media types left in the @import at-rule remove the @import at-rule
2398
- if (count($import[$ii]->MediaTypes) == 0)
2399
- {
2400
- $import[$ii] = null;
2401
- }
2402
- }
2403
- }
2404
- }
2405
- /*
2406
- * Remove media types of @media at-rule block not defined in the @import at-rule
2407
- */
2408
- for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2409
- {
2410
- if (get_class($import[$ii]) === "CssAtMediaStartToken")
2411
- {
2412
- foreach ($import[$ii]->MediaTypes as $index => $mediaType)
2413
- {
2414
- if (!in_array($mediaType, $tokens[$i]->MediaTypes))
2415
- {
2416
- unset($import[$ii]->MediaTypes[$index]);
2417
- }
2418
- $import[$ii]->MediaTypes = array_values($import[$ii]->MediaTypes);
2419
- }
2420
- }
2421
- }
2422
- /*
2423
- * If no media types left of the @media at-rule block remove the complete block
2424
- */
2425
- for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2426
- {
2427
- if (get_class($import[$ii]) === "CssAtMediaStartToken")
2428
- {
2429
- if (count($import[$ii]->MediaTypes) === 0)
2430
- {
2431
- for ($iii = $ii; $iii < $ll; $iii++)
2432
- {
2433
- if (get_class($import[$iii]) === "CssAtMediaEndToken")
2434
- {
2435
- break;
2436
- }
2437
- }
2438
- if (get_class($import[$iii]) === "CssAtMediaEndToken")
2439
- {
2440
- array_splice($import, $ii, $iii - $ii + 1, array());
2441
- $ll = count($import);
2442
- }
2443
- }
2444
- }
2445
- }
2446
- /*
2447
- * If the media types of the @media at-rule equals the media types defined in the @import
2448
- * at-rule remove the CssAtMediaStartToken and CssAtMediaEndToken token
2449
- */
2450
- for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2451
- {
2452
- if (get_class($import[$ii]) === "CssAtMediaStartToken" && count(array_diff($tokens[$i]->MediaTypes, $import[$ii]->MediaTypes)) === 0)
2453
- {
2454
- for ($iii = $ii; $iii < $ll; $iii++)
2455
- {
2456
- if (get_class($import[$iii]) == "CssAtMediaEndToken")
2457
- {
2458
- break;
2459
- }
2460
- }
2461
- if (get_class($import[$iii]) == "CssAtMediaEndToken")
2462
- {
2463
- unset($import[$ii]);
2464
- unset($import[$iii]);
2465
- $import = array_values($import);
2466
- $ll = count($import);
2467
- }
2468
- }
2469
- }
2470
- /**
2471
- * Extract CssAtImportToken and CssAtCharsetToken tokens
2472
- */
2473
- for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2474
- {
2475
- $class = get_class($import[$ii]);
2476
- if ($class === "CssAtImportToken" || $class === "CssAtCharsetToken")
2477
- {
2478
- $blocks = array_merge($blocks, array_splice($import, $ii, 1, array()));
2479
- $ll = count($import);
2480
- }
2481
- }
2482
- /*
2483
- * Extract the @font-face, @media and @page at-rule block
2484
- */
2485
- for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2486
- {
2487
- $class = get_class($import[$ii]);
2488
- if ($class === "CssAtFontFaceStartToken" || $class === "CssAtMediaStartToken" || $class === "CssAtPageStartToken" || $class === "CssAtVariablesStartToken")
2489
- {
2490
- for ($iii = $ii; $iii < $ll; $iii++)
2491
- {
2492
- $class = get_class($import[$iii]);
2493
- if ($class === "CssAtFontFaceEndToken" || $class === "CssAtMediaEndToken" || $class === "CssAtPageEndToken" || $class === "CssAtVariablesEndToken")
2494
- {
2495
- break;
2496
- }
2497
- }
2498
- $class = get_class($import[$iii]);
2499
- if (isset($import[$iii]) && ($class === "CssAtFontFaceEndToken" || $class === "CssAtMediaEndToken" || $class === "CssAtPageEndToken" || $class === "CssAtVariablesEndToken"))
2500
- {
2501
- $blocks = array_merge($blocks, array_splice($import, $ii, $iii - $ii + 1, array()));
2502
- $ll = count($import);
2503
- }
2504
- }
2505
- }
2506
- // Create the import array with extracted tokens and the rulesets wrapped into a @media at-rule block
2507
- $import = array_merge($blocks, array(new CssAtMediaStartToken($tokens[$i]->MediaTypes)), $import, array(new CssAtMediaEndToken()));
2508
- }
2509
- // Insert the imported tokens
2510
- array_splice($tokens, $i, 1, $import);
2511
- // Modify parameters of the for-loop
2512
- $i--;
2513
- $l = count($tokens);
2514
- }
2515
- }
2516
- }
2517
- }
2518
- }
2519
-
2520
- /**
2521
- * {@link aCssParserPlugin Parser plugin} for preserve parsing expression() declaration values.
2522
- *
2523
- * This plugin return no {@link aCssToken CssToken} but ensures that expression() declaration values will get parsed
2524
- * properly.
2525
- *
2526
- * @package CssMin/Parser/Plugins
2527
- * @link http://code.google.com/p/cssmin/
2528
- * @author Joe Scylla <joe.scylla@gmail.com>
2529
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2530
- * @license http://opensource.org/licenses/mit-license.php MIT License
2531
- * @version 3.0.1
2532
- */
2533
- class CssExpressionParserPlugin extends aCssParserPlugin
2534
- {
2535
- /**
2536
- * Count of left braces.
2537
- *
2538
- * @var integer
2539
- */
2540
- private $leftBraces = 0;
2541
- /**
2542
- * Count of right braces.
2543
- *
2544
- * @var integer
2545
- */
2546
- private $rightBraces = 0;
2547
- /**
2548
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
2549
- *
2550
- * @return array
2551
- */
2552
- public function getTriggerChars()
2553
- {
2554
- return array("(", ")", ";", "}");
2555
- }
2556
- /**
2557
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
2558
- *
2559
- * @return array
2560
- */
2561
- public function getTriggerStates()
2562
- {
2563
- return false;
2564
- }
2565
- /**
2566
- * Implements {@link aCssParserPlugin::parse()}.
2567
- *
2568
- * @param integer $index Current index
2569
- * @param string $char Current char
2570
- * @param string $previousChar Previous char
2571
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
2572
- */
2573
- public function parse($index, $char, $previousChar, $state)
2574
- {
2575
- // Start of expression
2576
- if ($char === "(" && strtolower(substr($this->parser->getSource(), $index - 10, 11)) === "expression(" && $state !== "T_EXPRESSION")
2577
- {
2578
- $this->parser->pushState("T_EXPRESSION");
2579
- $this->leftBraces++;
2580
- }
2581
- // Count left braces
2582
- elseif ($char === "(" && $state === "T_EXPRESSION")
2583
- {
2584
- $this->leftBraces++;
2585
- }
2586
- // Count right braces
2587
- elseif ($char === ")" && $state === "T_EXPRESSION")
2588
- {
2589
- $this->rightBraces++;
2590
- }
2591
- // Possible end of expression; if left and right braces are equal the expressen ends
2592
- elseif (($char === ";" || $char === "}") && $state === "T_EXPRESSION" && $this->leftBraces === $this->rightBraces)
2593
- {
2594
- $this->leftBraces = $this->rightBraces = 0;
2595
- $this->parser->popState();
2596
- return $index - 1;
2597
- }
2598
- else
2599
- {
2600
- return false;
2601
- }
2602
- return true;
2603
- }
2604
- }
2605
-
2606
- /**
2607
- * CSS Error.
2608
- *
2609
- * @package CssMin
2610
- * @link http://code.google.com/p/cssmin/
2611
- * @author Joe Scylla <joe.scylla@gmail.com>
2612
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2613
- * @license http://opensource.org/licenses/mit-license.php MIT License
2614
- * @version 3.0.1
2615
- */
2616
- class CssError
2617
- {
2618
- /**
2619
- * File.
2620
- *
2621
- * @var string
2622
- */
2623
- public $File = "";
2624
- /**
2625
- * Line.
2626
- *
2627
- * @var integer
2628
- */
2629
- public $Line = 0;
2630
- /**
2631
- * Error message.
2632
- *
2633
- * @var string
2634
- */
2635
- public $Message = "";
2636
- /**
2637
- * Source.
2638
- *
2639
- * @var string
2640
- */
2641
- public $Source = "";
2642
- /**
2643
- * Constructor triggering the error.
2644
- *
2645
- * @param string $message Error message
2646
- * @param string $source Corresponding line [optional]
2647
- * @return void
2648
- */
2649
- public function __construct($file, $line, $message, $source = "")
2650
- {
2651
- $this->File = $file;
2652
- $this->Line = $line;
2653
- $this->Message = $message;
2654
- $this->Source = $source;
2655
- }
2656
- /**
2657
- * Returns the error as formatted string.
2658
- *
2659
- * @return string
2660
- */
2661
- public function __toString()
2662
- {
2663
- return $this->Message . ($this->Source ? ": <br /><code>" . $this->Source . "</code>": "") . "<br />in file " . $this->File . " at line " . $this->Line;
2664
- }
2665
- }
2666
-
2667
- /**
2668
- * This {@link aCssMinifierPlugin} will convert a color value in rgb notation to hexadecimal notation.
2669
- *
2670
- * Example:
2671
- * <code>
2672
- * color: rgb(200,60%,5);
2673
- * </code>
2674
- *
2675
- * Will get converted to:
2676
- * <code>
2677
- * color:#c89905;
2678
- * </code>
2679
- *
2680
- * @package CssMin/Minifier/Plugins
2681
- * @link http://code.google.com/p/cssmin/
2682
- * @author Joe Scylla <joe.scylla@gmail.com>
2683
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2684
- * @license http://opensource.org/licenses/mit-license.php MIT License
2685
- * @version 3.0.1
2686
- */
2687
- class CssConvertRgbColorsMinifierPlugin extends aCssMinifierPlugin
2688
- {
2689
- /**
2690
- * Regular expression matching the value.
2691
- *
2692
- * @var string
2693
- */
2694
- private $reMatch = "/rgb\s*\(\s*([0-9%]+)\s*,\s*([0-9%]+)\s*,\s*([0-9%]+)\s*\)/iS";
2695
- /**
2696
- * Implements {@link aCssMinifierPlugin::minify()}.
2697
- *
2698
- * @param aCssToken $token Token to process
2699
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
2700
- */
2701
- public function apply(aCssToken &$token)
2702
- {
2703
- if (stripos($token->Value, "rgb") !== false && preg_match($this->reMatch, $token->Value, $m))
2704
- {
2705
- for ($i = 1, $l = count($m); $i < $l; $i++)
2706
- {
2707
- if (strpos("%", $m[$i]) !== false)
2708
- {
2709
- $m[$i] = substr($m[$i], 0, -1);
2710
- $m[$i] = (int) (256 * ($m[$i] / 100));
2711
- }
2712
- $m[$i] = str_pad(dechex($m[$i]), 2, "0", STR_PAD_LEFT);
2713
- }
2714
- $token->Value = str_replace($m[0], "#" . $m[1] . $m[2] . $m[3], $token->Value);
2715
- }
2716
- return false;
2717
- }
2718
- /**
2719
- * Implements {@link aMinifierPlugin::getTriggerTokens()}
2720
- *
2721
- * @return array
2722
- */
2723
- public function getTriggerTokens()
2724
- {
2725
- return array
2726
- (
2727
- "CssAtFontFaceDeclarationToken",
2728
- "CssAtPageDeclarationToken",
2729
- "CssRulesetDeclarationToken"
2730
- );
2731
- }
2732
- }
2733
-
2734
- /**
2735
- * This {@link aCssMinifierPlugin} will convert named color values to hexadecimal notation.
2736
- *
2737
- * Example:
2738
- * <code>
2739
- * color: black;
2740
- * border: 1px solid indigo;
2741
- * </code>
2742
- *
2743
- * Will get converted to:
2744
- * <code>
2745
- * color:#000;
2746
- * border:1px solid #4b0082;
2747
- * </code>
2748
- *
2749
- * @package CssMin/Minifier/Plugins
2750
- * @link http://code.google.com/p/cssmin/
2751
- * @author Joe Scylla <joe.scylla@gmail.com>
2752
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2753
- * @license http://opensource.org/licenses/mit-license.php MIT License
2754
- * @version 3.0.1
2755
- */
2756
- class CssConvertNamedColorsMinifierPlugin extends aCssMinifierPlugin
2757
- {
2758
-
2759
- /**
2760
- * Regular expression matching the value.
2761
- *
2762
- * @var string
2763
- */
2764
- private $reMatch = null;
2765
- /**
2766
- * Regular expression replacing the value.
2767
- *
2768
- * @var string
2769
- */
2770
- private $reReplace = "\"\${1}\" . \$this->transformation[strtolower(\"\${2}\")] . \"\${3}\"";
2771
- /**
2772
- * Transformation table used by the {@link CssConvertNamedColorsMinifierPlugin::$reReplace replace regular expression}.
2773
- *
2774
- * @var array
2775
- */
2776
- private $transformation = array
2777
- (
2778
- "aliceblue" => "#f0f8ff",
2779
- "antiquewhite" => "#faebd7",
2780
- "aqua" => "#0ff",
2781
- "aquamarine" => "#7fffd4",
2782
- "azure" => "#f0ffff",
2783
- "beige" => "#f5f5dc",
2784
- "black" => "#000",
2785
- "blue" => "#00f",
2786
- "blueviolet" => "#8a2be2",
2787
- "brown" => "#a52a2a",
2788
- "burlywood" => "#deb887",
2789
- "cadetblue" => "#5f9ea0",
2790
- "chartreuse" => "#7fff00",
2791
- "chocolate" => "#d2691e",
2792
- "coral" => "#ff7f50",
2793
- "cornflowerblue" => "#6495ed",
2794
- "cornsilk" => "#fff8dc",
2795
- "crimson" => "#dc143c",
2796
- "darkblue" => "#00008b",
2797
- "darkcyan" => "#008b8b",
2798
- "darkgoldenrod" => "#b8860b",
2799
- "darkgray" => "#a9a9a9",
2800
- "darkgreen" => "#006400",
2801
- "darkkhaki" => "#bdb76b",
2802
- "darkmagenta" => "#8b008b",
2803
- "darkolivegreen" => "#556b2f",
2804
- "darkorange" => "#ff8c00",
2805
- "darkorchid" => "#9932cc",
2806
- "darkred" => "#8b0000",
2807
- "darksalmon" => "#e9967a",
2808
- "darkseagreen" => "#8fbc8f",
2809
- "darkslateblue" => "#483d8b",
2810
- "darkslategray" => "#2f4f4f",
2811
- "darkturquoise" => "#00ced1",
2812
- "darkviolet" => "#9400d3",
2813
- "deeppink" => "#ff1493",
2814
- "deepskyblue" => "#00bfff",
2815
- "dimgray" => "#696969",
2816
- "dodgerblue" => "#1e90ff",
2817
- "firebrick" => "#b22222",
2818
- "floralwhite" => "#fffaf0",
2819
- "forestgreen" => "#228b22",
2820
- "fuchsia" => "#f0f",
2821
- "gainsboro" => "#dcdcdc",
2822
- "ghostwhite" => "#f8f8ff",
2823
- "gold" => "#ffd700",
2824
- "goldenrod" => "#daa520",
2825
- "gray" => "#808080",
2826
- "green" => "#008000",
2827
- "greenyellow" => "#adff2f",
2828
- "honeydew" => "#f0fff0",
2829
- "hotpink" => "#ff69b4",
2830
- "indianred" => "#cd5c5c",
2831
- "indigo" => "#4b0082",
2832
- "ivory" => "#fffff0",
2833
- "khaki" => "#f0e68c",
2834
- "lavender" => "#e6e6fa",
2835
- "lavenderblush" => "#fff0f5",
2836
- "lawngreen" => "#7cfc00",
2837
- "lemonchiffon" => "#fffacd",
2838
- "lightblue" => "#add8e6",
2839
- "lightcoral" => "#f08080",
2840
- "lightcyan" => "#e0ffff",
2841
- "lightgoldenrodyellow" => "#fafad2",
2842
- "lightgreen" => "#90ee90",
2843
- "lightgrey" => "#d3d3d3",
2844
- "lightpink" => "#ffb6c1",
2845
- "lightsalmon" => "#ffa07a",
2846
- "lightseagreen" => "#20b2aa",
2847
- "lightskyblue" => "#87cefa",
2848
- "lightslategray" => "#789",
2849
- "lightsteelblue" => "#b0c4de",
2850
- "lightyellow" => "#ffffe0",
2851
- "lime" => "#0f0",
2852
- "limegreen" => "#32cd32",
2853
- "linen" => "#faf0e6",
2854
- "maroon" => "#800000",
2855
- "mediumaquamarine" => "#66cdaa",
2856
- "mediumblue" => "#0000cd",
2857
- "mediumorchid" => "#ba55d3",
2858
- "mediumpurple" => "#9370db",
2859
- "mediumseagreen" => "#3cb371",
2860
- "mediumslateblue" => "#7b68ee",
2861
- "mediumspringgreen" => "#00fa9a",
2862
- "mediumturquoise" => "#48d1cc",
2863
- "mediumvioletred" => "#c71585",
2864
- "midnightblue" => "#191970",
2865
- "mintcream" => "#f5fffa",
2866
- "mistyrose" => "#ffe4e1",
2867
- "moccasin" => "#ffe4b5",
2868
- "navajowhite" => "#ffdead",
2869
- "navy" => "#000080",
2870
- "oldlace" => "#fdf5e6",
2871
- "olive" => "#808000",
2872
- "olivedrab" => "#6b8e23",
2873
- "orange" => "#ffa500",
2874
- "orangered" => "#ff4500",
2875
- "orchid" => "#da70d6",
2876
- "palegoldenrod" => "#eee8aa",
2877
- "palegreen" => "#98fb98",
2878
- "paleturquoise" => "#afeeee",
2879
- "palevioletred" => "#db7093",
2880
- "papayawhip" => "#ffefd5",
2881
- "peachpuff" => "#ffdab9",
2882
- "peru" => "#cd853f",
2883
- "pink" => "#ffc0cb",
2884
- "plum" => "#dda0dd",
2885
- "powderblue" => "#b0e0e6",
2886
- "purple" => "#800080",
2887
- "red" => "#f00",
2888
- "rosybrown" => "#bc8f8f",
2889
- "royalblue" => "#4169e1",
2890
- "saddlebrown" => "#8b4513",
2891
- "salmon" => "#fa8072",
2892
- "sandybrown" => "#f4a460",
2893
- "seagreen" => "#2e8b57",
2894
- "seashell" => "#fff5ee",
2895
- "sienna" => "#a0522d",
2896
- "silver" => "#c0c0c0",
2897
- "skyblue" => "#87ceeb",
2898
- "slateblue" => "#6a5acd",
2899
- "slategray" => "#708090",
2900
- "snow" => "#fffafa",
2901
- "springgreen" => "#00ff7f",
2902
- "steelblue" => "#4682b4",
2903
- "tan" => "#d2b48c",
2904
- "teal" => "#008080",
2905
- "thistle" => "#d8bfd8",
2906
- "tomato" => "#ff6347",
2907
- "turquoise" => "#40e0d0",
2908
- "violet" => "#ee82ee",
2909
- "wheat" => "#f5deb3",
2910
- "white" => "#fff",
2911
- "whitesmoke" => "#f5f5f5",
2912
- "yellow" => "#ff0",
2913
- "yellowgreen" => "#9acd32"
2914
- );
2915
- /**
2916
- * Overwrites {@link aCssMinifierPlugin::__construct()}.
2917
- *
2918
- * The constructor will create the {@link CssConvertNamedColorsMinifierPlugin::$reReplace replace regular expression}
2919
- * based on the {@link CssConvertNamedColorsMinifierPlugin::$transformation transformation table}.
2920
- *
2921
- * @param CssMinifier $minifier The CssMinifier object of this plugin.
2922
- * @param array $configuration Plugin configuration [optional]
2923
- * @return void
2924
- */
2925
- public function __construct(CssMinifier $minifier, array $configuration = array())
2926
- {
2927
- $this->reMatch = "/(^|\s)+(" . implode("|", array_keys($this->transformation)) . ")(\s|$)+/eiS";
2928
- parent::__construct($minifier, $configuration);
2929
- }
2930
- /**
2931
- * Implements {@link aCssMinifierPlugin::minify()}.
2932
- *
2933
- * @param aCssToken $token Token to process
2934
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
2935
- */
2936
- public function apply(aCssToken &$token)
2937
- {
2938
- $lcValue = strtolower($token->Value);
2939
- // Declaration value equals a value in the transformation table => simple replace
2940
- if (isset($this->transformation[$lcValue]))
2941
- {
2942
- $token->Value = $this->transformation[$lcValue];
2943
- }
2944
- // Declaration value contains a value in the transformation table => regular expression replace
2945
- elseif (preg_match($this->reMatch, $token->Value))
2946
- {
2947
- $token->Value = preg_replace($this->reMatch, $this->reReplace, $token->Value);
2948
- }
2949
- return false;
2950
- }
2951
- /**
2952
- * Implements {@link aMinifierPlugin::getTriggerTokens()}
2953
- *
2954
- * @return array
2955
- */
2956
- public function getTriggerTokens()
2957
- {
2958
- return array
2959
- (
2960
- "CssAtFontFaceDeclarationToken",
2961
- "CssAtPageDeclarationToken",
2962
- "CssRulesetDeclarationToken"
2963
- );
2964
- }
2965
- }
2966
-
2967
- /**
2968
- * This {@link aCssMinifierFilter minifier filter} triggers on CSS Level 3 properties and will add declaration tokens
2969
- * with browser-specific properties.
2970
- *
2971
- * @package CssMin/Minifier/Filters
2972
- * @link http://code.google.com/p/cssmin/
2973
- * @author Joe Scylla <joe.scylla@gmail.com>
2974
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2975
- * @license http://opensource.org/licenses/mit-license.php MIT License
2976
- * @version 3.0.1
2977
- */
2978
- class CssConvertLevel3PropertiesMinifierFilter extends aCssMinifierFilter
2979
- {
2980
- /**
2981
- * Css property transformations table. Used to convert CSS3 and proprietary properties to the browser-specific
2982
- * counterparts.
2983
- *
2984
- * @var array
2985
- */
2986
- private $transformations = array
2987
- (
2988
- // Property Array(Mozilla, Webkit, Opera, Internet Explorer); NULL values are placeholders and will get ignored
2989
- "animation" => array(null, "-webkit-animation", null, null),
2990
- "animation-delay" => array(null, "-webkit-animation-delay", null, null),
2991
- "animation-direction" => array(null, "-webkit-animation-direction", null, null),
2992
- "animation-duration" => array(null, "-webkit-animation-duration", null, null),
2993
- "animation-fill-mode" => array(null, "-webkit-animation-fill-mode", null, null),
2994
- "animation-iteration-count" => array(null, "-webkit-animation-iteration-count", null, null),
2995
- "animation-name" => array(null, "-webkit-animation-name", null, null),
2996
- "animation-play-state" => array(null, "-webkit-animation-play-state", null, null),
2997
- "animation-timing-function" => array(null, "-webkit-animation-timing-function", null, null),
2998
- "appearance" => array("-moz-appearance", "-webkit-appearance", null, null),
2999
- "backface-visibility" => array(null, "-webkit-backface-visibility", null, null),
3000
- "background-clip" => array(null, "-webkit-background-clip", null, null),
3001
- "background-composite" => array(null, "-webkit-background-composite", null, null),
3002
- "background-inline-policy" => array("-moz-background-inline-policy", null, null, null),
3003
- "background-origin" => array(null, "-webkit-background-origin", null, null),
3004
- "background-position-x" => array(null, null, null, "-ms-background-position-x"),
3005
- "background-position-y" => array(null, null, null, "-ms-background-position-y"),
3006
- "background-size" => array(null, "-webkit-background-size", null, null),
3007
- "behavior" => array(null, null, null, "-ms-behavior"),
3008
- "binding" => array("-moz-binding", null, null, null),
3009
- "border-after" => array(null, "-webkit-border-after", null, null),
3010
- "border-after-color" => array(null, "-webkit-border-after-color", null, null),
3011
- "border-after-style" => array(null, "-webkit-border-after-style", null, null),
3012
- "border-after-width" => array(null, "-webkit-border-after-width", null, null),
3013
- "border-before" => array(null, "-webkit-border-before", null, null),
3014
- "border-before-color" => array(null, "-webkit-border-before-color", null, null),
3015
- "border-before-style" => array(null, "-webkit-border-before-style", null, null),
3016
- "border-before-width" => array(null, "-webkit-border-before-width", null, null),
3017
- "border-border-bottom-colors" => array("-moz-border-bottom-colors", null, null, null),
3018
- "border-bottom-left-radius" => array("-moz-border-radius-bottomleft", "-webkit-border-bottom-left-radius", null, null),
3019
- "border-bottom-right-radius" => array("-moz-border-radius-bottomright", "-webkit-border-bottom-right-radius", null, null),
3020
- "border-end" => array("-moz-border-end", "-webkit-border-end", null, null),
3021
- "border-end-color" => array("-moz-border-end-color", "-webkit-border-end-color", null, null),
3022
- "border-end-style" => array("-moz-border-end-style", "-webkit-border-end-style", null, null),
3023
- "border-end-width" => array("-moz-border-end-width", "-webkit-border-end-width", null, null),
3024
- "border-fit" => array(null, "-webkit-border-fit", null, null),
3025
- "border-horizontal-spacing" => array(null, "-webkit-border-horizontal-spacing", null, null),
3026
- "border-image" => array("-moz-border-image", "-webkit-border-image", null, null),
3027
- "border-left-colors" => array("-moz-border-left-colors", null, null, null),
3028
- "border-radius" => array("-moz-border-radius", "-webkit-border-radius", null, null),
3029
- "border-border-right-colors" => array("-moz-border-right-colors", null, null, null),
3030
- "border-start" => array("-moz-border-start", "-webkit-border-start", null, null),
3031
- "border-start-color" => array("-moz-border-start-color", "-webkit-border-start-color", null, null),
3032
- "border-start-style" => array("-moz-border-start-style", "-webkit-border-start-style", null, null),
3033
- "border-start-width" => array("-moz-border-start-width", "-webkit-border-start-width", null, null),
3034
- "border-top-colors" => array("-moz-border-top-colors", null, null, null),
3035
- "border-top-left-radius" => array("-moz-border-radius-topleft", "-webkit-border-top-left-radius", null, null),
3036
- "border-top-right-radius" => array("-moz-border-radius-topright", "-webkit-border-top-right-radius", null, null),
3037
- "border-vertical-spacing" => array(null, "-webkit-border-vertical-spacing", null, null),
3038
- "box-align" => array("-moz-box-align", "-webkit-box-align", null, null),
3039
- "box-direction" => array("-moz-box-direction", "-webkit-box-direction", null, null),
3040
- "box-flex" => array("-moz-box-flex", "-webkit-box-flex", null, null),
3041
- "box-flex-group" => array(null, "-webkit-box-flex-group", null, null),
3042
- "box-flex-lines" => array(null, "-webkit-box-flex-lines", null, null),
3043
- "box-ordinal-group" => array("-moz-box-ordinal-group", "-webkit-box-ordinal-group", null, null),
3044
- "box-orient" => array("-moz-box-orient", "-webkit-box-orient", null, null),
3045
- "box-pack" => array("-moz-box-pack", "-webkit-box-pack", null, null),
3046
- "box-reflect" => array(null, "-webkit-box-reflect", null, null),
3047
- "box-shadow" => array("-moz-box-shadow", "-webkit-box-shadow", null, null),
3048
- "box-sizing" => array("-moz-box-sizing", null, null, null),
3049
- "color-correction" => array(null, "-webkit-color-correction", null, null),
3050
- "column-break-after" => array(null, "-webkit-column-break-after", null, null),
3051
- "column-break-before" => array(null, "-webkit-column-break-before", null, null),
3052
- "column-break-inside" => array(null, "-webkit-column-break-inside", null, null),
3053
- "column-count" => array("-moz-column-count", "-webkit-column-count", null, null),
3054
- "column-gap" => array("-moz-column-gap", "-webkit-column-gap", null, null),
3055
- "column-rule" => array("-moz-column-rule", "-webkit-column-rule", null, null),
3056
- "column-rule-color" => array("-moz-column-rule-color", "-webkit-column-rule-color", null, null),
3057
- "column-rule-style" => array("-moz-column-rule-style", "-webkit-column-rule-style", null, null),
3058
- "column-rule-width" => array("-moz-column-rule-width", "-webkit-column-rule-width", null, null),
3059
- "column-span" => array(null, "-webkit-column-span", null, null),
3060
- "column-width" => array("-moz-column-width", "-webkit-column-width", null, null),
3061
- "columns" => array(null, "-webkit-columns", null, null),
3062
- "filter" => array(__CLASS__, "filter"),
3063
- "float-edge" => array("-moz-float-edge", null, null, null),
3064
- "font-feature-settings" => array("-moz-font-feature-settings", null, null, null),
3065
- "font-language-override" => array("-moz-font-language-override", null, null, null),
3066
- "font-size-delta" => array(null, "-webkit-font-size-delta", null, null),
3067
- "font-smoothing" => array(null, "-webkit-font-smoothing", null, null),
3068
- "force-broken-image-icon" => array("-moz-force-broken-image-icon", null, null, null),
3069
- "highlight" => array(null, "-webkit-highlight", null, null),
3070
- "hyphenate-character" => array(null, "-webkit-hyphenate-character", null, null),
3071
- "hyphenate-locale" => array(null, "-webkit-hyphenate-locale", null, null),
3072
- "hyphens" => array(null, "-webkit-hyphens", null, null),
3073
- "force-broken-image-icon" => array("-moz-image-region", null, null, null),
3074
- "ime-mode" => array(null, null, null, "-ms-ime-mode"),
3075
- "interpolation-mode" => array(null, null, null, "-ms-interpolation-mode"),
3076
- "layout-flow" => array(null, null, null, "-ms-layout-flow"),
3077
- "layout-grid" => array(null, null, null, "-ms-layout-grid"),
3078
- "layout-grid-char" => array(null, null, null, "-ms-layout-grid-char"),
3079
- "layout-grid-line" => array(null, null, null, "-ms-layout-grid-line"),
3080
- "layout-grid-mode" => array(null, null, null, "-ms-layout-grid-mode"),
3081
- "layout-grid-type" => array(null, null, null, "-ms-layout-grid-type"),
3082
- "line-break" => array(null, "-webkit-line-break", null, "-ms-line-break"),
3083
- "line-clamp" => array(null, "-webkit-line-clamp", null, null),
3084
- "line-grid-mode" => array(null, null, null, "-ms-line-grid-mode"),
3085
- "logical-height" => array(null, "-webkit-logical-height", null, null),
3086
- "logical-width" => array(null, "-webkit-logical-width", null, null),
3087
- "margin-after" => array(null, "-webkit-margin-after", null, null),
3088
- "margin-after-collapse" => array(null, "-webkit-margin-after-collapse", null, null),
3089
- "margin-before" => array(null, "-webkit-margin-before", null, null),
3090
- "margin-before-collapse" => array(null, "-webkit-margin-before-collapse", null, null),
3091
- "margin-bottom-collapse" => array(null, "-webkit-margin-bottom-collapse", null, null),
3092
- "margin-collapse" => array(null, "-webkit-margin-collapse", null, null),
3093
- "margin-end" => array("-moz-margin-end", "-webkit-margin-end", null, null),
3094
- "margin-start" => array("-moz-margin-start", "-webkit-margin-start", null, null),
3095
- "margin-top-collapse" => array(null, "-webkit-margin-top-collapse", null, null),
3096
- "marquee " => array(null, "-webkit-marquee", null, null),
3097
- "marquee-direction" => array(null, "-webkit-marquee-direction", null, null),
3098
- "marquee-increment" => array(null, "-webkit-marquee-increment", null, null),
3099
- "marquee-repetition" => array(null, "-webkit-marquee-repetition", null, null),
3100
- "marquee-speed" => array(null, "-webkit-marquee-speed", null, null),
3101
- "marquee-style" => array(null, "-webkit-marquee-style", null, null),
3102
- "mask" => array(null, "-webkit-mask", null, null),
3103
- "mask-attachment" => array(null, "-webkit-mask-attachment", null, null),
3104
- "mask-box-image" => array(null, "-webkit-mask-box-image", null, null),
3105
- "mask-clip" => array(null, "-webkit-mask-clip", null, null),
3106
- "mask-composite" => array(null, "-webkit-mask-composite", null, null),
3107
- "mask-image" => array(null, "-webkit-mask-image", null, null),
3108
- "mask-origin" => array(null, "-webkit-mask-origin", null, null),
3109
- "mask-position" => array(null, "-webkit-mask-position", null, null),
3110
- "mask-position-x" => array(null, "-webkit-mask-position-x", null, null),
3111
- "mask-position-y" => array(null, "-webkit-mask-position-y", null, null),
3112
- "mask-repeat" => array(null, "-webkit-mask-repeat", null, null),
3113
- "mask-repeat-x" => array(null, "-webkit-mask-repeat-x", null, null),
3114
- "mask-repeat-y" => array(null, "-webkit-mask-repeat-y", null, null),
3115
- "mask-size" => array(null, "-webkit-mask-size", null, null),
3116
- "match-nearest-mail-blockquote-color" => array(null, "-webkit-match-nearest-mail-blockquote-color", null, null),
3117
- "max-logical-height" => array(null, "-webkit-max-logical-height", null, null),
3118
- "max-logical-width" => array(null, "-webkit-max-logical-width", null, null),
3119
- "min-logical-height" => array(null, "-webkit-min-logical-height", null, null),
3120
- "min-logical-width" => array(null, "-webkit-min-logical-width", null, null),
3121
- "object-fit" => array(null, null, "-o-object-fit", null),
3122
- "object-position" => array(null, null, "-o-object-position", null),
3123
- "opacity" => array(__CLASS__, "opacity"),
3124
- "outline-radius" => array("-moz-outline-radius", null, null, null),
3125
- "outline-bottom-left-radius" => array("-moz-outline-radius-bottomleft", null, null, null),
3126
- "outline-bottom-right-radius" => array("-moz-outline-radius-bottomright", null, null, null),
3127
- "outline-top-left-radius" => array("-moz-outline-radius-topleft", null, null, null),
3128
- "outline-top-right-radius" => array("-moz-outline-radius-topright", null, null, null),
3129
- "padding-after" => array(null, "-webkit-padding-after", null, null),
3130
- "padding-before" => array(null, "-webkit-padding-before", null, null),
3131
- "padding-end" => array("-moz-padding-end", "-webkit-padding-end", null, null),
3132
- "padding-start" => array("-moz-padding-start", "-webkit-padding-start", null, null),
3133
- "perspective" => array(null, "-webkit-perspective", null, null),
3134
- "perspective-origin" => array(null, "-webkit-perspective-origin", null, null),
3135
- "perspective-origin-x" => array(null, "-webkit-perspective-origin-x", null, null),
3136
- "perspective-origin-y" => array(null, "-webkit-perspective-origin-y", null, null),
3137
- "rtl-ordering" => array(null, "-webkit-rtl-ordering", null, null),
3138
- "scrollbar-3dlight-color" => array(null, null, null, "-ms-scrollbar-3dlight-color"),
3139
- "scrollbar-arrow-color" => array(null, null, null, "-ms-scrollbar-arrow-color"),
3140
- "scrollbar-base-color" => array(null, null, null, "-ms-scrollbar-base-color"),
3141
- "scrollbar-darkshadow-color" => array(null, null, null, "-ms-scrollbar-darkshadow-color"),
3142
- "scrollbar-face-color" => array(null, null, null, "-ms-scrollbar-face-color"),
3143
- "scrollbar-highlight-color" => array(null, null, null, "-ms-scrollbar-highlight-color"),
3144
- "scrollbar-shadow-color" => array(null, null, null, "-ms-scrollbar-shadow-color"),
3145
- "scrollbar-track-color" => array(null, null, null, "-ms-scrollbar-track-color"),
3146
- "stack-sizing" => array("-moz-stack-sizing", null, null, null),
3147
- "svg-shadow" => array(null, "-webkit-svg-shadow", null, null),
3148
- "tab-size" => array("-moz-tab-size", null, "-o-tab-size", null),
3149
- "table-baseline" => array(null, null, "-o-table-baseline", null),
3150
- "text-align-last" => array(null, null, null, "-ms-text-align-last"),
3151
- "text-autospace" => array(null, null, null, "-ms-text-autospace"),
3152
- "text-combine" => array(null, "-webkit-text-combine", null, null),
3153
- "text-decorations-in-effect" => array(null, "-webkit-text-decorations-in-effect", null, null),
3154
- "text-emphasis" => array(null, "-webkit-text-emphasis", null, null),
3155
- "text-emphasis-color" => array(null, "-webkit-text-emphasis-color", null, null),
3156
- "text-emphasis-position" => array(null, "-webkit-text-emphasis-position", null, null),
3157
- "text-emphasis-style" => array(null, "-webkit-text-emphasis-style", null, null),
3158
- "text-fill-color" => array(null, "-webkit-text-fill-color", null, null),
3159
- "text-justify" => array(null, null, null, "-ms-text-justify"),
3160
- "text-kashida-space" => array(null, null, null, "-ms-text-kashida-space"),
3161
- "text-overflow" => array(null, null, "-o-text-overflow", "-ms-text-overflow"),
3162
- "text-security" => array(null, "-webkit-text-security", null, null),
3163
- "text-size-adjust" => array(null, "-webkit-text-size-adjust", null, "-ms-text-size-adjust"),
3164
- "text-stroke" => array(null, "-webkit-text-stroke", null, null),
3165
- "text-stroke-color" => array(null, "-webkit-text-stroke-color", null, null),
3166
- "text-stroke-width" => array(null, "-webkit-text-stroke-width", null, null),
3167
- "text-underline-position" => array(null, null, null, "-ms-text-underline-position"),
3168
- "transform" => array("-moz-transform", "-webkit-transform", "-o-transform", null),
3169
- "transform-origin" => array("-moz-transform-origin", "-webkit-transform-origin", "-o-transform-origin", null),
3170
- "transform-origin-x" => array(null, "-webkit-transform-origin-x", null, null),
3171
- "transform-origin-y" => array(null, "-webkit-transform-origin-y", null, null),
3172
- "transform-origin-z" => array(null, "-webkit-transform-origin-z", null, null),
3173
- "transform-style" => array(null, "-webkit-transform-style", null, null),
3174
- "transition" => array("-moz-transition", "-webkit-transition", "-o-transition", null),
3175
- "transition-delay" => array("-moz-transition-delay", "-webkit-transition-delay", "-o-transition-delay", null),
3176
- "transition-duration" => array("-moz-transition-duration", "-webkit-transition-duration", "-o-transition-duration", null),
3177
- "transition-property" => array("-moz-transition-property", "-webkit-transition-property", "-o-transition-property", null),
3178
- "transition-timing-function" => array("-moz-transition-timing-function", "-webkit-transition-timing-function", "-o-transition-timing-function", null),
3179
- "user-drag" => array(null, "-webkit-user-drag", null, null),
3180
- "user-focus" => array("-moz-user-focus", null, null, null),
3181
- "user-input" => array("-moz-user-input", null, null, null),
3182
- "user-modify" => array("-moz-user-modify", "-webkit-user-modify", null, null),
3183
- "user-select" => array("-moz-user-select", "-webkit-user-select", null, null),
3184
- "white-space" => array(__CLASS__, "whiteSpace"),
3185
- "window-shadow" => array("-moz-window-shadow", null, null, null),
3186
- "word-break" => array(null, null, null, "-ms-word-break"),
3187
- "word-wrap" => array(null, null, null, "-ms-word-wrap"),
3188
- "writing-mode" => array(null, "-webkit-writing-mode", null, "-ms-writing-mode"),
3189
- "zoom" => array(null, null, null, "-ms-zoom")
3190
- );
3191
- /**
3192
- * Implements {@link aCssMinifierFilter::filter()}.
3193
- *
3194
- * @param array $tokens Array of objects of type aCssToken
3195
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
3196
- */
3197
- public function apply(array &$tokens)
3198
- {
3199
- $r = 0;
3200
- $transformations = &$this->transformations;
3201
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
3202
- {
3203
- if (get_class($tokens[$i]) === "CssRulesetDeclarationToken")
3204
- {
3205
- $tProperty = $tokens[$i]->Property;
3206
- if (isset($transformations[$tProperty]))
3207
- {
3208
- $result = array();
3209
- if (is_callable($transformations[$tProperty]))
3210
- {
3211
- $result = call_user_func_array($transformations[$tProperty], array($tokens[$i]));
3212
- if (!is_array($result) && is_object($result))
3213
- {
3214
- $result = array($result);
3215
- }
3216
- }
3217
- else
3218
- {
3219
- $tValue = $tokens[$i]->Value;
3220
- $tMediaTypes = $tokens[$i]->MediaTypes;
3221
- foreach ($transformations[$tProperty] as $property)
3222
- {
3223
- if ($property !== null)
3224
- {
3225
- $result[] = new CssRulesetDeclarationToken($property, $tValue, $tMediaTypes);
3226
- }
3227
- }
3228
- }
3229
- if (count($result) > 0)
3230
- {
3231
- array_splice($tokens, $i + 1, 0, $result);
3232
- $i += count($result);
3233
- $l += count($result);
3234
- }
3235
- }
3236
- }
3237
- }
3238
- return $r;
3239
- }
3240
- /**
3241
- * Transforms the Internet Explorer specific declaration property "filter" to Internet Explorer 8+ compatible
3242
- * declaratiopn property "-ms-filter".
3243
- *
3244
- * @param aCssToken $token
3245
- * @return array
3246
- */
3247
- private static function filter($token)
3248
- {
3249
- $r = array
3250
- (
3251
- new CssRulesetDeclarationToken("-ms-filter", "\"" . $token->Value . "\"", $token->MediaTypes),
3252
- );
3253
- return $r;
3254
- }
3255
- /**
3256
- * Transforms "opacity: {value}" into browser specific counterparts.
3257
- *
3258
- * @param aCssToken $token
3259
- * @return array
3260
- */
3261
- private static function opacity($token)
3262
- {
3263
- // Calculate the value for Internet Explorer filter statement
3264
- $ieValue = (int) ((float) $token->Value * 100);
3265
- $r = array
3266
- (
3267
- // Internet Explorer >= 8
3268
- new CssRulesetDeclarationToken("-ms-filter", "\"alpha(opacity=" . $ieValue . ")\"", $token->MediaTypes),
3269
- // Internet Explorer >= 4 <= 7
3270
- new CssRulesetDeclarationToken("filter", "alpha(opacity=" . $ieValue . ")", $token->MediaTypes),
3271
- new CssRulesetDeclarationToken("zoom", "1", $token->MediaTypes)
3272
- );
3273
- return $r;
3274
- }
3275
- /**
3276
- * Transforms "white-space: pre-wrap" into browser specific counterparts.
3277
- *
3278
- * @param aCssToken $token
3279
- * @return array
3280
- */
3281
- private static function whiteSpace($token)
3282
- {
3283
- if (strtolower($token->Value) === "pre-wrap")
3284
- {
3285
- $r = array
3286
- (
3287
- // Firefox < 3
3288
- new CssRulesetDeclarationToken("white-space", "-moz-pre-wrap", $token->MediaTypes),
3289
- // Webkit
3290
- new CssRulesetDeclarationToken("white-space", "-webkit-pre-wrap", $token->MediaTypes),
3291
- // Opera >= 4 <= 6
3292
- new CssRulesetDeclarationToken("white-space", "-pre-wrap", $token->MediaTypes),
3293
- // Opera >= 7
3294
- new CssRulesetDeclarationToken("white-space", "-o-pre-wrap", $token->MediaTypes),
3295
- // Internet Explorer >= 5.5
3296
- new CssRulesetDeclarationToken("word-wrap", "break-word", $token->MediaTypes)
3297
- );
3298
- return $r;
3299
- }
3300
- else
3301
- {
3302
- return array();
3303
- }
3304
- }
3305
- }
3306
-
3307
- /**
3308
- * This {@link aCssMinifierFilter minifier filter} will convert @keyframes at-rule block to browser specific counterparts.
3309
- *
3310
- * @package CssMin/Minifier/Filters
3311
- * @link http://code.google.com/p/cssmin/
3312
- * @author Joe Scylla <joe.scylla@gmail.com>
3313
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3314
- * @license http://opensource.org/licenses/mit-license.php MIT License
3315
- * @version 3.0.1
3316
- */
3317
- class CssConvertLevel3AtKeyframesMinifierFilter extends aCssMinifierFilter
3318
- {
3319
- /**
3320
- * Implements {@link aCssMinifierFilter::filter()}.
3321
- *
3322
- * @param array $tokens Array of objects of type aCssToken
3323
- * @return integer Count of added, changed or removed tokens; a return value larger than 0 will rebuild the array
3324
- */
3325
- public function apply(array &$tokens)
3326
- {
3327
- $r = 0;
3328
- $transformations = array("-moz-keyframes", "-webkit-keyframes");
3329
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
3330
- {
3331
- if (get_class($tokens[$i]) === "CssAtKeyframesStartToken")
3332
- {
3333
- for ($ii = $i; $ii < $l; $ii++)
3334
- {
3335
- if (get_class($tokens[$ii]) === "CssAtKeyframesEndToken")
3336
- {
3337
- break;
3338
- }
3339
- }
3340
- if (get_class($tokens[$ii]) === "CssAtKeyframesEndToken")
3341
- {
3342
- $add = array();
3343
- $source = array();
3344
- for ($iii = $i; $iii <= $ii; $iii++)
3345
- {
3346
- $source[] = clone($tokens[$iii]);
3347
- }
3348
- foreach ($transformations as $transformation)
3349
- {
3350
- $t = array();
3351
- foreach ($source as $token)
3352
- {
3353
- $t[] = clone($token);
3354
- }
3355
- $t[0]->AtRuleName = $transformation;
3356
- $add = array_merge($add, $t);
3357
- }
3358
- if (isset($this->configuration["RemoveSource"]) && $this->configuration["RemoveSource"] === true)
3359
- {
3360
- array_splice($tokens, $i, $ii - $i + 1, $add);
3361
- }
3362
- else
3363
- {
3364
- array_splice($tokens, $ii + 1, 0, $add);
3365
- }
3366
- $l = count($tokens);
3367
- $i = $ii + count($add);
3368
- $r += count($add);
3369
- }
3370
- }
3371
- }
3372
- return $r;
3373
- }
3374
- }
3375
-
3376
- /**
3377
- * This {@link aCssMinifierPlugin} will convert a color value in hsl notation to hexadecimal notation.
3378
- *
3379
- * Example:
3380
- * <code>
3381
- * color: hsl(232,36%,48%);
3382
- * </code>
3383
- *
3384
- * Will get converted to:
3385
- * <code>
3386
- * color:#4e5aa7;
3387
- * </code>
3388
- *
3389
- * @package CssMin/Minifier/Plugins
3390
- * @link http://code.google.com/p/cssmin/
3391
- * @author Joe Scylla <joe.scylla@gmail.com>
3392
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3393
- * @license http://opensource.org/licenses/mit-license.php MIT License
3394
- * @version 3.0.1
3395
- */
3396
- class CssConvertHslColorsMinifierPlugin extends aCssMinifierPlugin
3397
- {
3398
- /**
3399
- * Regular expression matching the value.
3400
- *
3401
- * @var string
3402
- */
3403
- private $reMatch = "/^hsl\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*%\s*,\s*([0-9]+)\s*%\s*\)/iS";
3404
- /**
3405
- * Implements {@link aCssMinifierPlugin::minify()}.
3406
- *
3407
- * @param aCssToken $token Token to process
3408
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3409
- */
3410
- public function apply(aCssToken &$token)
3411
- {
3412
- if (stripos($token->Value, "hsl") !== false && preg_match($this->reMatch, $token->Value, $m))
3413
- {
3414
- $token->Value = str_replace($m[0], $this->hsl2hex($m[1], $m[2], $m[3]), $token->Value);
3415
- }
3416
- return false;
3417
- }
3418
- /**
3419
- * Implements {@link aMinifierPlugin::getTriggerTokens()}
3420
- *
3421
- * @return array
3422
- */
3423
- public function getTriggerTokens()
3424
- {
3425
- return array
3426
- (
3427
- "CssAtFontFaceDeclarationToken",
3428
- "CssAtPageDeclarationToken",
3429
- "CssRulesetDeclarationToken"
3430
- );
3431
- }
3432
- /**
3433
- * Convert a HSL value to hexadecimal notation.
3434
- *
3435
- * Based on: {@link http://www.easyrgb.com/index.php?X=MATH&H=19#text19}.
3436
- *
3437
- * @param integer $hue Hue
3438
- * @param integer $saturation Saturation
3439
- * @param integer $lightness Lightnesss
3440
- * @return string
3441
- */
3442
- private function hsl2hex($hue, $saturation, $lightness)
3443
- {
3444
- $hue = $hue / 360;
3445
- $saturation = $saturation / 100;
3446
- $lightness = $lightness / 100;
3447
- if ($saturation == 0)
3448
- {
3449
- $red = $lightness * 255;
3450
- $green = $lightness * 255;
3451
- $blue = $lightness * 255;
3452
- }
3453
- else
3454
- {
3455
- if ($lightness < 0.5 )
3456
- {
3457
- $v2 = $lightness * (1 + $saturation);
3458
- }
3459
- else
3460
- {
3461
- $v2 = ($lightness + $saturation) - ($saturation * $lightness);
3462
- }
3463
- $v1 = 2 * $lightness - $v2;
3464
- $red = 255 * self::hue2rgb($v1, $v2, $hue + (1 / 3));
3465
- $green = 255 * self::hue2rgb($v1, $v2, $hue);
3466
- $blue = 255 * self::hue2rgb($v1, $v2, $hue - (1 / 3));
3467
- }
3468
- return "#" . str_pad(dechex(round($red)), 2, "0", STR_PAD_LEFT) . str_pad(dechex(round($green)), 2, "0", STR_PAD_LEFT) . str_pad(dechex(round($blue)), 2, "0", STR_PAD_LEFT);
3469
- }
3470
- /**
3471
- * Apply hue to a rgb color value.
3472
- *
3473
- * @param integer $v1 Value 1
3474
- * @param integer $v2 Value 2
3475
- * @param integer $hue Hue
3476
- * @return integer
3477
- */
3478
- private function hue2rgb($v1, $v2, $hue)
3479
- {
3480
- if ($hue < 0)
3481
- {
3482
- $hue += 1;
3483
- }
3484
- if ($hue > 1)
3485
- {
3486
- $hue -= 1;
3487
- }
3488
- if ((6 * $hue) < 1)
3489
- {
3490
- return ($v1 + ($v2 - $v1) * 6 * $hue);
3491
- }
3492
- if ((2 * $hue) < 1)
3493
- {
3494
- return ($v2);
3495
- }
3496
- if ((3 * $hue) < 2)
3497
- {
3498
- return ($v1 + ($v2 - $v1) * (( 2 / 3) - $hue) * 6);
3499
- }
3500
- return $v1;
3501
- }
3502
- }
3503
-
3504
- /**
3505
- * This {@link aCssMinifierPlugin} will convert the font-weight values normal and bold to their numeric notation.
3506
- *
3507
- * Example:
3508
- * <code>
3509
- * font-weight: normal;
3510
- * font: bold 11px monospace;
3511
- * </code>
3512
- *
3513
- * Will get converted to:
3514
- * <code>
3515
- * font-weight:400;
3516
- * font:700 11px monospace;
3517
- * </code>
3518
- *
3519
- * @package CssMin/Minifier/Pluginsn
3520
- * @link http://code.google.com/p/cssmin/
3521
- * @author Joe Scylla <joe.scylla@gmail.com>
3522
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3523
- * @license http://opensource.org/licenses/mit-license.php MIT License
3524
- * @version 3.0.1
3525
- */
3526
- class CssConvertFontWeightMinifierPlugin extends aCssMinifierPlugin
3527
- {
3528
- /**
3529
- * Array of included declaration properties this plugin will process; others declaration properties will get
3530
- * ignored.
3531
- *
3532
- * @var array
3533
- */
3534
- private $include = array
3535
- (
3536
- "font",
3537
- "font-weight"
3538
- );
3539
- /**
3540
- * Regular expression matching the value.
3541
- *
3542
- * @var string
3543
- */
3544
- private $reMatch = null;
3545
- /**
3546
- * Regular expression replace the value.
3547
- *
3548
- * @var string
3549
- */
3550
- private $reReplace = "\"\${1}\" . \$this->transformation[\"\${2}\"] . \"\${3}\"";
3551
- /**
3552
- * Transformation table used by the {@link CssConvertFontWeightMinifierPlugin::$reReplace replace regular expression}.
3553
- *
3554
- * @var array
3555
- */
3556
- private $transformation = array
3557
- (
3558
- "normal" => "400",
3559
- "bold" => "700"
3560
- );
3561
- /**
3562
- * Overwrites {@link aCssMinifierPlugin::__construct()}.
3563
- *
3564
- * The constructor will create the {@link CssConvertFontWeightMinifierPlugin::$reReplace replace regular expression}
3565
- * based on the {@link CssConvertFontWeightMinifierPlugin::$transformation transformation table}.
3566
- *
3567
- * @param CssMinifier $minifier The CssMinifier object of this plugin.
3568
- * @return void
3569
- */
3570
- public function __construct(CssMinifier $minifier)
3571
- {
3572
- $this->reMatch = "/(^|\s)+(" . implode("|", array_keys($this->transformation)). ")(\s|$)+/eiS";
3573
- parent::__construct($minifier);
3574
- }
3575
- /**
3576
- * Implements {@link aCssMinifierPlugin::minify()}.
3577
- *
3578
- * @param aCssToken $token Token to process
3579
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3580
- */
3581
- public function apply(aCssToken &$token)
3582
- {
3583
- if (in_array($token->Property, $this->include) && preg_match($this->reMatch, $token->Value, $m))
3584
- {
3585
- $token->Value = preg_replace($this->reMatch, $this->reReplace, $token->Value);
3586
- }
3587
- return false;
3588
- }
3589
- /**
3590
- * Implements {@link aMinifierPlugin::getTriggerTokens()}
3591
- *
3592
- * @return array
3593
- */
3594
- public function getTriggerTokens()
3595
- {
3596
- return array
3597
- (
3598
- "CssAtFontFaceDeclarationToken",
3599
- "CssAtPageDeclarationToken",
3600
- "CssRulesetDeclarationToken"
3601
- );
3602
- }
3603
- }
3604
-
3605
- /**
3606
- * This {@link aCssMinifierPlugin} will compress several unit values to their short notations. Examples:
3607
- *
3608
- * <code>
3609
- * padding: 0.5em;
3610
- * border: 0px;
3611
- * margin: 0 0 0 0;
3612
- * </code>
3613
- *
3614
- * Will get compressed to:
3615
- *
3616
- * <code>
3617
- * padding:.5px;
3618
- * border:0;
3619
- * margin:0;
3620
- * </code>
3621
- *
3622
- * --
3623
- *
3624
- * @package CssMin/Minifier/Plugins
3625
- * @link http://code.google.com/p/cssmin/
3626
- * @author Joe Scylla <joe.scylla@gmail.com>
3627
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3628
- * @license http://opensource.org/licenses/mit-license.php MIT License
3629
- * @version 3.0.1
3630
- */
3631
- class CssCompressUnitValuesMinifierPlugin extends aCssMinifierPlugin
3632
- {
3633
- /**
3634
- * Regular expression used for matching and replacing unit values.
3635
- *
3636
- * @var array
3637
- */
3638
- private $re = array
3639
- (
3640
- "/(^| |-)0\.([0-9]+?)(0+)?(%|em|ex|px|in|cm|mm|pt|pc)/iS" => "\${1}.\${2}\${4}",
3641
- "/(^| )-?(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)/iS" => "\${1}0",
3642
- "/(^0\s0\s0\s0)|(^0\s0\s0$)|(^0\s0$)/iS" => "0"
3643
- );
3644
- /**
3645
- * Regular expression matching the value.
3646
- *
3647
- * @var string
3648
- */
3649
- private $reMatch = "/(^| |-)0\.([0-9]+?)(0+)?(%|em|ex|px|in|cm|mm|pt|pc)|(^| )-?(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)|(^0\s0\s0\s0$)|(^0\s0\s0$)|(^0\s0$)/iS";
3650
- /**
3651
- * Implements {@link aCssMinifierPlugin::minify()}.
3652
- *
3653
- * @param aCssToken $token Token to process
3654
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3655
- */
3656
- public function apply(aCssToken &$token)
3657
- {
3658
- if (preg_match($this->reMatch, $token->Value))
3659
- {
3660
- foreach ($this->re as $reMatch => $reReplace)
3661
- {
3662
- $token->Value = preg_replace($reMatch, $reReplace, $token->Value);
3663
- }
3664
- }
3665
- return false;
3666
- }
3667
- /**
3668
- * Implements {@link aMinifierPlugin::getTriggerTokens()}
3669
- *
3670
- * @return array
3671
- */
3672
- public function getTriggerTokens()
3673
- {
3674
- return array
3675
- (
3676
- "CssAtFontFaceDeclarationToken",
3677
- "CssAtPageDeclarationToken",
3678
- "CssRulesetDeclarationToken"
3679
- );
3680
- }
3681
- }
3682
-
3683
- /**
3684
- * This {@link aCssMinifierPlugin} compress the content of expresssion() declaration values.
3685
- *
3686
- * For compression of expressions {@link https://github.com/rgrove/jsmin-php/ JSMin} will get used. JSMin have to be
3687
- * already included or loadable via {@link http://goo.gl/JrW54 PHP autoloading}.
3688
- *
3689
- * @package CssMin/Minifier/Plugins
3690
- * @link http://code.google.com/p/cssmin/
3691
- * @author Joe Scylla <joe.scylla@gmail.com>
3692
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3693
- * @license http://opensource.org/licenses/mit-license.php MIT License
3694
- * @version 3.0.1
3695
- */
3696
- class CssCompressExpressionValuesMinifierPlugin extends aCssMinifierPlugin
3697
- {
3698
- /**
3699
- * Implements {@link aCssMinifierPlugin::minify()}.
3700
- *
3701
- * @param aCssToken $token Token to process
3702
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3703
- */
3704
- public function apply(aCssToken &$token)
3705
- {
3706
- if (class_exists("JSMin") && stripos($token->Value, "expression(") !== false)
3707
- {
3708
- $value = $token->Value;
3709
- $value = substr($token->Value, stripos($token->Value, "expression(") + 10);
3710
- $value = trim(JSMin::minify($value));
3711
- $token->Value = "expression(" . $value . ")";
3712
- }
3713
- return false;
3714
- }
3715
- /**
3716
- * Implements {@link aMinifierPlugin::getTriggerTokens()}
3717
- *
3718
- * @return array
3719
- */
3720
- public function getTriggerTokens()
3721
- {
3722
- return array
3723
- (
3724
- "CssAtFontFaceDeclarationToken",
3725
- "CssAtPageDeclarationToken",
3726
- "CssRulesetDeclarationToken"
3727
- );
3728
- }
3729
- }
3730
-
3731
- /**
3732
- * This {@link aCssMinifierPlugin} will convert hexadecimal color value with 6 chars to their 3 char hexadecimal
3733
- * notation (if possible).
3734
- *
3735
- * Example:
3736
- * <code>
3737
- * color: #aabbcc;
3738
- * </code>
3739
- *
3740
- * Will get converted to:
3741
- * <code>
3742
- * color:#abc;
3743
- * </code>
3744
- *
3745
- * @package CssMin/Minifier/Plugins
3746
- * @link http://code.google.com/p/cssmin/
3747
- * @author Joe Scylla <joe.scylla@gmail.com>
3748
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3749
- * @license http://opensource.org/licenses/mit-license.php MIT License
3750
- * @version 3.0.1
3751
- */
3752
- class CssCompressColorValuesMinifierPlugin extends aCssMinifierPlugin
3753
- {
3754
- /**
3755
- * Regular expression matching 6 char hexadecimal color values.
3756
- *
3757
- * @var string
3758
- */
3759
- private $reMatch = "/\#([0-9a-f]{6})/iS";
3760
- /**
3761
- * Implements {@link aCssMinifierPlugin::minify()}.
3762
- *
3763
- * @param aCssToken $token Token to process
3764
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3765
- */
3766
- public function apply(aCssToken &$token)
3767
- {
3768
- if (strpos($token->Value, "#") !== false && preg_match($this->reMatch, $token->Value, $m))
3769
- {
3770
- $value = strtolower($m[1]);
3771
- if ($value[0] == $value[1] && $value[2] == $value[3] && $value[4] == $value[5])
3772
- {
3773
- $token->Value = str_replace($m[0], "#" . $value[0] . $value[2] . $value[4], $token->Value);
3774
- }
3775
- }
3776
- return false;
3777
- }
3778
- /**
3779
- * Implements {@link aMinifierPlugin::getTriggerTokens()}
3780
- *
3781
- * @return array
3782
- */
3783
- public function getTriggerTokens()
3784
- {
3785
- return array
3786
- (
3787
- "CssAtFontFaceDeclarationToken",
3788
- "CssAtPageDeclarationToken",
3789
- "CssRulesetDeclarationToken"
3790
- );
3791
- }
3792
- }
3793
-
3794
- /**
3795
- * This {@link aCssToken CSS token} represents a CSS comment.
3796
- *
3797
- * @package CssMin/Tokens
3798
- * @link http://code.google.com/p/cssmin/
3799
- * @author Joe Scylla <joe.scylla@gmail.com>
3800
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3801
- * @license http://opensource.org/licenses/mit-license.php MIT License
3802
- * @version 3.0.1
3803
- */
3804
- class CssCommentToken extends aCssToken
3805
- {
3806
- /**
3807
- * Comment as Text.
3808
- *
3809
- * @var string
3810
- */
3811
- public $Comment = "";
3812
- /**
3813
- * Set the properties of a comment token.
3814
- *
3815
- * @param string $comment Comment including comment delimiters
3816
- * @return void
3817
- */
3818
- public function __construct($comment)
3819
- {
3820
- $this->Comment = $comment;
3821
- }
3822
- /**
3823
- * Implements {@link aCssToken::__toString()}.
3824
- *
3825
- * @return string
3826
- */
3827
- public function __toString()
3828
- {
3829
- return $this->Comment;
3830
- }
3831
- }
3832
-
3833
- /**
3834
- * {@link aCssParserPlugin Parser plugin} for parsing comments.
3835
- *
3836
- * Adds a {@link CssCommentToken} to the parser if a comment was found.
3837
- *
3838
- * @package CssMin/Parser/Plugins
3839
- * @link http://code.google.com/p/cssmin/
3840
- * @author Joe Scylla <joe.scylla@gmail.com>
3841
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3842
- * @license http://opensource.org/licenses/mit-license.php MIT License
3843
- * @version 3.0.1
3844
- */
3845
- class CssCommentParserPlugin extends aCssParserPlugin
3846
- {
3847
- /**
3848
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
3849
- *
3850
- * @return array
3851
- */
3852
- public function getTriggerChars()
3853
- {
3854
- return array("*", "/");
3855
- }
3856
- /**
3857
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
3858
- *
3859
- * @return array
3860
- */
3861
- public function getTriggerStates()
3862
- {
3863
- return false;
3864
- }
3865
- /**
3866
- * Stored buffer for restore.
3867
- *
3868
- * @var string
3869
- */
3870
- private $restoreBuffer = "";
3871
- /**
3872
- * Implements {@link aCssParserPlugin::parse()}.
3873
- *
3874
- * @param integer $index Current index
3875
- * @param string $char Current char
3876
- * @param string $previousChar Previous char
3877
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
3878
- */
3879
- public function parse($index, $char, $previousChar, $state)
3880
- {
3881
- if ($char === "*" && $previousChar === "/" && $state !== "T_COMMENT")
3882
- {
3883
- $this->parser->pushState("T_COMMENT");
3884
- $this->parser->setExclusive(__CLASS__);
3885
- $this->restoreBuffer = substr($this->parser->getAndClearBuffer(), 0, -2);
3886
- }
3887
- elseif ($char === "/" && $previousChar === "*" && $state === "T_COMMENT")
3888
- {
3889
- $this->parser->popState();
3890
- $this->parser->unsetExclusive();
3891
- $this->parser->appendToken(new CssCommentToken("/*" . $this->parser->getAndClearBuffer()));
3892
- $this->parser->setBuffer($this->restoreBuffer);
3893
- }
3894
- else
3895
- {
3896
- return false;
3897
- }
3898
- return true;
3899
- }
3900
- }
3901
-
3902
- /**
3903
- * This {@link aCssToken CSS token} represents the start of a @variables at-rule block.
3904
- *
3905
- * @package CssMin/Tokens
3906
- * @link http://code.google.com/p/cssmin/
3907
- * @author Joe Scylla <joe.scylla@gmail.com>
3908
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3909
- * @license http://opensource.org/licenses/mit-license.php MIT License
3910
- * @version 3.0.1
3911
- */
3912
- class CssAtVariablesStartToken extends aCssAtBlockStartToken
3913
- {
3914
- /**
3915
- * Media types of the @variables at-rule block.
3916
- *
3917
- * @var array
3918
- */
3919
- public $MediaTypes = array();
3920
- /**
3921
- * Set the properties of a @variables at-rule token.
3922
- *
3923
- * @param array $mediaTypes Media types
3924
- * @return void
3925
- */
3926
- public function __construct($mediaTypes = null)
3927
- {
3928
- $this->MediaTypes = $mediaTypes ? $mediaTypes : array("all");
3929
- }
3930
- /**
3931
- * Implements {@link aCssToken::__toString()}.
3932
- *
3933
- * @return string
3934
- */
3935
- public function __toString()
3936
- {
3937
- return "";
3938
- }
3939
- }
3940
-
3941
- /**
3942
- * {@link aCssParserPlugin Parser plugin} for parsing @variables at-rule block with including declarations.
3943
- *
3944
- * Found @variables at-rule blocks will add a {@link CssAtVariablesStartToken} and {@link CssAtVariablesEndToken} to the
3945
- * parser; including declarations as {@link CssAtVariablesDeclarationToken}.
3946
- *
3947
- * @package CssMin/Parser/Plugins
3948
- * @link http://code.google.com/p/cssmin/
3949
- * @author Joe Scylla <joe.scylla@gmail.com>
3950
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3951
- * @license http://opensource.org/licenses/mit-license.php MIT License
3952
- * @version 3.0.1
3953
- */
3954
- class CssAtVariablesParserPlugin extends aCssParserPlugin
3955
- {
3956
- /**
3957
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
3958
- *
3959
- * @return array
3960
- */
3961
- public function getTriggerChars()
3962
- {
3963
- return array("@", "{", "}", ":", ";");
3964
- }
3965
- /**
3966
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
3967
- *
3968
- * @return array
3969
- */
3970
- public function getTriggerStates()
3971
- {
3972
- return array("T_DOCUMENT", "T_AT_VARIABLES::PREPARE", "T_AT_VARIABLES", "T_AT_VARIABLES_DECLARATION");
3973
- }
3974
- /**
3975
- * Implements {@link aCssParserPlugin::parse()}.
3976
- *
3977
- * @param integer $index Current index
3978
- * @param string $char Current char
3979
- * @param string $previousChar Previous char
3980
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
3981
- */
3982
- public function parse($index, $char, $previousChar, $state)
3983
- {
3984
- // Start of @variables at-rule block
3985
- if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@variables")
3986
- {
3987
- $this->parser->pushState("T_AT_VARIABLES::PREPARE");
3988
- $this->parser->clearBuffer();
3989
- return $index + 10;
3990
- }
3991
- // Start of @variables declarations
3992
- elseif ($char === "{" && $state === "T_AT_VARIABLES::PREPARE")
3993
- {
3994
- $this->parser->setState("T_AT_VARIABLES");
3995
- $mediaTypes = array_filter(array_map("trim", explode(",", $this->parser->getAndClearBuffer("{"))));
3996
- $this->parser->appendToken(new CssAtVariablesStartToken($mediaTypes));
3997
- }
3998
- // Start of @variables declaration
3999
- if ($char === ":" && $state === "T_AT_VARIABLES")
4000
- {
4001
- $this->buffer = $this->parser->getAndClearBuffer(":");
4002
- $this->parser->pushState("T_AT_VARIABLES_DECLARATION");
4003
- }
4004
- // Unterminated @variables declaration
4005
- elseif ($char === ":" && $state === "T_AT_VARIABLES_DECLARATION")
4006
- {
4007
- // Ignore Internet Explorer filter declarations
4008
- if ($this->buffer === "filter")
4009
- {
4010
- return false;
4011
- }
4012
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @variables declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
4013
- }
4014
- // End of @variables declaration
4015
- elseif (($char === ";" || $char === "}") && $state === "T_AT_VARIABLES_DECLARATION")
4016
- {
4017
- $value = $this->parser->getAndClearBuffer(";}");
4018
- if (strtolower(substr($value, -10, 10)) === "!important")
4019
- {
4020
- $value = trim(substr($value, 0, -10));
4021
- $isImportant = true;
4022
- }
4023
- else
4024
- {
4025
- $isImportant = false;
4026
- }
4027
- $this->parser->popState();
4028
- $this->parser->appendToken(new CssAtVariablesDeclarationToken($this->buffer, $value, $isImportant));
4029
- $this->buffer = "";
4030
- }
4031
- // End of @variables at-rule block
4032
- elseif ($char === "}" && $state === "T_AT_VARIABLES")
4033
- {
4034
- $this->parser->popState();
4035
- $this->parser->clearBuffer();
4036
- $this->parser->appendToken(new CssAtVariablesEndToken());
4037
- }
4038
- else
4039
- {
4040
- return false;
4041
- }
4042
- return true;
4043
- }
4044
- }
4045
-
4046
- /**
4047
- * This {@link aCssToken CSS token} represents the end of a @variables at-rule block.
4048
- *
4049
- * @package CssMin/Tokens
4050
- * @link http://code.google.com/p/cssmin/
4051
- * @author Joe Scylla <joe.scylla@gmail.com>
4052
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4053
- * @license http://opensource.org/licenses/mit-license.php MIT License
4054
- * @version 3.0.1
4055
- */
4056
- class CssAtVariablesEndToken extends aCssAtBlockEndToken
4057
- {
4058
- /**
4059
- * Implements {@link aCssToken::__toString()}.
4060
- *
4061
- * @return string
4062
- */
4063
- public function __toString()
4064
- {
4065
- return "";
4066
- }
4067
- }
4068
-
4069
- /**
4070
- * This {@link aCssToken CSS token} represents a declaration of a @variables at-rule block.
4071
- *
4072
- * @package CssMin/Tokens
4073
- * @link http://code.google.com/p/cssmin/
4074
- * @author Joe Scylla <joe.scylla@gmail.com>
4075
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4076
- * @license http://opensource.org/licenses/mit-license.php MIT License
4077
- * @version 3.0.1
4078
- */
4079
- class CssAtVariablesDeclarationToken extends aCssDeclarationToken
4080
- {
4081
- /**
4082
- * Implements {@link aCssToken::__toString()}.
4083
- *
4084
- * @return string
4085
- */
4086
- public function __toString()
4087
- {
4088
- return "";
4089
- }
4090
- }
4091
-
4092
- /**
4093
- * This {@link aCssToken CSS token} represents the start of a @page at-rule block.
4094
- *
4095
- * @package CssMin/Tokens
4096
- * @link http://code.google.com/p/cssmin/
4097
- * @author Joe Scylla <joe.scylla@gmail.com>
4098
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4099
- * @license http://opensource.org/licenses/mit-license.php MIT License
4100
- * @version 3.0.1
4101
- */
4102
- class CssAtPageStartToken extends aCssAtBlockStartToken
4103
- {
4104
- /**
4105
- * Selector.
4106
- *
4107
- * @var string
4108
- */
4109
- public $Selector = "";
4110
- /**
4111
- * Sets the properties of the @page at-rule.
4112
- *
4113
- * @param string $selector Selector
4114
- * @return void
4115
- */
4116
- public function __construct($selector = "")
4117
- {
4118
- $this->Selector = $selector;
4119
- }
4120
- /**
4121
- * Implements {@link aCssToken::__toString()}.
4122
- *
4123
- * @return string
4124
- */
4125
- public function __toString()
4126
- {
4127
- return "@page" . ($this->Selector ? " " . $this->Selector : "") . "{";
4128
- }
4129
- }
4130
-
4131
- /**
4132
- * {@link aCssParserPlugin Parser plugin} for parsing @page at-rule block with including declarations.
4133
- *
4134
- * Found @page at-rule blocks will add a {@link CssAtPageStartToken} and {@link CssAtPageEndToken} to the
4135
- * parser; including declarations as {@link CssAtPageDeclarationToken}.
4136
- *
4137
- * @package CssMin/Parser/Plugins
4138
- * @link http://code.google.com/p/cssmin/
4139
- * @author Joe Scylla <joe.scylla@gmail.com>
4140
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4141
- * @license http://opensource.org/licenses/mit-license.php MIT License
4142
- * @version 3.0.1
4143
- */
4144
- class CssAtPageParserPlugin extends aCssParserPlugin
4145
- {
4146
- /**
4147
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
4148
- *
4149
- * @return array
4150
- */
4151
- public function getTriggerChars()
4152
- {
4153
- return array("@", "{", "}", ":", ";");
4154
- }
4155
- /**
4156
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
4157
- *
4158
- * @return array
4159
- */
4160
- public function getTriggerStates()
4161
- {
4162
- return array("T_DOCUMENT", "T_AT_PAGE::SELECTOR", "T_AT_PAGE", "T_AT_PAGE_DECLARATION");
4163
- }
4164
- /**
4165
- * Implements {@link aCssParserPlugin::parse()}.
4166
- *
4167
- * @param integer $index Current index
4168
- * @param string $char Current char
4169
- * @param string $previousChar Previous char
4170
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4171
- */
4172
- public function parse($index, $char, $previousChar, $state)
4173
- {
4174
- // Start of @page at-rule block
4175
- if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 5)) === "@page")
4176
- {
4177
- $this->parser->pushState("T_AT_PAGE::SELECTOR");
4178
- $this->parser->clearBuffer();
4179
- return $index + 5;
4180
- }
4181
- // Start of @page declarations
4182
- elseif ($char === "{" && $state === "T_AT_PAGE::SELECTOR")
4183
- {
4184
- $selector = $this->parser->getAndClearBuffer("{");
4185
- $this->parser->setState("T_AT_PAGE");
4186
- $this->parser->clearBuffer();
4187
- $this->parser->appendToken(new CssAtPageStartToken($selector));
4188
- }
4189
- // Start of @page declaration
4190
- elseif ($char === ":" && $state === "T_AT_PAGE")
4191
- {
4192
- $this->parser->pushState("T_AT_PAGE_DECLARATION");
4193
- $this->buffer = $this->parser->getAndClearBuffer(":", true);
4194
- }
4195
- // Unterminated @font-face declaration
4196
- elseif ($char === ":" && $state === "T_AT_PAGE_DECLARATION")
4197
- {
4198
- // Ignore Internet Explorer filter declarations
4199
- if ($this->buffer === "filter")
4200
- {
4201
- return false;
4202
- }
4203
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @page declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
4204
- }
4205
- // End of @page declaration
4206
- elseif (($char === ";" || $char === "}") && $state == "T_AT_PAGE_DECLARATION")
4207
- {
4208
- $value = $this->parser->getAndClearBuffer(";}");
4209
- if (strtolower(substr($value, -10, 10)) == "!important")
4210
- {
4211
- $value = trim(substr($value, 0, -10));
4212
- $isImportant = true;
4213
- }
4214
- else
4215
- {
4216
- $isImportant = false;
4217
- }
4218
- $this->parser->popState();
4219
- $this->parser->appendToken(new CssAtPageDeclarationToken($this->buffer, $value, $isImportant));
4220
- // --
4221
- if ($char === "}")
4222
- {
4223
- $this->parser->popState();
4224
- $this->parser->appendToken(new CssAtPageEndToken());
4225
- }
4226
- $this->buffer = "";
4227
- }
4228
- // End of @page at-rule block
4229
- elseif ($char === "}" && $state === "T_AT_PAGE")
4230
- {
4231
- $this->parser->popState();
4232
- $this->parser->clearBuffer();
4233
- $this->parser->appendToken(new CssAtPageEndToken());
4234
- }
4235
- else
4236
- {
4237
- return false;
4238
- }
4239
- return true;
4240
- }
4241
- }
4242
-
4243
- /**
4244
- * This {@link aCssToken CSS token} represents the end of a @page at-rule block.
4245
- *
4246
- * @package CssMin/Tokens
4247
- * @link http://code.google.com/p/cssmin/
4248
- * @author Joe Scylla <joe.scylla@gmail.com>
4249
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4250
- * @license http://opensource.org/licenses/mit-license.php MIT License
4251
- * @version 3.0.1
4252
- */
4253
- class CssAtPageEndToken extends aCssAtBlockEndToken
4254
- {
4255
-
4256
- }
4257
-
4258
- /**
4259
- * This {@link aCssToken CSS token} represents a declaration of a @page at-rule block.
4260
- *
4261
- * @package CssMin/Tokens
4262
- * @link http://code.google.com/p/cssmin/
4263
- * @author Joe Scylla <joe.scylla@gmail.com>
4264
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4265
- * @license http://opensource.org/licenses/mit-license.php MIT License
4266
- * @version 3.0.1
4267
- */
4268
- class CssAtPageDeclarationToken extends aCssDeclarationToken
4269
- {
4270
-
4271
- }
4272
-
4273
- /**
4274
- * This {@link aCssToken CSS token} represents the start of a @media at-rule block.
4275
- *
4276
- * @package CssMin/Tokens
4277
- * @link http://code.google.com/p/cssmin/
4278
- * @author Joe Scylla <joe.scylla@gmail.com>
4279
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4280
- * @license http://opensource.org/licenses/mit-license.php MIT License
4281
- * @version 3.0.1
4282
- */
4283
- class CssAtMediaStartToken extends aCssAtBlockStartToken
4284
- {
4285
- /**
4286
- * Sets the properties of the @media at-rule.
4287
- *
4288
- * @param array $mediaTypes Media types
4289
- * @return void
4290
- */
4291
- public function __construct(array $mediaTypes = array())
4292
- {
4293
- $this->MediaTypes = $mediaTypes;
4294
- }
4295
- /**
4296
- * Implements {@link aCssToken::__toString()}.
4297
- *
4298
- * @return string
4299
- */
4300
- public function __toString()
4301
- {
4302
- return "@media " . implode(",", $this->MediaTypes) . "{";
4303
- }
4304
- }
4305
-
4306
- /**
4307
- * {@link aCssParserPlugin Parser plugin} for parsing @media at-rule block.
4308
- *
4309
- * Found @media at-rule blocks will add a {@link CssAtMediaStartToken} and {@link CssAtMediaEndToken} to the parser.
4310
- * This plugin will also set the the current media types using {@link CssParser::setMediaTypes()} and
4311
- * {@link CssParser::unsetMediaTypes()}.
4312
- *
4313
- * @package CssMin/Parser/Plugins
4314
- * @link http://code.google.com/p/cssmin/
4315
- * @author Joe Scylla <joe.scylla@gmail.com>
4316
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4317
- * @license http://opensource.org/licenses/mit-license.php MIT License
4318
- * @version 3.0.1
4319
- */
4320
- class CssAtMediaParserPlugin extends aCssParserPlugin
4321
- {
4322
- /**
4323
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
4324
- *
4325
- * @return array
4326
- */
4327
- public function getTriggerChars()
4328
- {
4329
- return array("@", "{", "}");
4330
- }
4331
- /**
4332
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
4333
- *
4334
- * @return array
4335
- */
4336
- public function getTriggerStates()
4337
- {
4338
- return array("T_DOCUMENT", "T_AT_MEDIA::PREPARE", "T_AT_MEDIA");
4339
- }
4340
- /**
4341
- * Implements {@link aCssParserPlugin::parse()}.
4342
- *
4343
- * @param integer $index Current index
4344
- * @param string $char Current char
4345
- * @param string $previousChar Previous char
4346
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4347
- */
4348
- public function parse($index, $char, $previousChar, $state)
4349
- {
4350
- if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 6)) === "@media")
4351
- {
4352
- $this->parser->pushState("T_AT_MEDIA::PREPARE");
4353
- $this->parser->clearBuffer();
4354
- return $index + 6;
4355
- }
4356
- elseif ($char === "{" && $state === "T_AT_MEDIA::PREPARE")
4357
- {
4358
- $mediaTypes = array_filter(array_map("trim", explode(",", $this->parser->getAndClearBuffer("{"))));
4359
- $this->parser->setMediaTypes($mediaTypes);
4360
- $this->parser->setState("T_AT_MEDIA");
4361
- $this->parser->appendToken(new CssAtMediaStartToken($mediaTypes));
4362
- }
4363
- elseif ($char === "}" && $state === "T_AT_MEDIA")
4364
- {
4365
- $this->parser->appendToken(new CssAtMediaEndToken());
4366
- $this->parser->clearBuffer();
4367
- $this->parser->unsetMediaTypes();
4368
- $this->parser->popState();
4369
- }
4370
- else
4371
- {
4372
- return false;
4373
- }
4374
- return true;
4375
- }
4376
- }
4377
-
4378
- /**
4379
- * This {@link aCssToken CSS token} represents the end of a @media at-rule block.
4380
- *
4381
- * @package CssMin/Tokens
4382
- * @link http://code.google.com/p/cssmin/
4383
- * @author Joe Scylla <joe.scylla@gmail.com>
4384
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4385
- * @license http://opensource.org/licenses/mit-license.php MIT License
4386
- * @version 3.0.1
4387
- */
4388
- class CssAtMediaEndToken extends aCssAtBlockEndToken
4389
- {
4390
-
4391
- }
4392
-
4393
- /**
4394
- * This {@link aCssToken CSS token} represents the start of a @keyframes at-rule block.
4395
- *
4396
- * @package CssMin/Tokens
4397
- * @link http://code.google.com/p/cssmin/
4398
- * @author Joe Scylla <joe.scylla@gmail.com>
4399
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4400
- * @license http://opensource.org/licenses/mit-license.php MIT License
4401
- * @version 3.0.1
4402
- */
4403
- class CssAtKeyframesStartToken extends aCssAtBlockStartToken
4404
- {
4405
- /**
4406
- * Name of the at-rule.
4407
- *
4408
- * @var string
4409
- */
4410
- public $AtRuleName = "keyframes";
4411
- /**
4412
- * Name
4413
- *
4414
- * @var string
4415
- */
4416
- public $Name = "";
4417
- /**
4418
- * Sets the properties of the @page at-rule.
4419
- *
4420
- * @param string $selector Selector
4421
- * @return void
4422
- */
4423
- public function __construct($name, $atRuleName = null)
4424
- {
4425
- $this->Name = $name;
4426
- if (!is_null($atRuleName))
4427
- {
4428
- $this->AtRuleName = $atRuleName;
4429
- }
4430
- }
4431
- /**
4432
- * Implements {@link aCssToken::__toString()}.
4433
- *
4434
- * @return string
4435
- */
4436
- public function __toString()
4437
- {
4438
- return "@" . $this->AtRuleName . " \"" . $this->Name . "\"{";
4439
- }
4440
- }
4441
-
4442
- /**
4443
- * This {@link aCssToken CSS token} represents the start of a ruleset of a @keyframes at-rule block.
4444
- *
4445
- * @package CssMin/Tokens
4446
- * @link http://code.google.com/p/cssmin/
4447
- * @author Joe Scylla <joe.scylla@gmail.com>
4448
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4449
- * @license http://opensource.org/licenses/mit-license.php MIT License
4450
- * @version 3.0.1
4451
- */
4452
- class CssAtKeyframesRulesetStartToken extends aCssRulesetStartToken
4453
- {
4454
- /**
4455
- * Array of selectors.
4456
- *
4457
- * @var array
4458
- */
4459
- public $Selectors = array();
4460
- /**
4461
- * Set the properties of a ruleset token.
4462
- *
4463
- * @param array $selectors Selectors of the ruleset
4464
- * @return void
4465
- */
4466
- public function __construct(array $selectors = array())
4467
- {
4468
- $this->Selectors = $selectors;
4469
- }
4470
- /**
4471
- * Implements {@link aCssToken::__toString()}.
4472
- *
4473
- * @return string
4474
- */
4475
- public function __toString()
4476
- {
4477
- return implode(",", $this->Selectors) . "{";
4478
- }
4479
- }
4480
-
4481
- /**
4482
- * This {@link aCssToken CSS token} represents the end of a ruleset of a @keyframes at-rule block.
4483
- *
4484
- * @package CssMin/Tokens
4485
- * @link http://code.google.com/p/cssmin/
4486
- * @author Joe Scylla <joe.scylla@gmail.com>
4487
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4488
- * @license http://opensource.org/licenses/mit-license.php MIT License
4489
- * @version 3.0.1
4490
- */
4491
- class CssAtKeyframesRulesetEndToken extends aCssRulesetEndToken
4492
- {
4493
-
4494
- }
4495
-
4496
- /**
4497
- * This {@link aCssToken CSS token} represents a ruleset declaration of a @keyframes at-rule block.
4498
- *
4499
- * @package CssMin/Tokens
4500
- * @link http://code.google.com/p/cssmin/
4501
- * @author Joe Scylla <joe.scylla@gmail.com>
4502
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4503
- * @license http://opensource.org/licenses/mit-license.php MIT License
4504
- * @version 3.0.1
4505
- */
4506
- class CssAtKeyframesRulesetDeclarationToken extends aCssDeclarationToken
4507
- {
4508
-
4509
- }
4510
-
4511
- /**
4512
- * {@link aCssParserPlugin Parser plugin} for parsing @keyframes at-rule blocks, rulesets and declarations.
4513
- *
4514
- * @package CssMin/Parser/Plugins
4515
- * @link http://code.google.com/p/cssmin/
4516
- * @author Joe Scylla <joe.scylla@gmail.com>
4517
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4518
- * @license http://opensource.org/licenses/mit-license.php MIT License
4519
- * @version 3.0.1
4520
- */
4521
- class CssAtKeyframesParserPlugin extends aCssParserPlugin
4522
- {
4523
- /**
4524
- * @var string Keyword
4525
- */
4526
- private $atRuleName = "";
4527
- /**
4528
- * Selectors.
4529
- *
4530
- * @var array
4531
- */
4532
- private $selectors = array();
4533
- /**
4534
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
4535
- *
4536
- * @return array
4537
- */
4538
- public function getTriggerChars()
4539
- {
4540
- return array("@", "{", "}", ":", ",", ";");
4541
- }
4542
- /**
4543
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
4544
- *
4545
- * @return array
4546
- */
4547
- public function getTriggerStates()
4548
- {
4549
- return array("T_DOCUMENT", "T_AT_KEYFRAMES::NAME", "T_AT_KEYFRAMES", "T_AT_KEYFRAMES_RULESETS", "T_AT_KEYFRAMES_RULESET", "T_AT_KEYFRAMES_RULESET_DECLARATION");
4550
- }
4551
- /**
4552
- * Implements {@link aCssParserPlugin::parse()}.
4553
- *
4554
- * @param integer $index Current index
4555
- * @param string $char Current char
4556
- * @param string $previousChar Previous char
4557
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4558
- */
4559
- public function parse($index, $char, $previousChar, $state)
4560
- {
4561
- // Start of @keyframes at-rule block
4562
- if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@keyframes")
4563
- {
4564
- $this->atRuleName = "keyframes";
4565
- $this->parser->pushState("T_AT_KEYFRAMES::NAME");
4566
- $this->parser->clearBuffer();
4567
- return $index + 10;
4568
- }
4569
- // Start of @keyframes at-rule block (@-moz-keyframes)
4570
- elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 15)) === "@-moz-keyframes")
4571
- {
4572
- $this->atRuleName = "-moz-keyframes";
4573
- $this->parser->pushState("T_AT_KEYFRAMES::NAME");
4574
- $this->parser->clearBuffer();
4575
- return $index + 15;
4576
- }
4577
- // Start of @keyframes at-rule block (@-webkit-keyframes)
4578
- elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 18)) === "@-webkit-keyframes")
4579
- {
4580
- $this->atRuleName = "-webkit-keyframes";
4581
- $this->parser->pushState("T_AT_KEYFRAMES::NAME");
4582
- $this->parser->clearBuffer();
4583
- return $index + 18;
4584
- }
4585
- // Start of @keyframes rulesets
4586
- elseif ($char === "{" && $state === "T_AT_KEYFRAMES::NAME")
4587
- {
4588
- $name = $this->parser->getAndClearBuffer("{\"'");
4589
- $this->parser->setState("T_AT_KEYFRAMES_RULESETS");
4590
- $this->parser->clearBuffer();
4591
- $this->parser->appendToken(new CssAtKeyframesStartToken($name, $this->atRuleName));
4592
- }
4593
- // Start of @keyframe ruleset and selectors
4594
- if ($char === "," && $state === "T_AT_KEYFRAMES_RULESETS")
4595
- {
4596
- $this->selectors[] = $this->parser->getAndClearBuffer(",{");
4597
- }
4598
- // Start of a @keyframes ruleset
4599
- elseif ($char === "{" && $state === "T_AT_KEYFRAMES_RULESETS")
4600
- {
4601
- if ($this->parser->getBuffer() !== "")
4602
- {
4603
- $this->selectors[] = $this->parser->getAndClearBuffer(",{");
4604
- $this->parser->pushState("T_AT_KEYFRAMES_RULESET");
4605
- $this->parser->appendToken(new CssAtKeyframesRulesetStartToken($this->selectors));
4606
- $this->selectors = array();
4607
- }
4608
- }
4609
- // Start of @keyframes ruleset declaration
4610
- elseif ($char === ":" && $state === "T_AT_KEYFRAMES_RULESET")
4611
- {
4612
- $this->parser->pushState("T_AT_KEYFRAMES_RULESET_DECLARATION");
4613
- $this->buffer = $this->parser->getAndClearBuffer(":;", true);
4614
- }
4615
- // Unterminated @keyframes ruleset declaration
4616
- elseif ($char === ":" && $state === "T_AT_KEYFRAMES_RULESET_DECLARATION")
4617
- {
4618
- // Ignore Internet Explorer filter declarations
4619
- if ($this->buffer === "filter")
4620
- {
4621
- return false;
4622
- }
4623
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @keyframes ruleset declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
4624
- }
4625
- // End of declaration
4626
- elseif (($char === ";" || $char === "}") && $state === "T_AT_KEYFRAMES_RULESET_DECLARATION")
4627
- {
4628
- $value = $this->parser->getAndClearBuffer(";}");
4629
- if (strtolower(substr($value, -10, 10)) === "!important")
4630
- {
4631
- $value = trim(substr($value, 0, -10));
4632
- $isImportant = true;
4633
- }
4634
- else
4635
- {
4636
- $isImportant = false;
4637
- }
4638
- $this->parser->popState();
4639
- $this->parser->appendToken(new CssAtKeyframesRulesetDeclarationToken($this->buffer, $value, $isImportant));
4640
- // Declaration ends with a right curly brace; so we have to end the ruleset
4641
- if ($char === "}")
4642
- {
4643
- $this->parser->appendToken(new CssAtKeyframesRulesetEndToken());
4644
- $this->parser->popState();
4645
- }
4646
- $this->buffer = "";
4647
- }
4648
- // End of @keyframes ruleset
4649
- elseif ($char === "}" && $state === "T_AT_KEYFRAMES_RULESET")
4650
- {
4651
- $this->parser->clearBuffer();
4652
-
4653
- $this->parser->popState();
4654
- $this->parser->appendToken(new CssAtKeyframesRulesetEndToken());
4655
- }
4656
- // End of @keyframes rulesets
4657
- elseif ($char === "}" && $state === "T_AT_KEYFRAMES_RULESETS")
4658
- {
4659
- $this->parser->clearBuffer();
4660
- $this->parser->popState();
4661
- $this->parser->appendToken(new CssAtKeyframesEndToken());
4662
- }
4663
- else
4664
- {
4665
- return false;
4666
- }
4667
- return true;
4668
- }
4669
- }
4670
-
4671
- /**
4672
- * This {@link aCssToken CSS token} represents the end of a @keyframes at-rule block.
4673
- *
4674
- * @package CssMin/Tokens
4675
- * @link http://code.google.com/p/cssmin/
4676
- * @author Joe Scylla <joe.scylla@gmail.com>
4677
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4678
- * @license http://opensource.org/licenses/mit-license.php MIT License
4679
- * @version 3.0.1
4680
- */
4681
- class CssAtKeyframesEndToken extends aCssAtBlockEndToken
4682
- {
4683
-
4684
- }
4685
-
4686
- /**
4687
- * This {@link aCssToken CSS token} represents a @import at-rule.
4688
- *
4689
- * @package CssMin/Tokens
4690
- * @link http://code.google.com/p/cssmin/
4691
- * @author Joe Scylla <joe.scylla@gmail.com>
4692
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4693
- * @license http://opensource.org/licenses/mit-license.php MIT License
4694
- * @version 3.0.1.b1 (2001-02-22)
4695
- */
4696
- class CssAtImportToken extends aCssToken
4697
- {
4698
- /**
4699
- * Import path of the @import at-rule.
4700
- *
4701
- * @var string
4702
- */
4703
- public $Import = "";
4704
- /**
4705
- * Media types of the @import at-rule.
4706
- *
4707
- * @var array
4708
- */
4709
- public $MediaTypes = array();
4710
- /**
4711
- * Set the properties of a @import at-rule token.
4712
- *
4713
- * @param string $import Import path
4714
- * @param array $mediaTypes Media types
4715
- * @return void
4716
- */
4717
- public function __construct($import, $mediaTypes)
4718
- {
4719
- $this->Import = $import;
4720
- $this->MediaTypes = $mediaTypes ? $mediaTypes : array();
4721
- }
4722
- /**
4723
- * Implements {@link aCssToken::__toString()}.
4724
- *
4725
- * @return string
4726
- */
4727
- public function __toString()
4728
- {
4729
- return "@import \"" . $this->Import . "\"" . (count($this->MediaTypes) > 0 ? " " . implode(",", $this->MediaTypes) : ""). ";";
4730
- }
4731
- }
4732
-
4733
- /**
4734
- * {@link aCssParserPlugin Parser plugin} for parsing @import at-rule.
4735
- *
4736
- * If a @import at-rule was found this plugin will add a {@link CssAtImportToken} to the parser.
4737
- *
4738
- * @package CssMin/Parser/Plugins
4739
- * @link http://code.google.com/p/cssmin/
4740
- * @author Joe Scylla <joe.scylla@gmail.com>
4741
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4742
- * @license http://opensource.org/licenses/mit-license.php MIT License
4743
- * @version 3.0.1
4744
- */
4745
- class CssAtImportParserPlugin extends aCssParserPlugin
4746
- {
4747
- /**
4748
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
4749
- *
4750
- * @return array
4751
- */
4752
- public function getTriggerChars()
4753
- {
4754
- return array("@", ";", ",", "\n");
4755
- }
4756
- /**
4757
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
4758
- *
4759
- * @return array
4760
- */
4761
- public function getTriggerStates()
4762
- {
4763
- return array("T_DOCUMENT", "T_AT_IMPORT");
4764
- }
4765
- /**
4766
- * Implements {@link aCssParserPlugin::parse()}.
4767
- *
4768
- * @param integer $index Current index
4769
- * @param string $char Current char
4770
- * @param string $previousChar Previous char
4771
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4772
- */
4773
- public function parse($index, $char, $previousChar, $state)
4774
- {
4775
- if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 7)) === "@import")
4776
- {
4777
- $this->parser->pushState("T_AT_IMPORT");
4778
- $this->parser->clearBuffer();
4779
- return $index + 7;
4780
- }
4781
- elseif (($char === ";" || $char === "\n") && $state === "T_AT_IMPORT")
4782
- {
4783
- $this->buffer = $this->parser->getAndClearBuffer(";");
4784
- $pos = false;
4785
- foreach (array(")", "\"", "'") as $needle)
4786
- {
4787
- if (($pos = strrpos($this->buffer, $needle)) !== false)
4788
- {
4789
- break;
4790
- }
4791
- }
4792
- $import = substr($this->buffer, 0, $pos + 1);
4793
- if (stripos($import, "url(") === 0)
4794
- {
4795
- $import = substr($import, 4, -1);
4796
- }
4797
- $import = trim($import, " \t\n\r\0\x0B'\"");
4798
- $mediaTypes = array_filter(array_map("trim", explode(",", trim(substr($this->buffer, $pos + 1), " \t\n\r\0\x0B{"))));
4799
- if ($pos)
4800
- {
4801
- $this->parser->appendToken(new CssAtImportToken($import, $mediaTypes));
4802
- }
4803
- else
4804
- {
4805
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Invalid @import at-rule syntax", $this->parser->buffer));
4806
- }
4807
- $this->parser->popState();
4808
- }
4809
- else
4810
- {
4811
- return false;
4812
- }
4813
- return true;
4814
- }
4815
- }
4816
-
4817
- /**
4818
- * This {@link aCssToken CSS token} represents the start of a @font-face at-rule block.
4819
- *
4820
- * @package CssMin/Tokens
4821
- * @link http://code.google.com/p/cssmin/
4822
- * @author Joe Scylla <joe.scylla@gmail.com>
4823
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4824
- * @license http://opensource.org/licenses/mit-license.php MIT License
4825
- * @version 3.0.1
4826
- */
4827
- class CssAtFontFaceStartToken extends aCssAtBlockStartToken
4828
- {
4829
- /**
4830
- * Implements {@link aCssToken::__toString()}.
4831
- *
4832
- * @return string
4833
- */
4834
- public function __toString()
4835
- {
4836
- return "@font-face{";
4837
- }
4838
- }
4839
-
4840
- /**
4841
- * {@link aCssParserPlugin Parser plugin} for parsing @font-face at-rule block with including declarations.
4842
- *
4843
- * Found @font-face at-rule blocks will add a {@link CssAtFontFaceStartToken} and {@link CssAtFontFaceEndToken} to the
4844
- * parser; including declarations as {@link CssAtFontFaceDeclarationToken}.
4845
- *
4846
- * @package CssMin/Parser/Plugins
4847
- * @link http://code.google.com/p/cssmin/
4848
- * @author Joe Scylla <joe.scylla@gmail.com>
4849
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4850
- * @license http://opensource.org/licenses/mit-license.php MIT License
4851
- * @version 3.0.1
4852
- */
4853
- class CssAtFontFaceParserPlugin extends aCssParserPlugin
4854
- {
4855
- /**
4856
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
4857
- *
4858
- * @return array
4859
- */
4860
- public function getTriggerChars()
4861
- {
4862
- return array("@", "{", "}", ":", ";");
4863
- }
4864
- /**
4865
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
4866
- *
4867
- * @return array
4868
- */
4869
- public function getTriggerStates()
4870
- {
4871
- return array("T_DOCUMENT", "T_AT_FONT_FACE::PREPARE", "T_AT_FONT_FACE", "T_AT_FONT_FACE_DECLARATION");
4872
- }
4873
- /**
4874
- * Implements {@link aCssParserPlugin::parse()}.
4875
- *
4876
- * @param integer $index Current index
4877
- * @param string $char Current char
4878
- * @param string $previousChar Previous char
4879
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4880
- */
4881
- public function parse($index, $char, $previousChar, $state)
4882
- {
4883
- // Start of @font-face at-rule block
4884
- if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@font-face")
4885
- {
4886
- $this->parser->pushState("T_AT_FONT_FACE::PREPARE");
4887
- $this->parser->clearBuffer();
4888
- return $index + 10;
4889
- }
4890
- // Start of @font-face declarations
4891
- elseif ($char === "{" && $state === "T_AT_FONT_FACE::PREPARE")
4892
- {
4893
- $this->parser->setState("T_AT_FONT_FACE");
4894
- $this->parser->clearBuffer();
4895
- $this->parser->appendToken(new CssAtFontFaceStartToken());
4896
- }
4897
- // Start of @font-face declaration
4898
- elseif ($char === ":" && $state === "T_AT_FONT_FACE")
4899
- {
4900
- $this->parser->pushState("T_AT_FONT_FACE_DECLARATION");
4901
- $this->buffer = $this->parser->getAndClearBuffer(":", true);
4902
- }
4903
- // Unterminated @font-face declaration
4904
- elseif ($char === ":" && $state === "T_AT_FONT_FACE_DECLARATION")
4905
- {
4906
- // Ignore Internet Explorer filter declarations
4907
- if ($this->buffer === "filter")
4908
- {
4909
- return false;
4910
- }
4911
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @font-face declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
4912
- }
4913
- // End of @font-face declaration
4914
- elseif (($char === ";" || $char === "}") && $state === "T_AT_FONT_FACE_DECLARATION")
4915
- {
4916
- $value = $this->parser->getAndClearBuffer(";}");
4917
- if (strtolower(substr($value, -10, 10)) === "!important")
4918
- {
4919
- $value = trim(substr($value, 0, -10));
4920
- $isImportant = true;
4921
- }
4922
- else
4923
- {
4924
- $isImportant = false;
4925
- }
4926
- $this->parser->popState();
4927
- $this->parser->appendToken(new CssAtFontFaceDeclarationToken($this->buffer, $value, $isImportant));
4928
- $this->buffer = "";
4929
- // --
4930
- if ($char === "}")
4931
- {
4932
- $this->parser->appendToken(new CssAtFontFaceEndToken());
4933
- $this->parser->popState();
4934
- }
4935
- }
4936
- // End of @font-face at-rule block
4937
- elseif ($char === "}" && $state === "T_AT_FONT_FACE")
4938
- {
4939
- $this->parser->appendToken(new CssAtFontFaceEndToken());
4940
- $this->parser->clearBuffer();
4941
- $this->parser->popState();
4942
- }
4943
- else
4944
- {
4945
- return false;
4946
- }
4947
- return true;
4948
- }
4949
- }
4950
-
4951
- /**
4952
- * This {@link aCssToken CSS token} represents the end of a @font-face at-rule block.
4953
- *
4954
- * @package CssMin/Tokens
4955
- * @link http://code.google.com/p/cssmin/
4956
- * @author Joe Scylla <joe.scylla@gmail.com>
4957
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4958
- * @license http://opensource.org/licenses/mit-license.php MIT License
4959
- * @version 3.0.1
4960
- */
4961
- class CssAtFontFaceEndToken extends aCssAtBlockEndToken
4962
- {
4963
-
4964
- }
4965
-
4966
- /**
4967
- * This {@link aCssToken CSS token} represents a declaration of a @font-face at-rule block.
4968
- *
4969
- * @package CssMin/Tokens
4970
- * @link http://code.google.com/p/cssmin/
4971
- * @author Joe Scylla <joe.scylla@gmail.com>
4972
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4973
- * @license http://opensource.org/licenses/mit-license.php MIT License
4974
- * @version 3.0.1
4975
- */
4976
- class CssAtFontFaceDeclarationToken extends aCssDeclarationToken
4977
- {
4978
-
4979
- }
4980
-
4981
- /**
4982
- * This {@link aCssToken CSS token} represents a @charset at-rule.
4983
- *
4984
- * @package CssMin/Tokens
4985
- * @link http://code.google.com/p/cssmin/
4986
- * @author Joe Scylla <joe.scylla@gmail.com>
4987
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4988
- * @license http://opensource.org/licenses/mit-license.php MIT License
4989
- * @version 3.0.1
4990
- */
4991
- class CssAtCharsetToken extends aCssToken
4992
- {
4993
- /**
4994
- * Charset of the @charset at-rule.
4995
- *
4996
- * @var string
4997
- */
4998
- public $Charset = "";
4999
- /**
5000
- * Set the properties of @charset at-rule token.
5001
- *
5002
- * @param string $charset Charset of the @charset at-rule token
5003
- * @return void
5004
- */
5005
- public function __construct($charset)
5006
- {
5007
- $this->Charset = $charset;
5008
- }
5009
- /**
5010
- * Implements {@link aCssToken::__toString()}.
5011
- *
5012
- * @return string
5013
- */
5014
- public function __toString()
5015
- {
5016
- return "@charset " . $this->Charset . ";";
5017
- }
5018
- }
5019
-
5020
- /**
5021
- * {@link aCssParserPlugin Parser plugin} for parsing @charset at-rule.
5022
- *
5023
- * If a @charset at-rule was found this plugin will add a {@link CssAtCharsetToken} to the parser.
5024
- *
5025
- * @package CssMin/Parser/Plugins
5026
- * @link http://code.google.com/p/cssmin/
5027
- * @author Joe Scylla <joe.scylla@gmail.com>
5028
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
5029
- * @license http://opensource.org/licenses/mit-license.php MIT License
5030
- * @version 3.0.1
5031
- */
5032
- class CssAtCharsetParserPlugin extends aCssParserPlugin
5033
- {
5034
- /**
5035
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
5036
- *
5037
- * @return array
5038
- */
5039
- public function getTriggerChars()
5040
- {
5041
- return array("@", ";", "\n");
5042
- }
5043
- /**
5044
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
5045
- *
5046
- * @return array
5047
- */
5048
- public function getTriggerStates()
5049
- {
5050
- return array("T_DOCUMENT", "T_AT_CHARSET");
5051
- }
5052
- /**
5053
- * Implements {@link aCssParserPlugin::parse()}.
5054
- *
5055
- * @param integer $index Current index
5056
- * @param string $char Current char
5057
- * @param string $previousChar Previous char
5058
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
5059
- */
5060
- public function parse($index, $char, $previousChar, $state)
5061
- {
5062
- if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 8)) === "@charset")
5063
- {
5064
- $this->parser->pushState("T_AT_CHARSET");
5065
- $this->parser->clearBuffer();
5066
- return $index + 8;
5067
- }
5068
- elseif (($char === ";" || $char === "\n") && $state === "T_AT_CHARSET")
5069
- {
5070
- $charset = $this->parser->getAndClearBuffer(";");
5071
- $this->parser->popState();
5072
- $this->parser->appendToken(new CssAtCharsetToken($charset));
5073
- }
5074
- else
5075
- {
5076
- return false;
5077
- }
5078
- return true;
5079
- }
5080
- }
5081
-
5082
- ?>
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
+ /*!
4
+ * cssmin.php v2.4.8-4
5
+ * Author: Tubal Martin - http://tubalmartin.me/
6
+ * Repo: https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port
7
+ *
8
+ * This is a PHP port of the CSS minification tool distributed with YUICompressor,
9
+ * itself a port of the cssmin utility by Isaac Schlueter - http://foohack.com/
10
+ * Permission is hereby granted to use the PHP version under the same
11
+ * conditions as the YUICompressor.
12
+ */
13
+
14
+ /*!
15
+ * YUI Compressor
16
+ * http://developer.yahoo.com/yui/compressor/
17
+ * Author: Julien Lecomte - http://www.julienlecomte.net/
18
+ * Copyright (c) 2013 Yahoo! Inc. All rights reserved.
19
+ * The copyrights embodied in the content of this file are licensed
20
+ * by Yahoo! Inc. under the BSD (revised) open source license.
21
+ */
22
+
23
+ class a3_CSSmin
24
+ {
25
+ const NL = '___YUICSSMIN_PRESERVED_NL___';
26
+ const TOKEN = '___YUICSSMIN_PRESERVED_TOKEN_';
27
+ const COMMENT = '___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_';
28
+ const CLASSCOLON = '___YUICSSMIN_PSEUDOCLASSCOLON___';
29
+ const QUERY_FRACTION = '___YUICSSMIN_QUERY_FRACTION___';
30
+
31
+ private $comments;
32
+ private $preserved_tokens;
33
+ private $memory_limit;
34
+ private $max_execution_time;
35
+ private $pcre_backtrack_limit;
36
+ private $pcre_recursion_limit;
37
+ private $raise_php_limits;
38
+
39
+ /**
40
+ * @param bool|int $raise_php_limits
41
+ * If true, PHP settings will be raised if needed
42
+ */
43
+ public function __construct($raise_php_limits = TRUE)
44
+ {
45
+ // Set suggested PHP limits
46
+ $this->memory_limit = 128 * 1048576; // 128MB in bytes
47
+ $this->max_execution_time = 60; // 1 min
48
+ $this->pcre_backtrack_limit = 1000 * 1000;
49
+ $this->pcre_recursion_limit = 500 * 1000;
50
+
51
+ $this->raise_php_limits = (bool) $raise_php_limits;
52
+ }
53
+
54
+ /**
55
+ * Minify a string of CSS
56
+ * @param string $css
57
+ * @param int|bool $linebreak_pos
58
+ * @return string
59
+ */
60
+ public function run($css = '', $linebreak_pos = FALSE)
61
+ {
62
+ if (empty($css)) {
63
+ return '';
64
+ }
65
+
66
+ if ($this->raise_php_limits) {
67
+ $this->do_raise_php_limits();
68
+ }
69
+
70
+ $this->comments = array();
71
+ $this->preserved_tokens = array();
72
+
73
+ $start_index = 0;
74
+ $length = strlen($css);
75
+
76
+ $css = $this->extract_data_urls($css);
77
+
78
+ // collect all comment blocks...
79
+ while (($start_index = $this->index_of($css, '/*', $start_index)) >= 0) {
80
+ $end_index = $this->index_of($css, '*/', $start_index + 2);
81
+ if ($end_index < 0) {
82
+ $end_index = $length;
83
+ }
84
+ $comment_found = $this->str_slice($css, $start_index + 2, $end_index);
85
+ $this->comments[] = $comment_found;
86
+ $comment_preserve_string = self::COMMENT . (count($this->comments) - 1) . '___';
87
+ $css = $this->str_slice($css, 0, $start_index + 2) . $comment_preserve_string . $this->str_slice($css, $end_index);
88
+ // Set correct start_index: Fixes issue #2528130
89
+ $start_index = $end_index + 2 + strlen($comment_preserve_string) - strlen($comment_found);
90
+ }
91
+
92
+ // preserve strings so their content doesn't get accidentally minified
93
+ $css = preg_replace_callback('/(?:"(?:[^\\\\"]|\\\\.|\\\\)*")|'."(?:'(?:[^\\\\']|\\\\.|\\\\)*')/S", array($this, 'replace_string'), $css);
94
+
95
+ // Let's divide css code in chunks of 5.000 chars aprox.
96
+ // Reason: PHP's PCRE functions like preg_replace have a "backtrack limit"
97
+ // of 100.000 chars by default (php < 5.3.7) so if we're dealing with really
98
+ // long strings and a (sub)pattern matches a number of chars greater than
99
+ // the backtrack limit number (i.e. /(.*)/s) PCRE functions may fail silently
100
+ // returning NULL and $css would be empty.
101
+ $charset = '';
102
+ $charset_regexp = '/(@charset)( [^;]+;)/i';
103
+ $css_chunks = array();
104
+ $css_chunk_length = 5000; // aprox size, not exact
105
+ $start_index = 0;
106
+ $i = $css_chunk_length; // save initial iterations
107
+ $l = strlen($css);
108
+
109
+
110
+ // if the number of characters is 5000 or less, do not chunk
111
+ if ($l <= $css_chunk_length) {
112
+ $css_chunks[] = $css;
113
+ } else {
114
+ // chunk css code securely
115
+ while ($i < $l) {
116
+ $i += 50; // save iterations
117
+ if ($l - $start_index <= $css_chunk_length || $i >= $l) {
118
+ $css_chunks[] = $this->str_slice($css, $start_index);
119
+ break;
120
+ }
121
+ if ($css[$i - 1] === '}' && $i - $start_index > $css_chunk_length) {
122
+ // If there are two ending curly braces }} separated or not by spaces,
123
+ // join them in the same chunk (i.e. @media blocks)
124
+ $next_chunk = substr($css, $i);
125
+ if (preg_match('/^\s*\}/', $next_chunk)) {
126
+ $i = $i + $this->index_of($next_chunk, '}') + 1;
127
+ }
128
+
129
+ $css_chunks[] = $this->str_slice($css, $start_index, $i);
130
+ $start_index = $i;
131
+ }
132
+ }
133
+ }
134
+
135
+ // Minify each chunk
136
+ for ($i = 0, $n = count($css_chunks); $i < $n; $i++) {
137
+ $css_chunks[$i] = $this->minify($css_chunks[$i], $linebreak_pos);
138
+ // Keep the first @charset at-rule found
139
+ if (empty($charset) && preg_match($charset_regexp, $css_chunks[$i], $matches)) {
140
+ $charset = strtolower($matches[1]) . $matches[2];
141
+ }
142
+ // Delete all @charset at-rules
143
+ $css_chunks[$i] = preg_replace($charset_regexp, '', $css_chunks[$i]);
144
+ }
145
+
146
+ // Update the first chunk and push the charset to the top of the file.
147
+ $css_chunks[0] = $charset . $css_chunks[0];
148
+
149
+ return implode('', $css_chunks);
150
+ }
151
+
152
+ /**
153
+ * Sets the memory limit for this script
154
+ * @param int|string $limit
155
+ */
156
+ public function set_memory_limit($limit)
157
+ {
158
+ $this->memory_limit = $this->normalize_int($limit);
159
+ }
160
+
161
+ /**
162
+ * Sets the maximum execution time for this script
163
+ * @param int|string $seconds
164
+ */
165
+ public function set_max_execution_time($seconds)
166
+ {
167
+ $this->max_execution_time = (int) $seconds;
168
+ }
169
+
170
+ /**
171
+ * Sets the PCRE backtrack limit for this script
172
+ * @param int $limit
173
+ */
174
+ public function set_pcre_backtrack_limit($limit)
175
+ {
176
+ $this->pcre_backtrack_limit = (int) $limit;
177
+ }
178
+
179
+ /**
180
+ * Sets the PCRE recursion limit for this script
181
+ * @param int $limit
182
+ */
183
+ public function set_pcre_recursion_limit($limit)
184
+ {
185
+ $this->pcre_recursion_limit = (int) $limit;
186
+ }
187
+
188
+ /**
189
+ * Try to configure PHP to use at least the suggested minimum settings
190
+ */
191
+ private function do_raise_php_limits()
192
+ {
193
+ $php_limits = array(
194
+ 'memory_limit' => $this->memory_limit,
195
+ 'max_execution_time' => $this->max_execution_time,
196
+ 'pcre.backtrack_limit' => $this->pcre_backtrack_limit,
197
+ 'pcre.recursion_limit' => $this->pcre_recursion_limit
198
+ );
199
+
200
+ // If current settings are higher respect them.
201
+ foreach ($php_limits as $name => $suggested) {
202
+ $current = $this->normalize_int(ini_get($name));
203
+ // memory_limit exception: allow -1 for "no memory limit".
204
+ if ($current > -1 && ($suggested == -1 || $current < $suggested)) {
205
+ ini_set($name, $suggested);
206
+ }
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Does bulk of the minification
212
+ * @param string $css
213
+ * @param int|bool $linebreak_pos
214
+ * @return string
215
+ */
216
+ private function minify($css, $linebreak_pos)
217
+ {
218
+ // strings are safe, now wrestle the comments
219
+ for ($i = 0, $max = count($this->comments); $i < $max; $i++) {
220
+
221
+ $token = $this->comments[$i];
222
+ $placeholder = '/' . self::COMMENT . $i . '___/';
223
+
224
+ // ! in the first position of the comment means preserve
225
+ // so push to the preserved tokens keeping the !
226
+ if (substr($token, 0, 1) === '!') {
227
+ $this->preserved_tokens[] = $token;
228
+ $token_tring = self::TOKEN . (count($this->preserved_tokens) - 1) . '___';
229
+ $css = preg_replace($placeholder, $token_tring, $css, 1);
230
+ // Preserve new lines for /*! important comments
231
+ $css = preg_replace('/\s*[\n\r\f]+\s*(\/\*'. $token_tring .')/S', self::NL.'$1', $css);
232
+ $css = preg_replace('/('. $token_tring .'\*\/)\s*[\n\r\f]+\s*/', '$1'.self::NL, $css);
233
+ continue;
234
+ }
235
+
236
+ // \ in the last position looks like hack for Mac/IE5
237
+ // shorten that to /*\*/ and the next one to /**/
238
+ if (substr($token, (strlen($token) - 1), 1) === '\\') {
239
+ $this->preserved_tokens[] = '\\';
240
+ $css = preg_replace($placeholder, self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
241
+ $i = $i + 1; // attn: advancing the loop
242
+ $this->preserved_tokens[] = '';
243
+ $css = preg_replace('/' . self::COMMENT . $i . '___/', self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
244
+ continue;
245
+ }
246
+
247
+ // keep empty comments after child selectors (IE7 hack)
248
+ // e.g. html >/**/ body
249
+ if (strlen($token) === 0) {
250
+ $start_index = $this->index_of($css, $this->str_slice($placeholder, 1, -1));
251
+ if ($start_index > 2) {
252
+ if (substr($css, $start_index - 3, 1) === '>') {
253
+ $this->preserved_tokens[] = '';
254
+ $css = preg_replace($placeholder, self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
255
+ }
256
+ }
257
+ }
258
+
259
+ // in all other cases kill the comment
260
+ $css = preg_replace('/\/\*' . $this->str_slice($placeholder, 1, -1) . '\*\//', '', $css, 1);
261
+ }
262
+
263
+
264
+ // Normalize all whitespace strings to single spaces. Easier to work with that way.
265
+ $css = preg_replace('/\s+/', ' ', $css);
266
+
267
+ // Fix IE7 issue on matrix filters which browser accept whitespaces between Matrix parameters
268
+ $css = preg_replace_callback('/\s*filter\:\s*progid:DXImageTransform\.Microsoft\.Matrix\(([^\)]+)\)/', array($this, 'preserve_old_IE_specific_matrix_definition'), $css);
269
+
270
+ // Shorten & preserve calculations calc(...) since spaces are important
271
+ $css = preg_replace_callback('/calc(\(((?:[^\(\)]+|(?1))*)\))/i', array($this, 'replace_calc'), $css);
272
+
273
+ // Replace positive sign from numbers preceded by : or a white-space before the leading space is removed
274
+ // +1.2em to 1.2em, +.8px to .8px, +2% to 2%
275
+ $css = preg_replace('/((?<!\\\\)\:|\s)\+(\.?\d+)/S', '$1$2', $css);
276
+
277
+ // Remove leading zeros from integer and float numbers preceded by : or a white-space
278
+ // 000.6 to .6, -0.8 to -.8, 0050 to 50, -01.05 to -1.05
279
+ $css = preg_replace('/((?<!\\\\)\:|\s)(\-?)0+(\.?\d+)/S', '$1$2$3', $css);
280
+
281
+ // Remove trailing zeros from float numbers preceded by : or a white-space
282
+ // -6.0100em to -6.01em, .0100 to .01, 1.200px to 1.2px
283
+ $css = preg_replace('/((?<!\\\\)\:|\s)(\-?)(\d?\.\d+?)0+([^\d])/S', '$1$2$3$4', $css);
284
+
285
+ // Remove trailing .0 -> -9.0 to -9
286
+ $css = preg_replace('/((?<!\\\\)\:|\s)(\-?\d+)\.0([^\d])/S', '$1$2$3', $css);
287
+
288
+ // Replace 0 length numbers with 0
289
+ $css = preg_replace('/((?<!\\\\)\:|\s)\-?\.?0+([^\d])/S', '${1}0$2', $css);
290
+
291
+ // Remove the spaces before the things that should not have spaces before them.
292
+ // But, be careful not to turn "p :link {...}" into "p:link{...}"
293
+ // Swap out any pseudo-class colons with the token, and then swap back.
294
+ $css = preg_replace_callback('/(?:^|\})[^\{]*\s+\:/', array($this, 'replace_colon'), $css);
295
+
296
+ // Remove spaces before the things that should not have spaces before them.
297
+ $css = preg_replace('/\s+([\!\{\}\;\:\>\+\(\)\]\~\=,])/', '$1', $css);
298
+
299
+ // Restore spaces for !important
300
+ $css = preg_replace('/\!important/i', ' !important', $css);
301
+
302
+ // bring back the colon
303
+ $css = preg_replace('/' . self::CLASSCOLON . '/', ':', $css);
304
+
305
+ // retain space for special IE6 cases
306
+ $css = preg_replace_callback('/\:first\-(line|letter)(\{|,)/i', array($this, 'lowercase_pseudo_first'), $css);
307
+
308
+ // no space after the end of a preserved comment
309
+ $css = preg_replace('/\*\/ /', '*/', $css);
310
+
311
+ // lowercase some popular @directives
312
+ $css = preg_replace_callback('/@(font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframe|media|page|namespace)/i', array($this, 'lowercase_directives'), $css);
313
+
314
+ // lowercase some more common pseudo-elements
315
+ $css = preg_replace_callback('/:(active|after|before|checked|disabled|empty|enabled|first-(?:child|of-type)|focus|hover|last-(?:child|of-type)|link|only-(?:child|of-type)|root|:selection|target|visited)/i', array($this, 'lowercase_pseudo_elements'), $css);
316
+
317
+ // lowercase some more common functions
318
+ $css = preg_replace_callback('/:(lang|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|(?:-(?:moz|webkit)-)?any)\(/i', array($this, 'lowercase_common_functions'), $css);
319
+
320
+ // lower case some common function that can be values
321
+ // NOTE: rgb() isn't useful as we replace with #hex later, as well as and() is already done for us
322
+ $css = preg_replace_callback('/([:,\( ]\s*)(attr|color-stop|from|rgba|to|url|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|max|min|(?:repeating-)?(?:linear|radial)-gradient)|-webkit-gradient)/iS', array($this, 'lowercase_common_functions_values'), $css);
323
+
324
+ // Put the space back in some cases, to support stuff like
325
+ // @media screen and (-webkit-min-device-pixel-ratio:0){
326
+ $css = preg_replace('/\band\(/i', 'and (', $css);
327
+
328
+ // Remove the spaces after the things that should not have spaces after them.
329
+ $css = preg_replace('/([\!\{\}\:;\>\+\(\[\~\=,])\s+/S', '$1', $css);
330
+
331
+ // remove unnecessary semicolons
332
+ $css = preg_replace('/;+\}/', '}', $css);
333
+
334
+ // Fix for issue: #2528146
335
+ // Restore semicolon if the last property is prefixed with a `*` (lte IE7 hack)
336
+ // to avoid issues on Symbian S60 3.x browsers.
337
+ $css = preg_replace('/(\*[a-z0-9\-]+\s*\:[^;\}]+)(\})/', '$1;$2', $css);
338
+
339
+ // Replace 0 <length> and 0 <percentage> values with 0.
340
+ // <length> data type: https://developer.mozilla.org/en-US/docs/Web/CSS/length
341
+ // <percentage> data type: https://developer.mozilla.org/en-US/docs/Web/CSS/percentage
342
+ $css = preg_replace('/([^\\\\]\:|\s)0(?:em|ex|ch|rem|vw|vh|vm|vmin|cm|mm|in|px|pt|pc|%)/iS', '${1}0', $css);
343
+
344
+ // 0% step in a keyframe? restore the % unit
345
+ $css = preg_replace_callback('/(@[a-z\-]*?keyframes[^\{]+\{)(.*?)(\}\})/iS', array($this, 'replace_keyframe_zero'), $css);
346
+
347
+ // Replace 0 0; or 0 0 0; or 0 0 0 0; with 0.
348
+ $css = preg_replace('/\:0(?: 0){1,3}(;|\}| \!)/', ':0$1', $css);
349
+
350
+ // Fix for issue: #2528142
351
+ // Replace text-shadow:0; with text-shadow:0 0 0;
352
+ $css = preg_replace('/(text-shadow\:0)(;|\}| \!)/i', '$1 0 0$2', $css);
353
+
354
+ // Replace background-position:0; with background-position:0 0;
355
+ // same for transform-origin
356
+ // Changing -webkit-mask-position: 0 0 to just a single 0 will result in the second parameter defaulting to 50% (center)
357
+ $css = preg_replace('/(background\-position|webkit-mask-position|(?:webkit|moz|o|ms|)\-?transform\-origin)\:0(;|\}| \!)/iS', '$1:0 0$2', $css);
358
+
359
+ // Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space)
360
+ // Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space)
361
+ // This makes it more likely that it'll get further compressed in the next step.
362
+ $css = preg_replace_callback('/rgb\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'rgb_to_hex'), $css);
363
+ $css = preg_replace_callback('/hsl\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'hsl_to_hex'), $css);
364
+
365
+ // Shorten colors from #AABBCC to #ABC or short color name.
366
+ $css = $this->compress_hex_colors($css);
367
+
368
+ // border: none to border:0, outline: none to outline:0
369
+ $css = preg_replace('/(border\-?(?:top|right|bottom|left|)|outline)\:none(;|\}| \!)/iS', '$1:0$2', $css);
370
+
371
+ // shorter opacity IE filter
372
+ $css = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $css);
373
+
374
+ // Find a fraction that is used for Opera's -o-device-pixel-ratio query
375
+ // Add token to add the "\" back in later
376
+ $css = preg_replace('/\(([a-z\-]+):([0-9]+)\/([0-9]+)\)/i', '($1:$2'. self::QUERY_FRACTION .'$3)', $css);
377
+
378
+ // Remove empty rules.
379
+ $css = preg_replace('/[^\};\{\/]+\{\}/S', '', $css);
380
+
381
+ // Add "/" back to fix Opera -o-device-pixel-ratio query
382
+ $css = preg_replace('/'. self::QUERY_FRACTION .'/', '/', $css);
383
+
384
+ // Replace multiple semi-colons in a row by a single one
385
+ // See SF bug #1980989
386
+ $css = preg_replace('/;;+/', ';', $css);
387
+
388
+ // Restore new lines for /*! important comments
389
+ $css = preg_replace('/'. self::NL .'/', "\n", $css);
390
+
391
+ // Lowercase all uppercase properties
392
+ $css = preg_replace_callback('/(\{|\;)([A-Z\-]+)(\:)/', array($this, 'lowercase_properties'), $css);
393
+
394
+ // Some source control tools don't like it when files containing lines longer
395
+ // than, say 8000 characters, are checked in. The linebreak option is used in
396
+ // that case to split long lines after a specific column.
397
+ if ($linebreak_pos !== FALSE && (int) $linebreak_pos >= 0) {
398
+ $linebreak_pos = (int) $linebreak_pos;
399
+ $start_index = $i = 0;
400
+ while ($i < strlen($css)) {
401
+ $i++;
402
+ if ($css[$i - 1] === '}' && $i - $start_index > $linebreak_pos) {
403
+ $css = $this->str_slice($css, 0, $i) . "\n" . $this->str_slice($css, $i);
404
+ $start_index = $i;
405
+ }
406
+ }
407
+ }
408
+
409
+ // restore preserved comments and strings in reverse order
410
+ for ($i = count($this->preserved_tokens) - 1; $i >= 0; $i--) {
411
+ $css = preg_replace('/' . self::TOKEN . $i . '___/', $this->preserved_tokens[$i], $css, 1);
412
+ }
413
+
414
+ // Trim the final string (for any leading or trailing white spaces)
415
+ return trim($css);
416
+ }
417
+
418
+ /**
419
+ * Utility method to replace all data urls with tokens before we start
420
+ * compressing, to avoid performance issues running some of the subsequent
421
+ * regexes against large strings chunks.
422
+ *
423
+ * @param string $css
424
+ * @return string
425
+ */
426
+ private function extract_data_urls($css)
427
+ {
428
+ // Leave data urls alone to increase parse performance.
429
+ $max_index = strlen($css) - 1;
430
+ $append_index = $index = $last_index = $offset = 0;
431
+ $sb = array();
432
+ $pattern = '/url\(\s*(["\']?)data\:/i';
433
+
434
+ // Since we need to account for non-base64 data urls, we need to handle
435
+ // ' and ) being part of the data string. Hence switching to indexOf,
436
+ // to determine whether or not we have matching string terminators and
437
+ // handling sb appends directly, instead of using matcher.append* methods.
438
+
439
+ while (preg_match($pattern, $css, $m, 0, $offset)) {
440
+ $index = $this->index_of($css, $m[0], $offset);
441
+ $last_index = $index + strlen($m[0]);
442
+ $start_index = $index + 4; // "url(".length()
443
+ $end_index = $last_index - 1;
444
+ $terminator = $m[1]; // ', " or empty (not quoted)
445
+ $found_terminator = FALSE;
446
+
447
+ if (strlen($terminator) === 0) {
448
+ $terminator = ')';
449
+ }
450
+
451
+ while ($found_terminator === FALSE && $end_index+1 <= $max_index) {
452
+ $end_index = $this->index_of($css, $terminator, $end_index + 1);
453
+
454
+ // endIndex == 0 doesn't really apply here
455
+ if ($end_index > 0 && substr($css, $end_index - 1, 1) !== '\\') {
456
+ $found_terminator = TRUE;
457
+ if (')' != $terminator) {
458
+ $end_index = $this->index_of($css, ')', $end_index);
459
+ }
460
+ }
461
+ }
462
+
463
+ // Enough searching, start moving stuff over to the buffer
464
+ $sb[] = $this->str_slice($css, $append_index, $index);
465
+
466
+ if ($found_terminator) {
467
+ $token = $this->str_slice($css, $start_index, $end_index);
468
+ $token = preg_replace('/\s+/', '', $token);
469
+ $this->preserved_tokens[] = $token;
470
+
471
+ $preserver = 'url(' . self::TOKEN . (count($this->preserved_tokens) - 1) . '___)';
472
+ $sb[] = $preserver;
473
+
474
+ $append_index = $end_index + 1;
475
+ } else {
476
+ // No end terminator found, re-add the whole match. Should we throw/warn here?
477
+ $sb[] = $this->str_slice($css, $index, $last_index);
478
+ $append_index = $last_index;
479
+ }
480
+
481
+ $offset = $last_index;
482
+ }
483
+
484
+ $sb[] = $this->str_slice($css, $append_index);
485
+
486
+ return implode('', $sb);
487
+ }
488
+
489
+ /**
490
+ * Utility method to compress hex color values of the form #AABBCC to #ABC or short color name.
491
+ *
492
+ * DOES NOT compress CSS ID selectors which match the above pattern (which would break things).
493
+ * e.g. #AddressForm { ... }
494
+ *
495
+ * DOES NOT compress IE filters, which have hex color values (which would break things).
496
+ * e.g. filter: chroma(color="#FFFFFF");
497
+ *
498
+ * DOES NOT compress invalid hex values.
499
+ * e.g. background-color: #aabbccdd
500
+ *
501
+ * @param string $css
502
+ * @return string
503
+ */
504
+ private function compress_hex_colors($css)
505
+ {
506
+ // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters)
507
+ $pattern = '/(\=\s*?["\']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/iS';
508
+ $_index = $index = $last_index = $offset = 0;
509
+ $sb = array();
510
+ // See: http://ajaxmin.codeplex.com/wikipage?title=CSS%20Colors
511
+ $short_safe = array(
512
+ '#808080' => 'gray',
513
+ '#008000' => 'green',
514
+ '#800000' => 'maroon',
515
+ '#000080' => 'navy',
516
+ '#808000' => 'olive',
517
+ '#ffa500' => 'orange',
518
+ '#800080' => 'purple',
519
+ '#c0c0c0' => 'silver',
520
+ '#008080' => 'teal',
521
+ '#f00' => 'red'
522
+ );
523
+
524
+ while (preg_match($pattern, $css, $m, 0, $offset)) {
525
+ $index = $this->index_of($css, $m[0], $offset);
526
+ $last_index = $index + strlen($m[0]);
527
+ $is_filter = $m[1] !== null && $m[1] !== '';
528
+
529
+ $sb[] = $this->str_slice($css, $_index, $index);
530
+
531
+ if ($is_filter) {
532
+ // Restore, maintain case, otherwise filter will break
533
+ $sb[] = $m[1] . '#' . $m[2] . $m[3] . $m[4] . $m[5] . $m[6] . $m[7];
534
+ } else {
535
+ if (strtolower($m[2]) == strtolower($m[3]) &&
536
+ strtolower($m[4]) == strtolower($m[5]) &&
537
+ strtolower($m[6]) == strtolower($m[7])) {
538
+ // Compress.
539
+ $hex = '#' . strtolower($m[3] . $m[5] . $m[7]);
540
+ } else {
541
+ // Non compressible color, restore but lower case.
542
+ $hex = '#' . strtolower($m[2] . $m[3] . $m[4] . $m[5] . $m[6] . $m[7]);
543
+ }
544
+ // replace Hex colors to short safe color names
545
+ $sb[] = array_key_exists($hex, $short_safe) ? $short_safe[$hex] : $hex;
546
+ }
547
+
548
+ $_index = $offset = $last_index - strlen($m[8]);
549
+ }
550
+
551
+ $sb[] = $this->str_slice($css, $_index);
552
+
553
+ return implode('', $sb);
554
+ }
555
+
556
+ /* CALLBACKS
557
+ * ---------------------------------------------------------------------------------------------
558
+ */
559
+
560
+ private function replace_string($matches)
561
+ {
562
+ $match = $matches[0];
563
+ $quote = substr($match, 0, 1);
564
+ // Must use addcslashes in PHP to avoid parsing of backslashes
565
+ $match = addcslashes($this->str_slice($match, 1, -1), '\\');
566
+
567
+ // maybe the string contains a comment-like substring?
568
+ // one, maybe more? put'em back then
569
+ if (($pos = $this->index_of($match, self::COMMENT)) >= 0) {
570
+ for ($i = 0, $max = count($this->comments); $i < $max; $i++) {
571
+ $match = preg_replace('/' . self::COMMENT . $i . '___/', $this->comments[$i], $match, 1);
572
+ }
573
+ }
574
+
575
+ // minify alpha opacity in filter strings
576
+ $match = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $match);
577
+
578
+ $this->preserved_tokens[] = $match;
579
+ return $quote . self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . $quote;
580
+ }
581
+
582
+ private function replace_colon($matches)
583
+ {
584
+ return preg_replace('/\:/', self::CLASSCOLON, $matches[0]);
585
+ }
586
+
587
+ private function replace_calc($matches)
588
+ {
589
+ $this->preserved_tokens[] = trim(preg_replace('/\s*([\*\/\(\),])\s*/', '$1', $matches[2]));
590
+ return 'calc('. self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')';
591
+ }
592
+
593
+ private function preserve_old_IE_specific_matrix_definition($matches)
594
+ {
595
+ $this->preserved_tokens[] = $matches[1];
596
+ return 'filter:progid:DXImageTransform.Microsoft.Matrix(' . self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')';
597
+ }
598
+
599
+ private function replace_keyframe_zero($matches)
600
+ {
601
+ return $matches[1] . preg_replace('/0(\{|,[^\)\{]+\{)/', '0%$1', $matches[2]) . $matches[3];
602
+ }
603
+
604
+ private function rgb_to_hex($matches)
605
+ {
606
+ // Support for percentage values rgb(100%, 0%, 45%);
607
+ if ($this->index_of($matches[1], '%') >= 0){
608
+ $rgbcolors = explode(',', str_replace('%', '', $matches[1]));
609
+ for ($i = 0; $i < count($rgbcolors); $i++) {
610
+ $rgbcolors[$i] = $this->round_number(floatval($rgbcolors[$i]) * 2.55);
611
+ }
612
+ } else {
613
+ $rgbcolors = explode(',', $matches[1]);
614
+ }
615
+
616
+ // Values outside the sRGB color space should be clipped (0-255)
617
+ for ($i = 0; $i < count($rgbcolors); $i++) {
618
+ $rgbcolors[$i] = $this->clamp_number(intval($rgbcolors[$i], 10), 0, 255);
619
+ $rgbcolors[$i] = sprintf("%02x", $rgbcolors[$i]);
620
+ }
621
+
622
+ // Fix for issue #2528093
623
+ if (!preg_match('/[\s\,\);\}]/', $matches[2])){
624
+ $matches[2] = ' ' . $matches[2];
625
+ }
626
+
627
+ return '#' . implode('', $rgbcolors) . $matches[2];
628
+ }
629
+
630
+ private function hsl_to_hex($matches)
631
+ {
632
+ $values = explode(',', str_replace('%', '', $matches[1]));
633
+ $h = floatval($values[0]);
634
+ $s = floatval($values[1]);
635
+ $l = floatval($values[2]);
636
+
637
+ // Wrap and clamp, then fraction!
638
+ $h = ((($h % 360) + 360) % 360) / 360;
639
+ $s = $this->clamp_number($s, 0, 100) / 100;
640
+ $l = $this->clamp_number($l, 0, 100) / 100;
641
+
642
+ if ($s == 0) {
643
+ $r = $g = $b = $this->round_number(255 * $l);
644
+ } else {
645
+ $v2 = $l < 0.5 ? $l * (1 + $s) : ($l + $s) - ($s * $l);
646
+ $v1 = (2 * $l) - $v2;
647
+ $r = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h + (1/3)));
648
+ $g = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h));
649
+ $b = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h - (1/3)));
650
+ }
651
+
652
+ return $this->rgb_to_hex(array('', $r.','.$g.','.$b, $matches[2]));
653
+ }
654
+
655
+ private function lowercase_pseudo_first($matches)
656
+ {
657
+ return ':first-'. strtolower($matches[1]) .' '. $matches[2];
658
+ }
659
+
660
+ private function lowercase_directives($matches)
661
+ {
662
+ return '@'. strtolower($matches[1]);
663
+ }
664
+
665
+ private function lowercase_pseudo_elements($matches)
666
+ {
667
+ return ':'. strtolower($matches[1]);
668
+ }
669
+
670
+ private function lowercase_common_functions($matches)
671
+ {
672
+ return ':'. strtolower($matches[1]) .'(';
673
+ }
674
+
675
+ private function lowercase_common_functions_values($matches)
676
+ {
677
+ return $matches[1] . strtolower($matches[2]);
678
+ }
679
+
680
+ private function lowercase_properties($matches)
681
+ {
682
+ return $matches[1].strtolower($matches[2]).$matches[3];
683
+ }
684
+
685
+ /* HELPERS
686
+ * ---------------------------------------------------------------------------------------------
687
+ */
688
+
689
+ private function hue_to_rgb($v1, $v2, $vh)
690
+ {
691
+ $vh = $vh < 0 ? $vh + 1 : ($vh > 1 ? $vh - 1 : $vh);
692
+ if ($vh * 6 < 1) return $v1 + ($v2 - $v1) * 6 * $vh;
693
+ if ($vh * 2 < 1) return $v2;
694
+ if ($vh * 3 < 2) return $v1 + ($v2 - $v1) * ((2/3) - $vh) * 6;
695
+ return $v1;
696
+ }
697
+
698
+ private function round_number($n)
699
+ {
700
+ return intval(floor(floatval($n) + 0.5), 10);
701
+ }
702
+
703
+ private function clamp_number($n, $min, $max)
704
+ {
705
+ return min(max($n, $min), $max);
706
+ }
707
+
708
+ /**
709
+ * PHP port of Javascript's "indexOf" function for strings only
710
+ * Author: Tubal Martin http://blog.margenn.com
711
+ *
712
+ * @param string $haystack
713
+ * @param string $needle
714
+ * @param int $offset index (optional)
715
+ * @return int
716
+ */
717
+ private function index_of($haystack, $needle, $offset = 0)
718
+ {
719
+ $index = strpos($haystack, $needle, $offset);
720
+
721
+ return ($index !== FALSE) ? $index : -1;
722
+ }
723
+
724
+ /**
725
+ * PHP port of Javascript's "slice" function for strings only
726
+ * Author: Tubal Martin http://blog.margenn.com
727
+ * Tests: http://margenn.com/tubal/str_slice/
728
+ *
729
+ * @param string $str
730
+ * @param int $start index
731
+ * @param int|bool $end index (optional)
732
+ * @return string
733
+ */
734
+ private function str_slice($str, $start = 0, $end = FALSE)
735
+ {
736
+ if ($end !== FALSE && ($start < 0 || $end <= 0)) {
737
+ $max = strlen($str);
738
+
739
+ if ($start < 0) {
740
+ if (($start = $max + $start) < 0) {
741
+ return '';
742
+ }
743
+ }
744
+
745
+ if ($end < 0) {
746
+ if (($end = $max + $end) < 0) {
747
+ return '';
748
+ }
749
+ }
750
+
751
+ if ($end <= $start) {
752
+ return '';
753
+ }
754
+ }
755
+
756
+ $slice = ($end === FALSE) ? substr($str, $start) : substr($str, $start, $end - $start);
757
+ return ($slice === FALSE) ? '' : $slice;
758
+ }
759
+
760
+ /**
761
+ * Convert strings like "64M" or "30" to int values
762
+ * @param mixed $size
763
+ * @return int
764
+ */
765
+ private function normalize_int($size)
766
+ {
767
+ if (is_string($size)) {
768
+ switch (substr($size, -1)) {
769
+ case 'M': case 'm': return $size * 1048576;
770
+ case 'K': case 'k': return $size * 1024;
771
+ case 'G': case 'g': return $size * 1073741824;
772
+ }
773
+ }
774
+
775
+ return (int) $size;
776
+ }
777
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/less/lib/lessc.inc.php CHANGED
@@ -15,7 +15,7 @@
15
  * The less compiler and parser.
16
  *
17
  * Converting LESS to CSS is a three stage process. The incoming file is parsed
18
- * by `lessc_parser` into a syntax tree, then it is compiled into another tree
19
  * representing the CSS structure by `lessc`. The CSS tree is fed into a
20
  * formatter, like `lessc_formatter` which then outputs CSS as a string.
21
  *
@@ -32,12 +32,12 @@
32
  * evaluation context, such as all available mixins and variables at any given
33
  * time.
34
  *
35
- * The `lessc_parser` class is only concerned with parsing its input.
36
  *
37
  * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string,
38
  * handling things like indentation.
39
  */
40
- class lessc {
41
  static public $VERSION = "v0.4.0";
42
  static protected $TRUE = array("keyword", "true");
43
  static protected $FALSE = array("keyword", "false");
@@ -184,7 +184,7 @@ class lessc {
184
  * Compiling the block involves pushing a fresh environment on the stack,
185
  * and iterating through the props, compiling each one.
186
  *
187
- * See lessc::compileProp()
188
  *
189
  */
190
  protected function compileBlock($block) {
@@ -1763,7 +1763,7 @@ class lessc {
1763
  // inject array of unparsed strings into environment as variables
1764
  protected function injectVariables($args) {
1765
  $this->pushEnv();
1766
- $parser = new lessc_parser($this, __METHOD__);
1767
  foreach ($args as $name => $strValue) {
1768
  if ($name{0} != '@') $name = '@'.$name;
1769
  $parser->count = 0;
@@ -1940,7 +1940,7 @@ class lessc {
1940
  }
1941
 
1942
  protected function makeParser($name) {
1943
- $parser = new lessc_parser($this, $name);
1944
  $parser->writeComments = $this->preserveComments;
1945
 
1946
  return $parser;
@@ -1951,11 +1951,11 @@ class lessc {
1951
  }
1952
 
1953
  protected function newFormatter() {
1954
- $className = "lessc_formatter_lessjs";
1955
  if (!empty($this->formatterName)) {
1956
  if (!is_string($this->formatterName))
1957
  return $this->formatterName;
1958
- $className = "lessc_formatter_$this->formatterName";
1959
  }
1960
 
1961
  return new $className;
@@ -2178,7 +2178,7 @@ class lessc {
2178
 
2179
  // responsible for taking a string of LESS code and converting it into a
2180
  // syntax tree
2181
- class lessc_parser {
2182
  static protected $nextBlockId = 0; // used to uniquely identify blocks
2183
 
2184
  static protected $precedence = array(
@@ -2237,12 +2237,12 @@ class lessc_parser {
2237
 
2238
  if (!self::$operatorString) {
2239
  self::$operatorString =
2240
- '('.implode('|', array_map(array('lessc', 'preg_quote'),
2241
  array_keys(self::$precedence))).')';
2242
 
2243
- $commentSingle = lessc::preg_quote(self::$commentSingle);
2244
- $commentMultiLeft = lessc::preg_quote(self::$commentMultiLeft);
2245
- $commentMultiRight = lessc::preg_quote(self::$commentMultiRight);
2246
 
2247
  self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
2248
  self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
@@ -2292,7 +2292,7 @@ class lessc_parser {
2292
  * functions represent discrete grammatical rules for the language, and
2293
  * they are able to capture the text that represents those rules.
2294
  *
2295
- * Consider the function lessc::keyword(). (all parse functions are
2296
  * structured the same)
2297
  *
2298
  * The function takes a single reference argument. When calling the
@@ -2301,7 +2301,7 @@ class lessc_parser {
2301
  * argument, advance the position in the buffer, and return true. If it
2302
  * fails then it won't advance the buffer and it will return false.
2303
  *
2304
- * All of these parse functions are powered by lessc::match(), which behaves
2305
  * the same way, but takes a literal regular expression. Sometimes it is
2306
  * more convenient to use match instead of creating a new function.
2307
  *
@@ -2310,7 +2310,7 @@ class lessc_parser {
2310
  *
2311
  * But, if some of the rules in the chain succeed before one fails, then
2312
  * the buffer position will be left at an invalid state. In order to
2313
- * avoid this, lessc::seek() is used to remember and set buffer positions.
2314
  *
2315
  * Before parsing a chain, use $s = $this->seek() to remember the current
2316
  * position into $s. Then if a chain fails, use $this->seek($s) to
@@ -2467,7 +2467,7 @@ class lessc_parser {
2467
  protected function isDirective($dirname, $directives) {
2468
  // TODO: cache pattern in parser
2469
  $pattern = implode("|",
2470
- array_map(array("lessc", "preg_quote"), $directives));
2471
  $pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i';
2472
 
2473
  return preg_match($pattern, $dirname);
@@ -2492,7 +2492,7 @@ class lessc_parser {
2492
 
2493
  if (count($values) == 0) return false;
2494
 
2495
- $exps = lessc::compressList($values, ' ');
2496
  return true;
2497
  }
2498
 
@@ -2590,7 +2590,7 @@ class lessc_parser {
2590
 
2591
  if (count($values) == 0) return false;
2592
 
2593
- $value = lessc::compressList($values, ', ');
2594
  return true;
2595
  }
2596
 
@@ -2755,7 +2755,7 @@ class lessc_parser {
2755
  $this->eatWhiteDefault = false;
2756
 
2757
  $stop = array("'", '"', "@{", $end);
2758
- $stop = array_map(array("lessc", "preg_quote"), $stop);
2759
  // $stop[] = self::$commentMulti;
2760
 
2761
  if (!is_null($rejectStrs)) {
@@ -2831,7 +2831,7 @@ class lessc_parser {
2831
 
2832
  // look for either ending delim , escape, or string interpolation
2833
  $patt = '([^\n]*?)(@\{|\\\\|' .
2834
- lessc::preg_quote($delim).')';
2835
 
2836
  $oldWhite = $this->eatWhiteDefault;
2837
  $this->eatWhiteDefault = false;
@@ -3348,7 +3348,7 @@ class lessc_parser {
3348
  }
3349
 
3350
  if (!isset(self::$literalCache[$what])) {
3351
- self::$literalCache[$what] = lessc::preg_quote($what);
3352
  }
3353
 
3354
  return $this->match(self::$literalCache[$what], $m, $eatWhitespace);
@@ -3388,7 +3388,7 @@ class lessc_parser {
3388
  } else {
3389
  $validChars = $allowNewline ? "." : "[^\n]";
3390
  }
3391
- if (!$this->match('('.$validChars.'*?)'.lessc::preg_quote($what), $m, !$until)) return false;
3392
  if ($until) $this->count -= strlen($what); // give back $what
3393
  $out = $m[1];
3394
  return true;
@@ -3558,7 +3558,7 @@ class lessc_parser {
3558
 
3559
  }
3560
 
3561
- class lessc_formatter_classic {
3562
  public $indentChar = " ";
3563
 
3564
  public $break = "\n";
@@ -3653,7 +3653,7 @@ class lessc_formatter_classic {
3653
  }
3654
  }
3655
 
3656
- class lessc_formatter_compressed extends lessc_formatter_classic {
3657
  public $disableSingle = true;
3658
  public $open = "{";
3659
  public $selectorSeparator = ",";
@@ -3666,7 +3666,7 @@ class lessc_formatter_compressed extends lessc_formatter_classic {
3666
  }
3667
  }
3668
 
3669
- class lessc_formatter_lessjs extends lessc_formatter_classic {
3670
  public $disableSingle = true;
3671
  public $breakSelectors = true;
3672
  public $assignSeparator = ": ";
15
  * The less compiler and parser.
16
  *
17
  * Converting LESS to CSS is a three stage process. The incoming file is parsed
18
+ * by `a3_lessc_parser` into a syntax tree, then it is compiled into another tree
19
  * representing the CSS structure by `lessc`. The CSS tree is fed into a
20
  * formatter, like `lessc_formatter` which then outputs CSS as a string.
21
  *
32
  * evaluation context, such as all available mixins and variables at any given
33
  * time.
34
  *
35
+ * The `a3_lessc_parser` class is only concerned with parsing its input.
36
  *
37
  * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string,
38
  * handling things like indentation.
39
  */
40
+ class a3_lessc {
41
  static public $VERSION = "v0.4.0";
42
  static protected $TRUE = array("keyword", "true");
43
  static protected $FALSE = array("keyword", "false");
184
  * Compiling the block involves pushing a fresh environment on the stack,
185
  * and iterating through the props, compiling each one.
186
  *
187
+ * See a3_lessc::compileProp()
188
  *
189
  */
190
  protected function compileBlock($block) {
1763
  // inject array of unparsed strings into environment as variables
1764
  protected function injectVariables($args) {
1765
  $this->pushEnv();
1766
+ $parser = new a3_lessc_parser($this, __METHOD__);
1767
  foreach ($args as $name => $strValue) {
1768
  if ($name{0} != '@') $name = '@'.$name;
1769
  $parser->count = 0;
1940
  }
1941
 
1942
  protected function makeParser($name) {
1943
+ $parser = new a3_lessc_parser($this, $name);
1944
  $parser->writeComments = $this->preserveComments;
1945
 
1946
  return $parser;
1951
  }
1952
 
1953
  protected function newFormatter() {
1954
+ $className = "a3_lessc_formatter_lessjs";
1955
  if (!empty($this->formatterName)) {
1956
  if (!is_string($this->formatterName))
1957
  return $this->formatterName;
1958
+ $className = "a3_lessc_formatter_$this->formatterName";
1959
  }
1960
 
1961
  return new $className;
2178
 
2179
  // responsible for taking a string of LESS code and converting it into a
2180
  // syntax tree
2181
+ class a3_lessc_parser {
2182
  static protected $nextBlockId = 0; // used to uniquely identify blocks
2183
 
2184
  static protected $precedence = array(
2237
 
2238
  if (!self::$operatorString) {
2239
  self::$operatorString =
2240
+ '('.implode('|', array_map(array('a3_lessc', 'preg_quote'),
2241
  array_keys(self::$precedence))).')';
2242
 
2243
+ $commentSingle = a3_lessc::preg_quote(self::$commentSingle);
2244
+ $commentMultiLeft = a3_lessc::preg_quote(self::$commentMultiLeft);
2245
+ $commentMultiRight = a3_lessc::preg_quote(self::$commentMultiRight);
2246
 
2247
  self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
2248
  self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
2292
  * functions represent discrete grammatical rules for the language, and
2293
  * they are able to capture the text that represents those rules.
2294
  *
2295
+ * Consider the function a3_lessc::keyword(). (all parse functions are
2296
  * structured the same)
2297
  *
2298
  * The function takes a single reference argument. When calling the
2301
  * argument, advance the position in the buffer, and return true. If it
2302
  * fails then it won't advance the buffer and it will return false.
2303
  *
2304
+ * All of these parse functions are powered by a3_lessc::match(), which behaves
2305
  * the same way, but takes a literal regular expression. Sometimes it is
2306
  * more convenient to use match instead of creating a new function.
2307
  *
2310
  *
2311
  * But, if some of the rules in the chain succeed before one fails, then
2312
  * the buffer position will be left at an invalid state. In order to
2313
+ * avoid this, a3_lessc::seek() is used to remember and set buffer positions.
2314
  *
2315
  * Before parsing a chain, use $s = $this->seek() to remember the current
2316
  * position into $s. Then if a chain fails, use $this->seek($s) to
2467
  protected function isDirective($dirname, $directives) {
2468
  // TODO: cache pattern in parser
2469
  $pattern = implode("|",
2470
+ array_map(array('a3_lessc', "preg_quote"), $directives));
2471
  $pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i';
2472
 
2473
  return preg_match($pattern, $dirname);
2492
 
2493
  if (count($values) == 0) return false;
2494
 
2495
+ $exps = a3_lessc::compressList($values, ' ');
2496
  return true;
2497
  }
2498
 
2590
 
2591
  if (count($values) == 0) return false;
2592
 
2593
+ $value = a3_lessc::compressList($values, ', ');
2594
  return true;
2595
  }
2596
 
2755
  $this->eatWhiteDefault = false;
2756
 
2757
  $stop = array("'", '"', "@{", $end);
2758
+ $stop = array_map(array('a3_lessc', "preg_quote"), $stop);
2759
  // $stop[] = self::$commentMulti;
2760
 
2761
  if (!is_null($rejectStrs)) {
2831
 
2832
  // look for either ending delim , escape, or string interpolation
2833
  $patt = '([^\n]*?)(@\{|\\\\|' .
2834
+ a3_lessc::preg_quote($delim).')';
2835
 
2836
  $oldWhite = $this->eatWhiteDefault;
2837
  $this->eatWhiteDefault = false;
3348
  }
3349
 
3350
  if (!isset(self::$literalCache[$what])) {
3351
+ self::$literalCache[$what] = a3_lessc::preg_quote($what);
3352
  }
3353
 
3354
  return $this->match(self::$literalCache[$what], $m, $eatWhitespace);
3388
  } else {
3389
  $validChars = $allowNewline ? "." : "[^\n]";
3390
  }
3391
+ if (!$this->match('('.$validChars.'*?)'.a3_lessc::preg_quote($what), $m, !$until)) return false;
3392
  if ($until) $this->count -= strlen($what); // give back $what
3393
  $out = $m[1];
3394
  return true;
3558
 
3559
  }
3560
 
3561
+ class a3_lessc_formatter_classic {
3562
  public $indentChar = " ";
3563
 
3564
  public $break = "\n";
3653
  }
3654
  }
3655
 
3656
+ class a3_lessc_formatter_compressed extends a3_lessc_formatter_classic {
3657
  public $disableSingle = true;
3658
  public $open = "{";
3659
  public $selectorSeparator = ",";
3666
  }
3667
  }
3668
 
3669
+ class a3_lessc_formatter_lessjs extends a3_lessc_formatter_classic {
3670
  public $disableSingle = true;
3671
  public $breakSelectors = true;
3672
  public $assignSeparator = ": ";
assets/images/free-woocommerce-plugins.png CHANGED
Binary file
assets/images/free-wordpress-plugins.png CHANGED
Binary file
assets/images/go-to-support-forum.png CHANGED
Binary file
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === a3 Lazy Load ===
2
 
3
- Contributors: a3rev, A3 Revolution Software Development team
4
  Tags: a3 lazy load, Lazy Loading , image lazy load, lazyload
5
  Requires at least: 4.0
6
- Tested up to: 4.2.2
7
- Stable tag: 1.4.0
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -144,6 +144,15 @@ Automatic installation is the easiest option as WordPress handles the file trans
144
 
145
  == Changelog ==
146
 
 
 
 
 
 
 
 
 
 
147
  = 1.4.0 - 2015/06/17 =
148
  * Feature - Plugin framework Mobile First focus upgrade
149
  * Feature - Massive improvement in admin UI and UX in PC, tablet and mobile browsers
@@ -216,6 +225,9 @@ Automatic installation is the easiest option as WordPress handles the file trans
216
 
217
  == Upgrade Notice ==
218
 
 
 
 
219
  = 1.4.0 =
220
  Major Feature Upgrade. Massive admin panel UI and UX upgrade. Includes 5 new features, 3 Tweaks, 1 bug fix plus full compatibility with WooCommerce Version 2.3.11
221
 
1
  === a3 Lazy Load ===
2
 
3
+ Contributors: a3rev, A3 Revolution Software Development team, nguyencongtuan
4
  Tags: a3 lazy load, Lazy Loading , image lazy load, lazyload
5
  Requires at least: 4.0
6
+ Tested up to: 4.3
7
+ Stable tag: 1.4.1
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
144
 
145
  == Changelog ==
146
 
147
+ = 1.4.1 - 2015/08/22 =
148
+ * Tweak - include new CSSMin lib from https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port into plugin framework instead of old CSSMin lib from http://code.google.com/p/cssmin/ , to avoid conflict with plugins or themes that have CSSMin lib
149
+ * Tweak - make __construct() function for 'Compile_Less_Sass' class instead of using a method with the same name as the class for compatibility on WP 4.3 and is deprecated on PHP4
150
+ * Tweak - change class name from 'lessc' to 'a3_lessc' so that it does not conflict with plugins or themes that have another Lessc lib
151
+ * Tweak - Plugin Framework DB query optimization. Refactored settings_get_option call for dynamic style elements, example typography, border, border_styles, border_corner, box_shadow
152
+ * Tweak - Tested for full compatibility with WordPress major version 4.3.0
153
+ * Fix - Update the plugin framework for setup correct default settings on first installed
154
+ * Fix - Update the plugin framework for reset to correct default settings when hit on 'Reset Settings' button on each settings tab
155
+
156
  = 1.4.0 - 2015/06/17 =
157
  * Feature - Plugin framework Mobile First focus upgrade
158
  * Feature - Massive improvement in admin UI and UX in PC, tablet and mobile browsers
225
 
226
  == Upgrade Notice ==
227
 
228
+ = 1.4.1 =
229
+ Major Maintenance Upgrade. 5 Code Tweaks plus 2 bug fixes for full compatibility with WordPress v 4.3.0
230
+
231
  = 1.4.0 =
232
  Major Feature Upgrade. Massive admin panel UI and UX upgrade. Includes 5 new features, 3 Tweaks, 1 bug fix plus full compatibility with WooCommerce Version 2.3.11
233