summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Andreev <narf@bofh.bg>2012-12-28 14:55:23 +0100
committerAndrey Andreev <narf@bofh.bg>2012-12-28 14:55:23 +0100
commit37141da3f20c5eed7ee0b9527498ade000fe3080 (patch)
tree0798611fa615344b7aa72bf1f990eba4a4f6051c
parent16c26ff619d460228066e25ab2bc314925b85760 (diff)
parent96b9501f42ac773c9ec4fcda2a6ecabe72222365 (diff)
Merge pull request #2097 from AndrewPodner/feature-minify
issue #2092 : Improve/Revise JS and CSS minify method
-rw-r--r--system/core/Output.php64
1 files changed, 57 insertions, 7 deletions
diff --git a/system/core/Output.php b/system/core/Output.php
index 9367e3b43..b6f69fd88 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -802,7 +802,16 @@ class CI_Output {
* the string initially and saved without stripping whitespace to preserve
* the tags and any associated properties if tags are present
*
- * @param string $output Output to minify
+ * Minification logic/workflow is similar to methods used by Douglas Crockford
+ * in JSMIN. http://www.crockford.com/javascript/jsmin.html
+ *
+ * KNOWN ISSUE: ending a line with a closing parenthesis ')' and no semicolon
+ * where there should be one will break the Javascript. New lines after a
+ * closing parenthesis are not recognized by the script. For best results
+ * be sure to terminate lines with a semicolon when appropriate.
+ *
+ *
+ * @param string $output Output to minify
* @param bool $has_tags Specify if the output has style or script tags
* @return string Minified output
*/
@@ -812,7 +821,7 @@ class CI_Output {
if ($has_tags === TRUE)
{
// Remove opening tag and save for later
- $pos = strpos($output, '>');
+ $pos = strpos($output, '>') + 1;
$open_tag = substr($output, 0, $pos);
$output = substr_replace($output, '', 0, $pos);
@@ -830,8 +839,13 @@ class CI_Output {
// semi-colons, parenthesis, commas
$output = preg_replace('!\s*(:|;|,|}|{|\(|\))\s*!i', '$1', $output);
- // Remove spaces
- $in_string = $in_dstring = FALSE;
+ // Replace tabs with spaces
+ // Replace carriage returns & multiple new lines with single new line
+ // and trim any leading or trailing whitespace
+ $output = trim(preg_replace(array('/\t+/', '/\r/', '/\n+/'), array(' ', "\n", "\n"), $output));
+
+ // Remove spaces when safe to do so.
+ $in_string = $in_dstring = $prev = FALSE;
$array_output = str_split($output);
foreach ($array_output as $key => $value)
{
@@ -839,7 +853,24 @@ class CI_Output {
{
if ($value === ' ')
{
- unset($array_output[$key]);
+ // Get the next element in the array for comparisons
+ $next = $array_output[$key + 1];
+
+ // Strip spaces preceded/followed by a non-ASCII character
+ // or not preceded/followed by an alphanumeric
+ // or not preceded/followed \ $ and _
+ if ((preg_match('/^[\x20-\x7f]*$/D', $next) OR preg_match('/^[\x20-\x7f]*$/D', $prev))
+ && ( ! ctype_alnum($next) OR ! ctype_alnum($prev))
+ && ( ! in_array($next, array('\\', '_', '$')) && ! in_array($prev, array('\\', '_', '$'))))
+ {
+ unset($array_output[$key]);
+ }
+ }
+ else
+ {
+ // Save this value as previous for the next iteration
+ // if it is not a blank space
+ $prev = $value;
}
}
@@ -853,8 +884,27 @@ class CI_Output {
}
}
- // Remove breaklines and tabs
- $output = preg_replace('/[\r\n\t]/', '', implode($array_output));
+ // Put the string back together after spaces have been stripped
+ $output = implode($array_output);
+
+ // Remove new line characters unless previous or next character is
+ // printable or Non-ASCII
+ preg_match_all('/[\n]/', $output, $lf, PREG_OFFSET_CAPTURE);
+ $removed_lf = 0;
+ foreach ($lf as $feed_position)
+ {
+ foreach ($feed_position as $position)
+ {
+ $next_char = substr($output, $position[1] - $removed_lf + 1, 1);
+ $prev_char = substr($output, $position[1] - $removed_lf - 1, 1);
+ if ( ! ctype_print($next_char) && ! ctype_print($prev_char)
+ && ! preg_match('/^[\x20-\x7f]*$/D', $next_char)
+ && ! preg_match('/^[\x20-\x7f]*$/D', $prev_char))
+ {
+ $output = substr_replace($output, '', $position[1] - $removed_lf++, 1);
+ }
+ }
+ }
// Put the opening and closing tags back if applicable
return isset($open_tag)