diff --git a/min/lib/Minify.php b/min/lib/Minify.php index 5baa181..75b44c2 100644 --- a/min/lib/Minify.php +++ b/min/lib/Minify.php @@ -486,32 +486,63 @@ class Minify { $defaultMinifier = isset(self::$_options['minifiers'][$type]) ? self::$_options['minifiers'][$type] : false; - - // minify each source with its own options and minifier, then combine. - // Here we used to combine all first but this was probably - // bad for PCRE performance, esp. in CSS. - foreach (self::$_controller->sources as $source) { - // allow the source to override our minifier and options - $minifier = (null !== $source->minifier) - ? $source->minifier - : $defaultMinifier; - $options = (null !== $source->minifyOptions) - ? array_merge($defaultOptions, $source->minifyOptions) - : $defaultOptions; - if ($minifier) { - self::$_controller->loadMinifier($minifier); - // get source content and minify it - try { - $pieces[] = call_user_func($minifier, $source->getContent(), $options); - } catch (Exception $e) { - throw new Exception("Exception in " . $source->getId() . - ": " . $e->getMessage()); - } - } else { - $pieces[] = $source->getContent(); + + // process groups of sources with identical minifiers/options + $content = array(); + $i = 0; + $l = count(self::$_controller->sources); + $groupToProcessTogether = array(); + $lastMinifier = null; + $lastOptions = null; + do { + // get next source + $source = null; + if ($i < $l) { + $source = self::$_controller->sources[$i]; + /* @var Minify_Source $source */ + $sourceContent = $source->getContent(); + + // allow the source to override our minifier and options + $minifier = (null !== $source->minifier) + ? $source->minifier + : $defaultMinifier; + $options = (null !== $source->minifyOptions) + ? array_merge($defaultOptions, $source->minifyOptions) + : $defaultOptions; } - } - $content = implode($implodeSeparator, $pieces); + // do we need to process our group right now? + if ($i > 0 // no, the first group doesn't exist yet + && ( + ! $source // yes, we ran out of sources + || $type === self::TYPE_CSS // yes, to process CSS individually (avoiding PCRE bugs/limits) + || $minifier !== $lastMinifier // yes, minifier changed + || $options !== $lastOptions) // yes, options changed + ) + { + // minify previous sources with last settings + $imploded = implode($implodeSeparator, $groupToProcessTogether); + $groupToProcessTogether = array(); + if ($lastMinifier) { + self::$_controller->loadMinifier($lastMinifier); + try { + $content[] = call_user_func($lastMinifier, $imploded, $lastOptions); + } catch (Exception $e) { + throw new Exception("Exception in minifier: " . $e->getMessage()); + } + } else { + $content[] = $imploded; + } + } + // add content to the group + if ($source) { + $groupToProcessTogether[] = $sourceContent; + $lastMinifier = $minifier; + $lastOptions = $options; + } + $i++; + } while ($source); + + $content = implode($implodeSeparator, $content); if ($type === self::TYPE_CSS && false !== strpos($content, '@import')) { $content = self::_handleCssImports($content); diff --git a/min_unit_tests/_test_files/minify/minified.js b/min_unit_tests/_test_files/minify/minified.js index 3883520..5a490ed 100644 --- a/min_unit_tests/_test_files/minify/minified.js +++ b/min_unit_tests/_test_files/minify/minified.js @@ -1,6 +1,5 @@ (function(){var -reMailto=/^mailto:my_name_is_(\S+)_and_the_domain_is_(\S+)$/,reRemoveTitleIf=/^my name is/,oo=window.onload,fixHrefs=function(){var i=0,l,m;while(l=document.links[i++]){if(m=l.href.match(reMailto)){l.href='mailto:'+m[1]+'@'+m[2];if(reRemoveTitleIf.test(l.title)){l.title='';}}}};window.onload=function(){oo&&oo();fixHrefs();};})(); -;var MrClay=window.MrClay||{};MrClay.QueryString=function(){var parse=function(str){var assignments=str.split('&'),obj={},propValue;for(var i=0,l=assignments.length;i2||-1!=propValue[0].indexOf('+')||propValue[0]==''){continue;} +reMailto=/^mailto:my_name_is_(\S+)_and_the_domain_is_(\S+)$/,reRemoveTitleIf=/^my name is/,oo=window.onload,fixHrefs=function(){var i=0,l,m;while(l=document.links[i++]){if(m=l.href.match(reMailto)){l.href='mailto:'+m[1]+'@'+m[2];if(reRemoveTitleIf.test(l.title)){l.title='';}}}};window.onload=function(){oo&&oo();fixHrefs();};})();;var MrClay=window.MrClay||{};MrClay.QueryString=function(){var parse=function(str){var assignments=str.split('&'),obj={},propValue;for(var i=0,l=assignments.length;i2||-1!=propValue[0].indexOf('+')||propValue[0]==''){continue;} if(propValue.length==1){propValue[1]=propValue[0];} obj[unescape(propValue[0])]=unescape(propValue[1].replace(/\+/g,' '));} return obj;};function construct_(spec){spec=spec||window;if(typeof spec=='object'){this.window=spec;spec=spec.location.search.substr(1);}else{this.window=window;} diff --git a/min_unit_tests/test_Minify.php b/min_unit_tests/test_Minify.php index f45be60..d09fbc1 100644 --- a/min_unit_tests/test_Minify.php +++ b/min_unit_tests/test_Minify.php @@ -98,7 +98,7 @@ function test_Minify() // test for Issue 73 Minify::setCache(null); - $expected = "\n;function h(){}"; + $expected = ";function h(){}"; $output = Minify::serve('Files', array( 'files' => array( $minifyTestPath . '/issue73_1.js'