Robson » Code Viewer
- Path: code/css_compressor.php
- Lines: 915
- Size: 31.19kB
<? /* CSS Compressor v0.13 http://iceyboard.no-ip.org/projects/css_compressor Copyright (C) 2008-2011 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 ($_REQUEST['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 ($_REQUEST['opt_rgb2hex']) rgb2hex($cssfile); // shorten colours if ($_REQUEST['opt_colours2hex']) long_colours_to_short_hex($cssfile); if ($_REQUEST['opt_hex2colours']) long_hex_to_short_colours($cssfile); // remove any extra measurements that aren't needed if ($_REQUEST['opt_remove_zeros']) remove_zero_measurements($cssfile); // seperate into selectors and properties sort_css($cssfile); // change font weight text into numbers if ($_REQUEST['opt_text_weights_to_numbers']) font_weight_text_to_numbers($cssfile); // check if any selectors are used twice and combine the properties if ($_REQUEST['opt_combine_identical_selectors']) combine_identical_selectors(); // remove any properties which are declared twice in one rule if ($_REQUEST['opt_remove_overwritten_properties']) remove_overwritten_properties(); // check if properties should be combined if ($_REQUEST['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 ($_REQUEST['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 ($_REQUEST['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>'; } if ($_REQUEST['upload_link']) { $_REQUEST['upload_style'] = NULL; if (!$_POST['upload_link']) $_POST = $_GET; foreach ($_POST as $key => $value) if ($value) if (!$url) $url .= '?' . $key . '=' . $value; else $url .= '&' . $key . '=' . $value; echo '<ul><li><a href="http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . $url . '">Link to this output</a>.</ul>'; } 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($_REQUEST['upload_link'] != 'http://' && eregi('http:\/\/*', $_REQUEST['upload_link'])) { // grab a remote file for compressing // the at symbol stops php from producing errors, because i've specified one $cssfile = @file($_REQUEST['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($_REQUEST['upload_style']) // store the css into the css file variable return $_REQUEST['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)); // don't touch rgba values! if($string[3] != 'a') { // 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'), array('ffffff', 'white')); // 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);} // 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]); $file_props[$a][$b] = str_replace('font:bold', 'font:700', $file_props[$a][$b]); } }} // seperate the parts of each rulefunction parse_rules($css){ // make these variables available to this function global $file_selector; global $file_props; // get the selectors contained in this part of the sheet $selector = substr($css, 0, strpos($css, '{')); // get the css properties and values contained in this part of the sheet $props = trim(substr($css, strlen($selector)+1, -1)); // remove extra space from before, between and after the selector(s) strip_space($selector); // remove any additional space $selector = trim(eregi_replace(', +', ',', $selector)); $selector = trim(eregi_replace(' +,', ',', $selector)); // seperate selector(s) and add to the global selector array $file_selector[] = array_unique(explode(',', $selector)); // shorten the css code strip_space($props); // remove any additional space $props = trim(eregi_replace('(:|;) +', '\\1', $props)); $props = trim(eregi_replace(' +(:|;)', '\\1', $props)); $props = trim(eregi_replace('\( +', '(', $props)); $props = trim(eregi_replace(' +\)', ')', $props)); // if the last character is a semi-colon if (substr($props, strlen($props)-1, 1) == ';') // remove it $props = substr($props, 0, -1); // seperate properties and add to the global props array $file_props[] = explode(';', $props);} // removes white space from a string and returns the resultfunction strip_space(&$string){ // kill whitespace on classes // kill new lines $string = str_replace(chr(10), '', $string); $string = str_replace(chr(13), '', $string); // change tabs into spaces $string = str_replace(chr(9), ' ', $string); // remove additional white space $string = eregi_replace(' +', ' ', $string);} // the following code combines rules with the same single selector// currently it only works on rules which have one selectorfunction combine_identical_selectors(){ // make these arrays available to this function global $file_selector; global $file_props; // this will store which selectors have been used $cur_selectors = array(); // loop through all the rules for ($a = 0; $a < count($file_selector); $a++) { // check there is only one selector if (count($file_selector[$a]) == 1) { // see if this selector has been used before if (in_array($file_selector[$a][0], $cur_selectors)) { // if so, loop round until it can be found for ($b = 0; $b < count($cur_selectors); $b++) { // check if this matches a previous rule if ($cur_selectors[$b] == $file_selector[$a][0]) { // combine the properties in this rule and the previous one // they remian in the order they were in the file, so new rules override old ones $new_props = array_merge($file_props[$b], $file_props[$a]); // replace the current props with all of them $file_props[$a] = $new_props; // kill the old selector $file_selector[$b] = NULL; // kill the old properties $file_props[$b] = array(NULL); // remove from the selectors array $cur_selector[$b] = NULL; } } } // add the current selector to the selectors array $cur_selectors[] = $file_selector[$a][0]; } else // add nothing to maintain the selector index $cur_selectors[] = NULL; }} // this removes duplicates classes from rules// if a property is repeated the last one is only used, so old oens can be safely removedfunction remove_overwritten_properties(){ // make these arrays available to this function global $file_selector; global $file_props; // loop through rules for ($a = 0; $a < count($file_props); $a++) { // this will store the property list $cur_props = array(); // loop through all the properties in the current rule for ($b = 0; $b < count($file_props[$a]); $b++) { // explode the property and the value $parts = explode(':', $file_props[$a][$b]); // check if this property has been used previously if (in_array($parts[0], $cur_props)) { // if so, find where for ($c = 0; $c < count($cur_props); $c++) { // check if it's the same as the old one if ($cur_props[$c] == $parts[0]) // kill the old one, it's not needed $file_props[$a][$c] = NULL; } } // add the type to the property array $cur_props[] = $parts[0]; } }} // this is the list of properties that can be combinedfunction combine_props_list(&$props){ // each call sends the current part of the stylesheet being worked on, // the combined property, // the parts which makes up this property combine_props($props, 'padding', array('padding-top', 'padding-right', 'padding-bottom', 'padding-left')); combine_props($props, 'margin', array('margin-top', 'margin-right', 'margin-bottom', 'margin-left')); combine_props($props, 'list-style', array('list-style-type', 'list-style-position', 'list-style-image')); combine_props($props, 'list-style', array('list-style-type', 'list-style-position')); combine_props($props, 'outline', array('outline-color', 'outline-style', 'outline-width')); // to do: this might be improvable combine_props($props, 'background', array('background-color', 'background-image', 'background-repeat', 'background-attachment', 'background-position')); combine_props($props, 'border-bottom', array('border-bottom-width', 'border-bottom-style', 'border-bottom-color')); combine_props($props, 'border-top', array('border-top-width', 'border-top-style', 'border-top-color')); combine_props($props, 'border-left', array('border-left-width', 'border-left-style', 'border-left-color')); combine_props($props, 'border-right', array('border-right-width', 'border-right-style', 'border-right-color')); combine_props_borders($props, 'border', array('border-bottom', 'border-top', 'border-left', 'border-right')); combine_props($props, 'border', array('border-width', 'border-style', 'border-color')); // to do: this needs some checking combine_props($props, 'font', array('font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family')); /* combine_props($props, 'font', array('font-style', 'font-variant', 'font-weight', 'font-size', 'font-family')); combine_props($props, 'font', array('font-variant', 'font-weight', 'font-size', 'line-height', 'font-family')); combine_props($props, 'font', array('font-style', 'font-weight', 'font-size', 'line-height', 'font-family')); combine_props($props, 'font', array('font-style', 'font-variant', 'font-size', 'line-height', 'font-family')); combine_props($props, 'font', array('font-variant', 'font-weight', 'font-size', 'font-family')); combine_props($props, 'font', array('font-style', 'font-weight', 'font-size', 'font-family')); combine_props($props, 'font', array('font-style', 'font-variant', 'font-size', 'font-family')); combine_props($props, 'font', array('font-variant', 'font-size', 'font-family')); combine_props($props, 'font', array('font-weight', 'font-size', 'font-family')); combine_props($props, 'font', array('font-style', 'font-size', 'font-family')); */} // this code is responsible for combining properties off rules// example: margin-left, margin-right, margin-top, margin-bottom can be combined to just margin:// the combined variable would be 'margin' and the parts would be the properties beforefunction combine_props_borders(&$props, $combined, $parts){ // split the properties and values for ($n = 0; $n < count($props); $n++) { // add the type to an array $props_type[] = substr($props[$n], 0, strpos($props[$n], ':')); // add the values to an array, although those are just stored and not processed $props_values[] = substr($props[$n], strpos($props[$n], ':')+1, strlen($props[$n])); } // assume it's combinable $combinable = TRUE; // loop through all the different properties that can be combined in this instance for ($n = 0; $n < count($parts); $n++) { // check if this property isn't contained within the combinable array if (!in_array($parts[$n], $props_type)) { // if so, it can't be combined, so store that $combinable = FALSE; } else { $these_props = substr($props[$n], strpos($props[$n], ':')+1, 100); } } if ($combinable) // loop through all the different properties that can be combined in this instance for ($n = 0; $n < count($parts); $n++) // check if this property isn't contained within the combinable array if (in_array($parts[$n], $props_type)) if (substr($props[$n], strpos($props[$n], ':')+1, 100) <> $these_props) // if so, it can't be combined, so store that $combinable = FALSE; // if any of the properties were contained in the combinable array if ($combinable) { // loop through all the parts for ($a = 0; $a < count($parts); $a++) { // loop through all the properties found here for ($b = 0; $b < count($props_type); $b++) { // check if it's the same if ($props_type[$b] == $parts[$a]) { // add the current values to the combined values // this must be done in the correct order $combined_values[] = $props_values[$b]; // no longer need the property since it's been added to the combined part, so remove it $props[$b] = NULL; } } } // add the new combined property with all the values of the individual propertys $props[] = $combined . ':' . $combined_values[0]; }} // this code is responsible for combining properties off rules// example: margin-left, margin-right, margin-top, margin-bottom can be combined to just margin:// the combined variable would be 'margin' and the parts would be the properties beforefunction combine_props(&$props, $combined, $parts){ // split the properties and values for ($n = 0; $n < count($props); $n++) { // add the type to an array $props_type[] = substr($props[$n], 0, strpos($props[$n], ':')); // add the values to an array, although those are just stored and not processed $props_values[] = substr($props[$n], strpos($props[$n], ':')+1, strlen($props[$n])); } // assume it's combinable $combinable = TRUE; // loop through all the different properties that can be combined in this instance for ($n = 0; $n < count($parts); $n++) { // check if this property isn't contained within the combinable array if (!in_array($parts[$n], $props_type)) // if so, it can't be combined, so store that $combinable = FALSE; } // if any of the properties were contained in the combinable array if ($combinable) { // loop through all the parts for ($a = 0; $a < count($parts); $a++) { // loop through all the properties found here for ($b = 0; $b < count($props_type); $b++) { // check if it's the same if ($props_type[$b] == $parts[$a]) { // add the current values to the combined values // this must be done in the correct order $combined_values[] = $props_values[$b]; // no longer need the property since it's been added to the combined part, so remove it $props[$b] = NULL; } } } // add the new combined property with all the values of the individual propertys $props[] = $combined . ':' . implode(' ', $combined_values); }} // this function just calls other onesfunction reduce_prop(&$item, $key){ // reduces six hex codes to three (#ff0000 -> #f00) if ($_REQUEST['opt_short_hex']) short_hex($item); // removes useless values from padding and margins (margin: 4px 5px 4px 5px -> margin: 4px 5px) if ($_REQUEST['opt_short_margins_and_paddings']); compress_padding_and_margins($item);} // this code turns hex codes into short three-character hex codes when possible// for example:// #ff0000 -> #f00// #aabbcc -> #abcfunction short_hex(&$item){ // check if this part of the code has some hex codes in it if (strstr($item, '#')) { // grab the next six characters $hex = substr($item, strpos($item, '#')+1, 6); // check if this is a hex code, so ids don't get picked up if (eregi('[0-9a-f]{6}', $hex)) { // if the characters in each pair match if ($hex[0] == $hex[1] && $hex[2] == $hex[3] && $hex[4] == $hex[5]) // it can be made shorter, so convert to the shorter version $item = eregi_replace('#' . $hex, '#' . $hex[0] . $hex[2] . $hex[4], $item); } }} // this removes the useless values from padding and margin properties// this code is run after properties are combined (like margin-left, margin-top etc)// for example// padding: 5px 5px 5px 5px -> padding: 5px// margin: 2px 4px 2px 4px -> margin: 2px 4px// padding: 3px 5px 9px 5px -> padding: 3px 5px 9pxfunction compress_padding_and_margins(&$item){ // get the type and value of the property $item_parts = explode(':', $item); // check if this is a padding or margin property if ($item_parts[0] == 'padding' || $item_parts[0] == 'margin') { // place all the values into an array $values = explode(' ', $item_parts[1]); // switched based on the number of values found // no need to check if it's 1, because that can't be compressed switch (count($values)) { // icey demonstrates the art of making pop corn: case 2: // example: margin: 4px 4px if ($values[0] == $values[1]) // example: margin: 4px array_pop($values); break; case 3: // example: margin: 5px 7px 5px if ($values[0] == $values[2]) { // example: margin: 5px 7px array_pop($values); // example: margin: 4px 4px if ($values[0] == $values[1]) // example: 4px array_pop($values); } break; case 4: // example: margin: 3px 7px 9px 7px if ($values[1] == $values[3]) { // example: 3px 7px 9px array_pop($values); // example: 3px 4px 3px if ($values[0] == $values[2]) { // example: 3px 4px array_pop($values); // example: 7px 7px if ($values[0] == $values[1]) // example: 7px array_pop($values); } } break; } // check if any changes were made by comparing the original values to the current values if (implode(' ', $values) != $item_parts[1]) // if so, change the item in the array to the shorter version $item = $item_parts[0] . ':' . implode(' ', $values); }} function remove_empty_rules(){ // make these arrays available to this function global $file_selector; global $file_props; // loop through each section of the css file and see if it contains no properties for ($a = 0; $a < count($file_selector); $a++) { // remove blank items from the array $file_props[$a] = array_values(array_diff($file_props[$a], array(NULL))); // check if this part has no properties if (!$file_props[$a][0]) { // remove the empty prop part of the array and the class(es) array_splice($file_selector, $a, 1); array_splice($file_props, $a, 1); // decrease by one due to the decreased total $a--; } }} // now that the stylesheet has been compressed as much as possible,// the code to combine identical classes is usedfunction combine_identical_rules(){ // make these variables available locally global $file_selector; global $file_props; // loop through each rule for ($a = 0; $a < count($file_props); $a++) { // loop from 0 up the current number, this ensures future processed properties aren't processed prematurely for ($b = 0; $b < $a; $b++) { if (substr($file_selector[$a][0], 0, 1) <> "@" && substr($file_selector[$b][0], 0, 1) <> "@") { // check if this rule is identical to an earlier one if (!array_diff($file_props[$a], $file_props[$b]) && !array_diff($file_props[$b], $file_props[$a])) { // combine the selectors $file_selector[$a] = array_unique(array_merge($file_selector[$a], $file_selector[$b])); // remove the old properties $file_props[$b] = array(NULL); // remove the old selectors $file_selector[$b] = array(NULL); } } } }} function create_output(){ global $file_selector; global $file_props; if ($_REQUEST['opt_output_colour']) { if ($_REQUEST['opt_output_compress']) { $css = '<span style="color:#000;font-family:monospace">'; for ($a = 0; $a < count($file_selector); $a++) { for ($b = 0; $b < count($file_selector[$a]); $b++) $file_selector[$a][$b] = '<span style="color:#685">' . $file_selector[$a][$b] . '</span>'; for ($b = 0; $b < count($file_props[$a]); $b++) { $parts = explode(':', $file_props[$a][$b]); $file_props[$a][$b] = '<span style="color:#c86464">' . $parts[0] . '</span>:<span style="color:#369">' . $parts[1] . '</span>'; } $css .= implode(',', $file_selector[$a]) . '{'; $css .= implode(';', $file_props[$a]) . '}'; } $css .= '</span>'; } else { $css = '<span style="color:#000;font-family:monospace">'; for ($a = 0; $a < count($file_selector); $a++) { for ($b = 0; $b < count($file_selector[$a]); $b++) $file_selector[$a][$b] = '<span style="color:#685">' . $file_selector[$a][$b] . '</span>'; for ($b = 0; $b < count($file_props[$a]); $b++) { $parts = explode(':', $file_props[$a][$b]); $file_props[$a][$b] = '<span style="color:#c86464"> ' . $parts[0] . '</span>: <span style="color:#369">' . $parts[1] . '</span>'; } $css .= implode(', ', $file_selector[$a]) . ' {<br>'; $css .= implode(';<br>', $file_props[$a]) . ';<br>}<br> <br>'; } $css .= '</span>'; } } else { if ($_REQUEST['opt_output_compress']) { $css = '<span style="font-family:monospace">'; for ($a = 0; $a < count($file_selector); $a++) { for ($b = 0; $b < count($file_selector[$a]); $b++) $file_selector[$a][$b] = $file_selector[$a][$b]; for ($b = 0; $b < count($file_props[$a]); $b++) { $parts = explode(':', $file_props[$a][$b]); $file_props[$a][$b] = '' . $parts[0] . ':' . $parts[1]; } $css .= implode(',', $file_selector[$a]) . '{'; $css .= implode(';', $file_props[$a]) . '}'; } $css .= '</span>'; } else { $css = '<span style="font-family:monospace">'; for ($a = 0; $a < count($file_selector); $a++) { for ($b = 0; $b < count($file_selector[$a]); $b++) $file_selector[$a][$b] = $file_selector[$a][$b]; for ($b = 0; $b < count($file_props[$a]); $b++) { $parts = explode(':', $file_props[$a][$b]); $file_props[$a][$b] = ' ' . $parts[0] . ': ' . $parts[1]; } $css .= implode(', ', $file_selector[$a]) . ' {<br>'; $css .= implode(';<br>', $file_props[$a]) . ';<br>}<br> <br>'; } $css .= '</span>'; } } return $css;} ?>