Robson » Code Viewer
- Path: code/css_compressor.php
- Lines: 831
- Size: 28.52kB
<? /* CSS Compressor v0.6 http://iceyboard.no-ip.org/projects/css_compressor Copyright (C) 2008 Robson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/ // functions appear in the order they are first called compress_css(); function compress_css(){ // make these variables available locally global $file_selector; global $file_props; // first, get the css that was sent, referenced or uploaded $cssfile = get_sent_css(); // check if the user wants to see statistics if ($_POST['opt_output_stats']) { // save the size of the code $start_size = strlen($cssfile); // save the current time $start = explode(' ', microtime()); } // check if no css was found if (!$cssfile) // just die exit ("/* You didn't upload anything or the stylesheet is empty - Ro" . "bson */"); // temporarily change semicolons in web links $cssfile = str_replace('://', '[!semi-colon!]//', $cssfile); // remove html and css comments kill_comments($cssfile); // trim whitespace from the start and end $cssfile = trim($cssfile); // turn all rgb values into hex if ($_POST['opt_rgb2hex']) rgb2hex($cssfile); // shorten colours if ($_POST['opt_colours2hex']) long_colours_to_short_hex($cssfile); if ($_POST['opt_hex2colours']) long_hex_to_short_colours($cssfile); // remove any extra measurements that aren't needed if ($_POST['opt_remove_zeros']) remove_zero_measurements($cssfile); // seperate into selectors and properties sort_css($cssfile); // change font weight text into numbers if ($_POST['opt_text_weights_to_numbers']) font_weight_text_to_numbers($cssfile); // check if any selectors are used twice and combine the properties if ($_POST['opt_combine_identical_selectors']) combine_identical_selectors(); // remove any properties which are declared twice in one rule if ($_POST['opt_remove_overwritten_properties']) remove_overwritten_properties(); // check if properties should be combined if ($_POST['opt_combine_props_list']) { // for each rule in the file for ($n = 0; $n < count($file_props); $n++) // attempt to combine the different parts combine_props_list($file_props[$n]); } // for each rule in the file for ($n = 0; $n < count($file_props); $n++) // run all the individual functions to reduce their size array_walk($file_props[$n], 'reduce_prop'); // remove all the properties that were blanked out earlier remove_empty_rules(); // check if any rules are the same as other ones and remove the first ones if ($_POST['opt_combine_identical_rules']) combine_identical_rules(); // one final run through to remove all unnecessary parts of the arrays remove_empty_rules(); $output = create_output(); // turn back colons $output = str_replace('[!semi-colon!]//', '://', $output); $output = stripslashes($output); // check if the user wants to view stats if ($_POST['opt_output_stats']) { echo '<h1>Statistics</h1><ul>'; echo '<li>Original size: ' . round($start_size / 1024, 2) . ' kB (' . number_format($start_size) . ' B)</li>'; echo '<li>Final size: ' . round(strlen(strip_tags($output)) / 1024, 2) . ' kB (' . number_format(strlen(strip_tags($output))) . ' B)</li>'; echo '<li>Saved: ' . round(($start_size - strlen(strip_tags($output))) / 1024, 2) . ' kB (' . number_format(($start_size - strlen(strip_tags($output)))) . ' B)</li>'; echo '<li>Reduction: ' . round(100 - ((strlen(strip_tags($output)) / $start_size) * 100), 2) . '%</li>'; echo '</ul>'; $finish = explode(' ', microtime()); // work out the differences between the times $seconds = $finish[1] - $start[1]; $miliseconds = $finish[0] - $start[0]; $duration = round($seconds + $miliseconds, 5); echo '<ul>'; echo '<li>Duration: ' . $duration . ' seconds</li>' ; echo '</ul>'; echo '<ul>'; echo '<li>Rules: ' . count($file_selector) . '</li>'; for ($n = 0; $n < count($file_selector); $n++) $selectors += count($file_selector[$n]); for ($n = 0; $n < count($file_props); $n++) $props += count($file_props[$n]); echo '<li>Selectors: ' . $selectors . '</li>'; echo '<li>Properties: ' . $props . '</li>'; echo '</ul>'; echo '<h1>CSS</h1>'; } echo $output;} // retrieves the css sent by the user// can handle uploaded stylesheets, url references and directly uploaded cssfunction get_sent_css(){ // check if they uploaded a file if ($_FILES['upload_file']['name']) // grab the uploaded file from it's temporary position // the temporary file is deleted at the end of the scripts execution // this implodes all the lines of the file into one simple variable return implode('', file($_FILES['upload_file']['tmp_name'])); // the eregi check is for security, it ensures people don't request files on the local server else if($_POST['upload_link'] != 'http://' && eregi('http:\/\/*', $_POST['upload_link'])) { // grab a remote file for compressing // the at symbol stops php from producing errors, because i've specified one $cssfile = @file($_POST['upload_link']) or die("/* Error: Sorry, that URL couldn't be found. */"); // implode the code return implode('', $cssfile); } // check if they posted css else if($_POST['upload_style']) // store the css into the css file variable return $_POST['upload_style']; // the user wants to combine multiple uploaded files else if ($_FILES['upload_file_1']['name']) { // add the first file to the current css code $file = implode('', file($_FILES['upload_file_1']['tmp_name'])); // check if they added another file if ($_FILES['upload_file_2']['name']) // if so, add that one to the css code string $file .= implode('', file($_FILES['upload_file_2']['tmp_name'])); // check if they added another file if ($_FILES['upload_file_3']['name']) // if so, add that one to the css code string $file .= implode('', file($_FILES['upload_file_3']['tmp_name'])); // check if they added another file if ($_FILES['upload_file_4']['name']) // if so, add that one to the css code string $file .= implode('', file($_FILES['upload_file_4']['tmp_name'])); // check if they added another file if ($_FILES['upload_file_5']['name']) // if so, add that one to the css code string $file .= implode('', file($_FILES['upload_file_5']['tmp_name'])); // check if they added another file if ($_FILES['upload_file_6']['name']) // if so, add that one to the css code string $file .= implode('', file($_FILES['upload_file_6']['tmp_name'])); // check if they added another file if ($_FILES['upload_file_7']['name']) // if so, add that one to the css code string $file .= implode('', file($_FILES['upload_file_7']['tmp_name'])); // check if they added another file if ($_FILES['upload_file_8']['name']) // if so, add that one to the css code string $file .= implode('', file($_FILES['upload_file_8']['tmp_name'])); // check if they added another file if ($_FILES['upload_file_9']['name']) // if so, add that one to the css code string $file .= implode('', file($_FILES['upload_file_9']['tmp_name'])); // check if they added another file if ($_FILES['upload_file_10']['name']) // if so, add that one to the css code string $file .= implode('', file($_FILES['upload_file_10']['tmp_name'])); return $file; } else return NULL;} // this removes html and css comments from the filefunction kill_comments(&$css){ // kill html comments $css = str_replace('<!--', '', $css); $css = str_replace('-->', '', $css); // kill css comments $css = preg_replace('/\/\*(.*?)\*\//si', '', $css);} // converts any rgb values to hex values// i.e. rgb(255,170,0) -> #ffaa00function rgb2hex(&$string){ // loop only while there are rgb values in the string while (strpos($string, 'rgb')) { // find the location of the first rgb value $where = strpos($string, 'rgb'); // add everything before to the new string $text .= substr($string, 0, $where); // remove the before part from the original string $string = substr($string, $where, strlen($string)); // find the end of the rgb value $where = strpos($string, ')'); // get the rgb value, like 'rgb(255, 170, 0)' $rgb = substr($string, 0, $where+1); // remove spaces, like 'rgb(255,170,0)' $rgb = eregi_replace(' +', '', $rgb); // remove the parts that aren't values, like '255,170,0' $rgb = substr($rgb, 4, -1); // explode the values into an array, like 255|170|0 $rgb = explode(',', $rgb); // set colour to nothing so it doesn't use the previous value $colour = ''; // loop through each rgb value, for red, green and blue for ($n = 0; $n < 3; $n++) // ff or 0f - always return two characters $colour .= strlen(dechex($rgb[$n])) == 1 ? '0' . dechex($rgb[$n]) : dechex($rgb[$n]) ; // 'ffaa00' - add the six-character hex value $text .= '#' . $colour; // remove the rgb property from the string $string = substr($string, $where+1, strlen($string)); } // add the remaining parts of the file back to the original string // return the new string with rgb values converted to hex values $string = $text . $string;} // turn long colour names into short hex codes// for example: fuscia -> #ff00ff (which is then compressed later to #f0f)function long_colours_to_short_hex(&$string){ // first, change colour names into hex values // hex values are shortened later, so this is done now $colours = array(array('000000', 'black'), array('ff00ff', 'fuchsia'), array('ffff00', 'yellow')); // loop through each colour for ($n = 0; $n < count($colours); $n++) // replace all instances of this colour with the hex code $string = str_replace(":" . $colours[$n][1], ':#' . $colours[$n][0], $string); // convert instances of 'white' to #fff $string = eregi_replace("white([^-])", "#ffffff\\1", $string);} // this converts hex colour codes to shorter text equivilants// only the standard sixteen colours codes are used herefunction long_hex_to_short_colours(&$string){ // the colours that are shorter than the hex representation of them $colours = array( array('808080', 'gray'), array('008000', 'green'), array('800000', 'maroon'), array('00080', 'navy'), array('808000', 'olive'), array('800080', 'purple'), array('ff0000', 'red'), array('c0c0c0', 'silver'), array('008080', 'teal') ); // loop through each colour for ($n = 0; $n < count($colours); $n++) // replace hex with colour name // ie #808080 -> gray $string = str_replace('#' . $colours[$n][0], $colours[$n][1], $string);} // zero is always zero, so measurements don't matterfunction remove_zero_measurements(&$string){ // change 0 ems, 0 pixels and 0 percentages to 0 // this wont change values like 10px, since those do need measurements $string = trim(eregi_replace('([^0-9])0(px|em|\%)', '\\10', ' ' . $string)); $string = trim(eregi_replace('([^0-9])0\.([0-9]+)em', '\\1.\\2em', ' ' . $string));} // this seperates the css file into it's rules,// which it then sends to another function to sort into each partfunction sort_css($cssfile){ // the first thing to do is seperate everything out in the file // so loop round each rule in the file while ($cssfile) { // check if there is some more code if (substr_count($cssfile, '}')) { // the next rule is everything up to the squiggly bracket $rule = substr($cssfile, 0, strpos($cssfile, '}')+1); // seperate out everything in this rule and add it to different global arrays parse_rules($rule); // remove that rule from the css file $cssfile = substr($cssfile, strlen($rule), strlen($cssfile)); } // no more rules? else // kill the css file variable to terminate this loop unset($cssfile); }} // turns font-weight text into numbers// for example: font-weight:normal -> font-weight:400function font_weight_text_to_numbers(&$string){ // make these variables available to this function global $file_selector; global $file_props; for ($a = 0; $a < count($file_props); $a++) { for ($b = 0; $b < count($file_props[$a]); $b++) { if ($file_props[$a][$b] == 'font-weight:bold') $file_props[$a][$b] = 'font-weight:700'; if ($file_props[$a][$b] == 'font-weight:normal') $file_props[$a][$b] = 'font-weight:400'; $file_props[$a][$b] = str_replace('font:normal', 'font:400', $file_props[$a][$b]);