<?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'
?>
|