From 0fc245e8c6cb287d2fefb3b33c97476625f1e7b6 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Thu, 26 Feb 2009 17:06:31 +0000 Subject: [PATCH] Minify.php : added serve() 'bubbleCssImports' option --- min/lib/Minify.php | 54 ++++++++++++++++++++++++++++-- min/lib/Minify/Controller/Base.php | 1 + 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/min/lib/Minify.php b/min/lib/Minify.php index b5f606d..9af0517 100644 --- a/min/lib/Minify.php +++ b/min/lib/Minify.php @@ -48,6 +48,16 @@ class Minify { */ public static $uploaderHoursBehind = 0; + /** + * If this string is not empty AND the serve() option 'bubbleCssImports' is + * NOT set, then serve() will check CSS files for @import declarations that + * appear too late in the combined stylesheet. If found, serve() will prepend + * the output with this warning. + * + * @var string $importWarning + */ + public static $importWarning = "/* See http://code.google.com/p/minify/wiki/CommonProblems#@imports_can_appear_in_invalid_locations_in_combined_CSS_files */"; + /** * Specify a cache object (with identical interface as Minify_Cache_File) or * a path to use with Minify_Cache_File. @@ -103,6 +113,10 @@ class Minify { * 'rewriteCssUris' : If true, serve() will automatically set the 'currentDir' * minifier option to enable URI rewriting in CSS files (default true) * + * 'bubbleCssImports' : If true, all @import declarations in combined CSS + * files will be move to the top. Note this may alter effective CSS values + * due to a change in order. (default false) + * * 'debug' : set to true to minify all sources with the 'Lines' controller, which * eases the debugging of combined files. This also prevents 304 responses. * @see Minify_Lines::minify() @@ -321,18 +335,22 @@ class Minify { * * @param array $sources array of filepaths and/or Minify_Source objects * + * @param array $options (optional) array of options for serve. By default + * these are already set: quiet = true, encodeMethod = '', lastModifiedTime = 0. + * * @return string */ - public static function combine($sources) + public static function combine($sources, $options = array()) { $cache = self::$_cache; self::$_cache = null; - $out = self::serve('Files', array( + $options = array_merge(array( 'files' => (array)$sources ,'quiet' => true ,'encodeMethod' => '' ,'lastModifiedTime' => 0 - )); + ), $options); + $out = self::serve('Files', $options); self::$_cache = $cache; return $out['content']; } @@ -453,6 +471,10 @@ class Minify { $content = implode($implodeSeparator, $pieces); } + if ($type === self::TYPE_CSS && false !== strpos($content, '@import')) { + $content = self::_handleCssImports($content); + } + // do any post-processing (esp. for editing build URIs) if (self::$_options['postprocessorRequire']) { require_once self::$_options['postprocessorRequire']; @@ -476,6 +498,32 @@ class Minify { ,self::$_options['minifiers'] ,self::$_options['minifierOptions'] ,self::$_options['postprocessor'] + ,self::$_options['bubbleCssImports'] ))); } + + /** + * Bubble CSS @imports to the top or prepend a warning if an + * @import is detected not at the top. + */ + protected static function _handleCssImports($css) { + if (self::$_options['bubbleCssImports']) { + // bubble CSS imports + preg_match_all('/@import.*?;/', $css, $imports); + $css = implode('', $imports[0]) . preg_replace('/@import.*?;/', '', $css); + } else if ('' !== self::$importWarning) { + // remove comments so we don't mistake { in a comment as a block + $noCommentCss = preg_replace('@/\\*[\\s\\S]*?\\*/@', '', $css); + $lastImportPos = strrpos($noCommentCss, '@import'); + $firstBlockPos = strpos($noCommentCss, '{'); + if (false !== $lastImportPos + && false !== $firstBlockPos + && $firstBlockPos < $lastImportPos + ) { + // { appears before @import : prepend warning + $css = self::$importWarning . $css; + } + } + return $css; + } } diff --git a/min/lib/Minify/Controller/Base.php b/min/lib/Minify/Controller/Base.php index a3ad47a..6520a9b 100644 --- a/min/lib/Minify/Controller/Base.php +++ b/min/lib/Minify/Controller/Base.php @@ -48,6 +48,7 @@ abstract class Minify_Controller_Base { ,'contentTypeCharset' => 'UTF-8' ,'maxAge' => 1800 // 30 minutes ,'rewriteCssUris' => true + ,'bubbleCssImports' => false ,'quiet' => false // serve() will send headers and output ,'debug' => false