[SPIP] v3.2.1-->v3.2.3
[lhc/web/www.git] / www / plugins-dist / compresseur / lib / csstidy / class.csstidy_optimise.php
index d42341c..4972436 100644 (file)
@@ -70,40 +70,60 @@ class csstidy_optimise {
         * @version 1.0
         */
        public function postparse() {
+
+               if ($this->parser->get_cfg('reverse_left_and_right') > 0) {
+
+                       foreach ($this->css as $medium => $selectors) {
+                               if (is_array($selectors)) {
+                                       foreach ($selectors as $selector => $properties) {
+                                               $this->css[$medium][$selector] = $this->reverse_left_and_right($this->css[$medium][$selector]);
+                                       }
+                               }
+                       }
+
+               }
+
                if ($this->parser->get_cfg('preserve_css')) {
                        return;
                }
 
-               if ($this->parser->get_cfg('merge_selectors') === 2) {
+               if ((int)$this->parser->get_cfg('merge_selectors') === 2) {
                        foreach ($this->css as $medium => $value) {
-                               $this->merge_selectors($this->css[$medium]);
+                               if (is_array($value)) {
+                                       $this->merge_selectors($this->css[$medium]);
+                               }
                        }
                }
 
                if ($this->parser->get_cfg('discard_invalid_selectors')) {
                        foreach ($this->css as $medium => $value) {
-                               $this->discard_invalid_selectors($this->css[$medium]);
+                               if (is_array($value)) {
+                                       $this->discard_invalid_selectors($this->css[$medium]);
+                               }
                        }
                }
 
                if ($this->parser->get_cfg('optimise_shorthands') > 0) {
                        foreach ($this->css as $medium => $value) {
-                               foreach ($value as $selector => $value1) {
-                                       $this->css[$medium][$selector] = $this->merge_4value_shorthands($this->css[$medium][$selector]);
+                               if (is_array($value)) {
+                                       foreach ($value as $selector => $value1) {
+                                               $this->css[$medium][$selector] = $this->merge_4value_shorthands($this->css[$medium][$selector]);
+                                               $this->css[$medium][$selector] = $this->merge_4value_radius_shorthands($this->css[$medium][$selector]);
 
-                                       if ($this->parser->get_cfg('optimise_shorthands') < 2) {
-                                               continue;
-                                       }
+                                               if ($this->parser->get_cfg('optimise_shorthands') < 2) {
+                                                       continue;
+                                               }
 
-                                       $this->css[$medium][$selector] = $this->merge_font($this->css[$medium][$selector]);
+                                               $this->css[$medium][$selector] = $this->merge_font($this->css[$medium][$selector]);
 
-                                       if ($this->parser->get_cfg('optimise_shorthands') < 3) {
-                                               continue;
-                                       }
+                                               if ($this->parser->get_cfg('optimise_shorthands') < 3) {
+                                                       continue;
+                                               }
 
-                                       $this->css[$medium][$selector] = $this->merge_bg($this->css[$medium][$selector]);
-                                       if (empty($this->css[$medium][$selector])) {
-                                               unset($this->css[$medium][$selector]);
+                                               $this->css[$medium][$selector] = $this->merge_bg($this->css[$medium][$selector]);
+                                               if (empty($this->css[$medium][$selector])) {
+                                                       unset($this->css[$medium][$selector]);
+                                               }
                                        }
                                }
                        }
@@ -269,7 +289,8 @@ class csstidy_optimise {
         */
        public function compress_important(&$string) {
                if ($this->parser->is_important($string)) {
-                       $string = $this->parser->gvw_important($string) . '!important';
+                       $important = $this->parser->get_cfg('space_before_important') ? ' !important' : '!important';
+                       $string = $this->parser->gvw_important($string) . $important;
                }
                return $string;
        }
@@ -399,9 +420,9 @@ class csstidy_optimise {
                                if ($number[1] == '' && in_array($this->property, $unit_values, true)) {
                                        $number[1] = 'px';
                                }
-                       } else {
-                               $number[1] = '';
-                       }
+                        } elseif ($number[1] != 's' && $number[1] != 'ms') {
+                                $number[1] = '';
+                        }
 
                        $temp[$l] = $number[0] . $number[1];
                }
@@ -524,12 +545,15 @@ class csstidy_optimise {
         * Dissolves properties like padding:10px 10px 10px to padding-top:10px;padding-bottom:10px;...
         * @param string $property
         * @param string $value
+        * @param array|null $shorthands
         * @return array
         * @version 1.0
         * @see merge_4value_shorthands()
         */
-       public function dissolve_4value_shorthands($property, $value) {
-               $shorthands = & $this->parser->data['csstidy']['shorthands'];
+       public function dissolve_4value_shorthands($property, $value, $shorthands = null) {
+               if (is_null($shorthands)) {
+                       $shorthands = & $this->parser->data['csstidy']['shorthands'];
+               }
                if (!is_array($shorthands[$property])) {
                        $return[$property] = $value;
                        return $return;
@@ -566,25 +590,66 @@ class csstidy_optimise {
                return $return;
        }
 
+       /**
+        * Dissolves radius properties like
+        * border-radius:10px 10px 10px / 1px 2px
+        * to border-top-left:10px 1px;border-top-right:10px 2x;...
+        * @param string $property
+        * @param string $value
+        * @return array
+        * @version 1.0
+        * @use dissolve_4value_shorthands()
+        * @see merge_4value_radius_shorthands()
+        */
+       public function dissolve_4value_radius_shorthands($property, $value) {
+               $shorthands = & $this->parser->data['csstidy']['radius_shorthands'];
+               if (!is_array($shorthands[$property])) {
+                       $return[$property] = $value;
+                       return $return;
+               }
+
+               if (strpos($value, '/') !== false) {
+                       $values = $this->explode_ws('/', $value);
+                       if (count($values) == 2) {
+                               $r[0] = $this->dissolve_4value_shorthands($property, trim($values[0]), $shorthands);
+                               $r[1] = $this->dissolve_4value_shorthands($property, trim($values[1]), $shorthands);
+                               $return = array();
+                               foreach ($r[0] as $p=>$v) {
+                                       $return[$p] = $v;
+                                       if ($r[1][$p] !== $v) {
+                                               $return[$p] .= ' ' . $r[1][$p];
+                                       }
+                               }
+                               return $return;
+                       }
+               }
+
+               $return = $this->dissolve_4value_shorthands($property, $value, $shorthands);
+               return $return;
+       }
+
        /**
         * Explodes a string as explode() does, however, not if $sep is escaped or within a string.
         * @param string $sep seperator
         * @param string $string
+        * @param bool $explode_in_parenthesis
         * @return array
         * @version 1.0
         */
-       public function explode_ws($sep, $string) {
+       public function explode_ws($sep, $string, $explode_in_parenthesis = false) {
                $status = 'st';
                $to = '';
 
-               $output = array();
+               $output = array(
+                       0 => '',
+               );
                $num = 0;
                for ($i = 0, $len = strlen($string); $i < $len; $i++) {
                        switch ($status) {
                                case 'st':
                                        if ($string{$i} == $sep && !$this->parser->escaped($string, $i)) {
                                                ++$num;
-                                       } elseif ($string{$i} === '"' || $string{$i} === '\'' || $string{$i} === '(' && !$this->parser->escaped($string, $i)) {
+                                       } elseif ($string{$i} === '"' || $string{$i} === '\'' || (!$explode_in_parenthesis && $string{$i} === '(') && !$this->parser->escaped($string, $i)) {
                                                $status = 'str';
                                                $to = ($string{$i} === '(') ? ')' : $string{$i};
                                                (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
@@ -602,27 +667,26 @@ class csstidy_optimise {
                        }
                }
 
-               if (isset($output[0])) {
-                       return $output;
-               } else {
-                       return array($output);
-               }
+               return $output;
        }
 
        /**
         * Merges Shorthand properties again, the opposite of dissolve_4value_shorthands()
         * @param array $array
+        * @param array|null $shorthands
         * @return array
         * @version 1.2
         * @see dissolve_4value_shorthands()
         */
-       public function merge_4value_shorthands($array) {
+       public function merge_4value_shorthands($array, $shorthands = null) {
                $return = $array;
-               $shorthands = & $this->parser->data['csstidy']['shorthands'];
+               if (is_null($shorthands)) {
+                       $shorthands = & $this->parser->data['csstidy']['shorthands'];
+               }
 
                foreach ($shorthands as $key => $value) {
-                       if (isset($array[$value[0]]) && isset($array[$value[1]])
-                                                       && isset($array[$value[2]]) && isset($array[$value[3]]) && $value !== 0) {
+                       if ($value !== 0 && isset($array[$value[0]]) && isset($array[$value[1]])
+                                                       && isset($array[$value[2]]) && isset($array[$value[3]])) {
                                $return[$key] = '';
 
                                $important = '';
@@ -642,6 +706,45 @@ class csstidy_optimise {
                return $return;
        }
 
+       /**
+        * Merges Shorthand properties again, the opposite of dissolve_4value_shorthands()
+        * @param array $array
+        * @return array
+        * @version 1.2
+        * @use merge_4value_shorthands()
+        * @see dissolve_4value_radius_shorthands()
+        */
+       public function merge_4value_radius_shorthands($array) {
+               $return = $array;
+               $shorthands = & $this->parser->data['csstidy']['radius_shorthands'];
+
+               foreach ($shorthands as $key => $value) {
+                       if (isset($array[$value[0]]) && isset($array[$value[1]])
+                                                       && isset($array[$value[2]]) && isset($array[$value[3]]) && $value !== 0) {
+                               $return[$key] = '';
+                               $a = array();
+                               for ($i = 0; $i < 4; $i++) {
+                                       $v = $this->explode_ws(' ', trim($array[$value[$i]]));
+                                       $a[0][$value[$i]] = reset($v);
+                                       $a[1][$value[$i]] = end($v);
+                               }
+                               $r = array();
+                               $r[0] = $this->merge_4value_shorthands($a[0], $shorthands);
+                               $r[1] = $this->merge_4value_shorthands($a[1], $shorthands);
+
+                               if (isset($r[0][$key]) and isset($r[1][$key])) {
+                                       $return[$key] = $r[0][$key];
+                                       if ($r[1][$key] !== $r[0][$key]) {
+                                               $return[$key] .= ' / ' . $r[1][$key];
+                                       }
+                                       for ($i = 0; $i < 4; $i++) {
+                                               unset($return[$value[$i]]);
+                                       }
+                               }
+                       }
+               }
+               return $return;
+       }
        /**
         * Dissolve background property
         * @param string $str_value
@@ -899,7 +1002,7 @@ class csstidy_optimise {
                $new_font_value = '';
                $important = '';
                // Skip if not font-family and font-size set
-               if (isset($input_css['font-family']) && isset($input_css['font-size'])) {
+               if (isset($input_css['font-family']) && isset($input_css['font-size']) && $input_css['font-family'] != 'inherit') {
                        // fix several words in font-family - add quotes
                        if (isset($input_css['font-family'])) {
                                $families = explode(',', $input_css['font-family']);
@@ -959,4 +1062,237 @@ class csstidy_optimise {
                return $input_css;
        }
 
+       /**
+        * Reverse left vs right in a list of properties/values
+        * @param array $array
+        * @return array
+        */
+       public function reverse_left_and_right($array) {
+               $return = array();
+
+               // change left <-> right in properties name and values
+               foreach ($array as $propertie => $value) {
+
+                       if (method_exists($this, $m = 'reverse_left_and_right_' . str_replace('-','_',trim($propertie)))) {
+                               $value = $this->$m($value);
+                       }
+
+                       // simple replacement for properties
+                       $propertie = str_ireplace(array('left', 'right' ,"\x1"), array("\x1", 'left', 'right') , $propertie);
+                       // be careful for values, not modifying protected or quoted valued
+                       foreach (array('left' => "\x1", 'right' => 'left', "\x1" => 'right') as $v => $r) {
+                               if (strpos($value, $v) !== false) {
+                                       // attraper les left et right separes du reste (pas au milieu d'un mot)
+                                       if (in_array($v, array('left', 'right') )) {
+                                               $value = preg_replace(",\\b$v\\b,", "\x0" , $value);
+                                       }
+                                       else {
+                                               $value = str_replace($v, "\x0" , $value);
+                                       }
+                                       $value = $this->explode_ws("\x0", $value . ' ', true);
+                                       $value = rtrim(implode($r, $value));
+                                       $value = str_replace("\x0" , $v, $value);
+                               }
+                       }
+                       $return[$propertie] = $value;
+               }
+
+               return $return;
+       }
+
+       /**
+        * Reversing 4 values shorthands properties
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_4value_shorthands($property, $value) {
+               $shorthands = & $this->parser->data['csstidy']['shorthands'];
+               if (isset($shorthands[$property])) {
+                       $property_right = $shorthands[$property][1];
+                       $property_left = $shorthands[$property][3];
+                       $v = $this->dissolve_4value_shorthands($property, $value);
+                       if ($v[$property_left] !== $v[$property_right]) {
+                               $r = $v[$property_right];
+                               $v[$property_right] = $v[$property_left];
+                               $v[$property_left] = $r;
+                               $v = $this->merge_4value_shorthands($v);
+                               if (isset($v[$property])) {
+                                       return $v[$property];
+                               }
+                       }
+               }
+               return $value;
+       }
+
+       /**
+        * Reversing 4 values radius shorthands properties
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_4value_radius_shorthands($property, $value) {
+               $shorthands = & $this->parser->data['csstidy']['radius_shorthands'];
+               if (isset($shorthands[$property])) {
+                       $v = $this->dissolve_4value_radius_shorthands($property, $value);
+                       if ($v[$shorthands[$property][0]] !== $v[$shorthands[$property][1]]
+                         or $v[$shorthands[$property][2]] !== $v[$shorthands[$property][3]]) {
+                               $r = array(
+                                       $shorthands[$property][0] => $v[$shorthands[$property][1]],
+                                       $shorthands[$property][1] => $v[$shorthands[$property][0]],
+                                       $shorthands[$property][2] => $v[$shorthands[$property][3]],
+                                       $shorthands[$property][3] => $v[$shorthands[$property][2]],
+                               );
+                               $v = $this->merge_4value_radius_shorthands($r);
+                               if (isset($v[$property])) {
+                                       return $v[$property];
+                               }
+                       }
+               }
+               return $value;
+       }
+
+       /**
+        * Reversing margin shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_margin($value) {
+               return $this->reverse_left_and_right_4value_shorthands('margin', $value);
+       }
+
+       /**
+        * Reversing padding shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_padding($value) {
+               return $this->reverse_left_and_right_4value_shorthands('padding', $value);
+       }
+
+       /**
+        * Reversing border-color shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_border_color($value) {
+               return $this->reverse_left_and_right_4value_shorthands('border-color', $value);
+       }
+
+       /**
+        * Reversing border-style shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_border_style($value) {
+               return $this->reverse_left_and_right_4value_shorthands('border-style', $value);
+       }
+
+       /**
+        * Reversing border-width shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_border_width($value) {
+               return $this->reverse_left_and_right_4value_shorthands('border-width', $value);
+       }
+
+       /**
+        * Reversing border-radius shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_border_radius($value) {
+               return $this->reverse_left_and_right_4value_radius_shorthands('border-radius', $value);
+       }
+
+       /**
+        * Reversing border-radius shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right__moz_border_radius($value) {
+               return $this->reverse_left_and_right_4value_radius_shorthands('border-radius', $value);
+       }
+
+       /**
+        * Reversing border-radius shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right__webkit_border_radius($value) {
+               return $this->reverse_left_and_right_4value_radius_shorthands('border-radius', $value);
+       }
+
+
+       /**
+        * Reversing background shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_background($value) {
+               $values = $this->dissolve_short_bg($value);
+               if (isset($values['background-position']) and $values['background-position']) {
+                       $v = $this->reverse_left_and_right_background_position($values['background-position']);
+                       if ($v !== $values['background-position']) {
+                               if ($value == $values['background-position']) {
+                                       return $v;
+                               }
+                               else {
+                                       $values['background-position'] = $v;
+                                       $x = $this->merge_bg($values);
+                                       if (isset($x['background'])) {
+                                               return $x['background'];
+                                       }
+                               }
+                       }
+               }
+               return $value;
+       }
+
+       /**
+        * Reversing background position shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_background_position_x($value) {
+               return $this->reverse_left_and_right_background_position($value);
+       }
+
+       /**
+        * Reversing background position shorthands
+        * @param string $value
+        * @return string
+        */
+       public function reverse_left_and_right_background_position($value) {
+               // multiple background case
+               if (strpos($value, ',') !== false) {
+                       $values = $this->explode_ws(',', $value);
+                       if (count($values) > 1) {
+                               foreach ($values as $k=>$v) {
+                                       $values[$k] = $this->reverse_left_and_right_background_position($v);
+                               }
+                               return implode(',', $values);
+                       }
+               }
+
+               // if no explicit left or right value
+               if (stripos($value, 'left') === false and stripos($value, 'right') === false) {
+                       $values = $this->explode_ws(' ', trim($value));
+                       $values = array_map('trim', $values);
+                       $values = array_filter($values);
+                       $values = array_values($values);
+                       if (count($values) == 1) {
+                               return "left $value";
+                       }
+                       if ($values[1] == 'top' or $values[1] == 'bottom') {
+                               return 'left ' . implode(' ', $values);
+                       }
+                       else {
+                               $last = array_pop($values);
+                               return implode(' ', $values) . ' left ' . $last;
+                       }
+               }
+
+               return $value;
+       }
+
 }