<?php 
 
 
/**
 
 * CssShrink
 
 * 
 
 * @package CssShrink v1.0 - CSS Compressor & Uncompressor
 
 * @author João Romão (iceburn.info)
 
 * @version 2008
 
 * @access public
 
 */
 
class CssShrink {
 
    
 
    // Alowed 'normal' CSS chars regex constant
 
    const chars_regex = '[^a-z0-9-_\{\}\>:;\*\.\#,\/\/\s\'\)\(\[\]!%@=\$\^]';    
 
    
 
    public static $css;
 
    
 
    
 
    /**
 
     * CssShrink::compressed()
 
     * 
 
     * @return string
 
     */
 
    public function compressed() {
 
        return self::filter($this->css);
 
    }
 
 
 
    /**
 
     * CssShrink::uncompressed()
 
     * 
 
     * @return string
 
     */
 
    public function uncompressed($str = null) {
 
        return self::reverse(self::prepare(is_null($str) ? $this->css : $str));
 
    }
 
 
 
    /**
 
     * CssShrink::gain()
 
     * 
 
     * @return int
 
     */
 
    public function gain() {
 
        return (int)(strlen($this->css) - strlen(self::filter($this->css)));
 
    }
 
 
 
    /**
 
     * CssShrink::dump2file()
 
     * 
 
     * @param mixed $filename
 
     * @param mixed $contents
 
     * @return bool
 
     */
 
    public function dump2file($filename, $contents) {
 
       
 
        // Attempt to create file, if not exists
 
        if(!is_file($filename)) {
 
          touch($filename) or die('Attempt to create inexistent file failed!');
 
        }
 
        
 
        // Attempt to chmod 777 before write
 
        chmod($filename, 0777);    
 
        
 
        // Write to file
 
        if(file_put_contents($filename, $contents, LOCK_EX)) {
 
          chmod($filename, 0644);
 
          return true;    
 
        } else {
 
          // chmod 644, even if cannot write to file
 
          chmod($filename, 0644);    
 
        }
 
        
 
        return false;
 
    }
 
 
 
    /**
 
     * CssShrink::prepare()
 
     * 
 
     * @param mixed $str
 
     * @return string
 
     */
 
    private static function prepare($str) {
 
 
        // Globalize quotes format
 
        $str = str_replace('"', "'", $str);
 
 
        // Only process allowed CSS chars, and strip all others
 
        $str = preg_replace('/' . self::chars_regex . '/i', '', $str);
 
 
        // Remove CSS Comments
 
        $str = preg_replace('/(\/\*(.*?)\*\/)/s', '', $str);
 
        
 
        // Remove all unecessary spaces
 
        $str = preg_replace('/\s\s+/', ' ', $str);
 
        
 
        return $str;
 
    }
 
 
 
    /**
 
     * CssShrink::filter()
 
     * 
 
     * @param mixed $css
 
     * @return string
 
     */
 
    private static function filter($css) {
 
 
        $css = self::prepare($css);
 
 
        // Remove spaces around certain chars
 
        $css = preg_replace('/(\s)?(:|;|,|{|})(\s)?/s', '\\2', $css);
 
 
        /**
 
         * Final clean up:
 
         * - Semi-colon is not needed in last atribute
 
         * - In url() quotes are not needed
 
         */
 
        $css = str_replace(array("('", "')", ';}'), array('(', ')', '}'), $css);
 
 
        return trim($css);
 
    }
 
 
 
    /**
 
     * CssShrink::reverse()
 
     * 
 
     * @param mixed $css
 
     * @return string
 
     */
 
    private static function reverse($css) {
 
 
        $css = self::prepare($css);
 
        
 
        // Remove unhandled line breaks and tabs
 
        $css = str_replace(array("\n", "\r", "\t"), ' ', $css);
 
        
 
        // Add spaces next to certain chars
 
        $css = preg_replace('/(\s)?(;|:|,|{|})(\s)?/s', '\\2 ', $css);
 
        
 
        // Some extra CSS beautify and cleanup
 
        $src = array('(', ')', ';}', "(''", "'')");
 
        $rep = array("('", "')", '}', "('", "')");
 
        $css = str_replace($src, $rep, $css);
 
        unset($src, $rep);
 
        
 
        // Add new lines after '{', ';' and '}'
 
        $src = array('{', '}', ';');
 
        $rep = array(" {\n", ";}\n\n", ";\n");
 
        $css = str_replace($src, $rep, $css);
 
        unset($src, $rep);
 
 
        // Temporary, turn the whole CSS into an array
 
        // TODO: Simplify the array process, and process everything as a string    
 
        $css_array = array_map('ltrim', explode("\n", $css));
 
 
        $ncss = array();
 
        
 
        foreach ($css_array as $data) {
 
            
 
            if(!ereg('^;', $data)) {
 
              
 
              //  Make indents
 
              $data = (preg_match('/({|}|,)/', $data) && !ereg('^(font)', $data)) ? str_replace(': ', ':', $data) : '    ' . $data;
 
              
 
              // Remove space after ':' in URL's
 
              $data = preg_replace("/(http:)(\s)/", '\\1', $data);
 
              
 
              // Add to new array
 
              $ncss[] = $data;
 
              
 
              // Free some memory
 
              unset($data);
 
            }
 
        }
 
        
 
        // Free some memory
 
        unset($css_array);
 
        
 
        // Correct selectors with no content (removes the ';' previously added)
 
        $css = preg_replace("/({)\n(\s){4};\n(})/s", "\\1 \\3", implode("\n", $ncss));
 
        
 
        // Free some memory
 
        unset($ncss);
 
        
 
        return rtrim($css);
 
    }
 
 
 
} // end of class 'CssShrink'
 
?>
 
 |