diff --git a/.gitignore b/.gitignore index 8467073..e8f2d67 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ # / /test /docs +.idea/ \ No newline at end of file diff --git a/min/builder/_index.js b/min/builder/_index.js index ca2d497..8d0a3e2 100644 --- a/min/builder/_index.js +++ b/min/builder/_index.js @@ -2,37 +2,37 @@ * Minify URI Builder */ var MUB = { - _uid : 0 - ,_minRoot : '/min/?' - ,checkRewrite : function () { + _uid : 0, + _minRoot : '/min/?', + checkRewrite : function () { var testUri = location.pathname.replace(/\/[^\/]*$/, '/rewriteTest.js').substr(1); function fail() { $('#minRewriteFailed')[0].className = 'topNote'; - }; + } $.ajax({ - url : '../f=' + testUri + '&' + (new Date()).getTime() - ,success : function (data) { + url : '../f=' + testUri + '&' + (new Date()).getTime(), + success : function (data) { if (data === '1') { MUB._minRoot = '/min/'; $('span.minRoot').html('/min/'); } else fail(); - } - ,error : fail + }, + error : fail }); - } + }, /** * Get markup for new source LI element */ - ,newLi : function () { - return '
  • http://' + location.host + '/' - + ' ' - + '
  • '; - } + newLi : function () { + return '
  • http://' + location.host + '/' + + ' ' + + '
  • '; + }, /** * Add new empty source LI and attach handlers to buttons */ - ,addLi : function () { + addLi : function () { $('#sources').append(MUB.newLi()); var li = $('#li' + MUB._uid)[0]; $('button[title=Remove]', li).click(function () { @@ -61,22 +61,22 @@ var MUB = { }); }); ++MUB._uid; - } + }, /** * In the context of a source LI element, this will analyze the URI in * the INPUT and check the URL on the site. */ - ,liUpdateTestLink : function () { // call in context of li element + liUpdateTestLink : function () { // call in context of li element if (! $('input', this)[0].value) return; var li = this; $('span', this).html(''); - var url = 'http://' + location.host + '/' - + $('input', this)[0].value.replace(/^\//, ''); + var url = 'http://' + location.host + '/' + + $('input', this)[0].value.replace(/^\//, ''); $.ajax({ - url : url - ,complete : function (xhr, stat) { - if ('success' == stat) + url : url, + complete : function (xhr, stat) { + if ('success' === stat) $('span', li).html('✓'); else { $('span', li).html('') @@ -84,16 +84,16 @@ var MUB = { MUB.liUpdateTestLink.call(li); }); } - } - ,dataType : 'text' + }, + dataType : 'text' }); - } + }, /** * Check all source URLs */ - ,updateAllTestLinks : function () { + updateAllTestLinks : function () { $('#sources li').each(MUB.liUpdateTestLink); - } + }, /** * In a given array of strings, find the character they all have at * a particular index @@ -101,25 +101,25 @@ var MUB = { * @param Number pos index to check * @return mixed a common char or '' if any do not match */ - ,getCommonCharAtPos : function (arr, pos) { - var i - ,l = arr.length - ,c = arr[0].charAt(pos); + getCommonCharAtPos : function (arr, pos) { + var i, + l = arr.length, + c = arr[0].charAt(pos); if (c === '' || l === 1) return c; for (i = 1; i < l; ++i) if (arr[i].charAt(pos) !== c) return ''; return c; - } + }, /** * Get the shortest URI to minify the set of source files * @param Array sources URIs */ - ,getBestUri : function (sources) { - var pos = 0 - ,base = '' - ,c; + getBestUri : function (sources) { + var pos = 0, + base = '', + c; while (true) { c = MUB.getCommonCharAtPos(sources, pos); if (c === '') @@ -132,29 +132,28 @@ var MUB = { var uri = MUB._minRoot + 'f=' + sources.join(','); if (base.charAt(base.length - 1) === '/') { // we have a base dir! - var basedSources = sources - ,i - ,l = sources.length; + var basedSources = sources, + i, + l = sources.length; for (i = 0; i < l; ++i) { basedSources[i] = sources[i].substr(base.length); } base = base.substr(0, base.length - 1); var bUri = MUB._minRoot + 'b=' + base + '&f=' + basedSources.join(','); //window.console && console.log([uri, bUri]); - uri = uri.length < bUri.length - ? uri - : bUri; + uri = uri.length < bUri.length ? uri : bUri; } return uri; - } + }, /** * Create the Minify URI for the sources */ - ,update : function () { + update : function () { MUB.updateAllTestLinks(); - var sources = [] - ,ext = false - ,fail = false; + var sources = [], + ext = false, + fail = false, + markup; $('#sources input').each(function () { var m, val; if (! fail && this.value && (m = this.value.match(/\.(css|js)$/))) { @@ -166,7 +165,7 @@ var MUB = { return alert('extensions must match!'); } this.value = this.value.replace(/^\//, ''); - if (-1 != $.inArray(this.value, sources)) { + if (-1 !== $.inArray(this.value, sources)) { fail = true; return alert('duplicate file!'); } @@ -176,30 +175,31 @@ var MUB = { if (fail || ! sources.length) return; $('#groupConfig').val(" 'keyName' => array('//" + sources.join("', '//") + "'),"); - var uri = MUB.getBestUri(sources) - ,uriH = uri.replace(//, '>').replace(/&/, '&'); + var uri = MUB.getBestUri(sources), + uriH = uri.replace(//, '>').replace(/&/, '&'); $('#uriA').html(uriH)[0].href = uri; - $('#uriHtml').val( - ext === 'js' - ? '' - : '' - ); + if (ext === 'js') { + markup = ''; + } else { + markup = ''; + } + $('#uriHtml').val(markup); $('#results').show(); - } + }, /** * Handler for the "Add file +" button */ - ,addButtonClick : function () { + addButtonClick : function () { $('#results').hide(); MUB.addLi(); MUB.updateAllTestLinks(); $('#update').show().click(MUB.update); $('#sources li:last input')[0].focus(); - } + }, /** * Runs on DOMready */ - ,init : function () { + init : function () { $('#jsDidntLoad').remove(); $('#app').show(); $('#sources').html(''); @@ -214,13 +214,13 @@ var MUB = { if (location.hash) { // make links out of URIs from bookmarklet $('#getBm').hide(); - $('#bmUris').html('

    Found by bookmarklet: /' - + location.hash.substr(1).split(',').join(' | /') - + '

    ' + $('#bmUris').html('

    Found by bookmarklet: /' + + location.hash.substr(1).split(',').join(' | /') + + '

    ' ); $('#bmUris a').click(function () { MUB.addButtonClick(); - $('#sources li:last input').val(this.innerHTML) + $('#sources li:last input').val(this.innerHTML); MUB.liUpdateTestLink.call($('#sources li:last')[0]); $('#results').hide(); return false; @@ -228,24 +228,26 @@ var MUB = { } else { // setup bookmarklet 1 $.ajax({ - url : '../?f=' + location.pathname.replace(/\/[^\/]*$/, '/bm.js').substr(1) - ,success : function (code) { + url : '../?f=' + location.pathname.replace(/\/[^\/]*$/, '/bm.js').substr(1), + success : function (code) { $('#bm')[0].href = code .replace('%BUILDER_URL%', location.href) .replace(/\n/g, ' '); - } - ,dataType : 'text' + }, + dataType : 'text' }); - $.browser.msie && $('#getBm p:last').append(' Sorry, not supported in MSIE!'); + if ($.browser.msie) { + $('#getBm p:last').append(' Sorry, not supported in MSIE!'); + } MUB.addButtonClick(); } // setup bookmarklet 2 $.ajax({ - url : '../?f=' + location.pathname.replace(/\/[^\/]*$/, '/bm2.js').substr(1) - ,success : function (code) { + url : '../?f=' + location.pathname.replace(/\/[^\/]*$/, '/bm2.js').substr(1), + success : function (code) { $('#bm2')[0].href = code.replace(/\n/g, ' '); - } - ,dataType : 'text' + }, + dataType : 'text' }); MUB.checkRewrite(); } diff --git a/min/builder/bm2.js b/min/builder/bm2.js index db92172..6b558ce 100644 --- a/min/builder/bm2.js +++ b/min/builder/bm2.js @@ -1,15 +1,15 @@ javascript:(function(){ var d = document ,c = d.cookie - ,m = c.match(/\bminDebug=([^; ]+)/) + ,m = c.match(/\bminifyDebug=([^; ]+)/) ,v = m ? decodeURIComponent(m[1]) : '' ,p = prompt('Debug Minify URIs on ' + location.hostname + ' which contain:' - + '\n(empty for none, space = OR)', v) + + '\n(empty for none, space = OR, * = any string, ? = any char)', v) ; if (p === null) return; p = p.replace(/^\s+|\s+$/, ''); v = (p === '') - ? 'minDebug=; expires=Fri, 27 Jul 2001 02:47:11 UTC; path=/' - : 'minDebug=' + encodeURIComponent(p) + '; path=/'; + ? 'minifyDebug=; expires=Fri, 27 Jul 2001 02:47:11 UTC; path=/' + : 'minifyDebug=' + encodeURIComponent(p) + '; path=/'; d.cookie = v; })(); \ No newline at end of file diff --git a/min/builder/index.php b/min/builder/index.php index deb0fea..a3c4e2f 100644 --- a/min/builder/index.php +++ b/min/builder/index.php @@ -228,9 +228,6 @@ $(function () { $content = ob_get_clean(); // setup Minify -if (0 === stripos(PHP_OS, 'win')) { - Minify::setDocRoot(); // we may be on IIS -} Minify::setCache( isset($min_cachePath) ? $min_cachePath : '' ,$min_cacheFileLocking diff --git a/min/index.php b/min/index.php index 165c8d5..501c8a0 100644 --- a/min/index.php +++ b/min/index.php @@ -25,8 +25,7 @@ Minify::setCache( if ($min_documentRoot) { $_SERVER['DOCUMENT_ROOT'] = $min_documentRoot; -} elseif (0 === stripos(PHP_OS, 'win')) { - Minify::setDocRoot(); // IIS may need help + Minify::$isDocRootSet = true; } $min_serveOptions['minifierOptions']['text/css']['symlinks'] = $min_symlinks; @@ -36,18 +35,8 @@ foreach ($min_symlinks as $uri => $target) { } if ($min_allowDebugFlag) { - if (! empty($_COOKIE['minDebug'])) { - foreach (preg_split('/\\s+/', $_COOKIE['minDebug']) as $debugUri) { - if (false !== strpos($_SERVER['REQUEST_URI'], $debugUri)) { - $min_serveOptions['debug'] = true; - break; - } - } - } - // allow GET to override - if (isset($_GET['debug'])) { - $min_serveOptions['debug'] = true; - } + require_once 'Minify/DebugDetector.php'; + $min_serveOptions['debug'] = Minify_DebugDetector::shouldDebugRequest($_COOKIE, $_GET, $_SERVER['REQUEST_URI']); } if ($min_errorLogger) { diff --git a/min/lib/Minify.php b/min/lib/Minify.php index d70e32d..5baa181 100644 --- a/min/lib/Minify.php +++ b/min/lib/Minify.php @@ -59,7 +59,14 @@ class Minify { * @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 */\n"; - + + /** + * Has the DOCUMENT_ROOT been set in user code? + * + * @var bool + */ + public static $isDocRootSet = false; + /** * Specify a cache object (with identical interface as Minify_Cache_File) or * a path to use with Minify_Cache_File. @@ -160,6 +167,10 @@ class Minify { */ public static function serve($controller, $options = array()) { + if (! self::$isDocRootSet && 0 === stripos(PHP_OS, 'win')) { + self::setDocRoot(); + } + if (is_string($controller)) { // make $controller into object $class = 'Minify_Controller_' . $controller; @@ -252,7 +263,6 @@ class Minify { if (self::$_options['contentType'] === self::TYPE_CSS && self::$_options['rewriteCssUris']) { - reset($controller->sources); foreach($controller->sources as $key => $source) { if ($source->filepath && !isset($source->minifyOptions['currentDir']) @@ -401,6 +411,7 @@ class Minify { require_once 'Minify/Logger.php'; Minify_Logger::log("setDocRoot() set DOCUMENT_ROOT to \"{$_SERVER['DOCUMENT_ROOT']}\""); } + self::$isDocRootSet = true; } /** diff --git a/min/lib/Minify/Controller/MinApp.php b/min/lib/Minify/Controller/MinApp.php index 986ef2c..2fb10f7 100644 --- a/min/lib/Minify/Controller/MinApp.php +++ b/min/lib/Minify/Controller/MinApp.php @@ -35,7 +35,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base { unset($options['minApp']); $sources = array(); $this->selectionId = ''; - $missingUri = ''; + $firstMissingResource = null; if (isset($_GET['g'])) { // add group(s) @@ -45,7 +45,8 @@ class Minify_Controller_MinApp extends Minify_Controller_Base { $this->log("Duplicate group key found."); return $options; } - foreach (explode(',', $_GET['g']) as $key) { + $keys = explode(',', $_GET['g']); + foreach ($keys as $key) { if (! isset($cOptions['groups'][$key])) { $this->log("A group configuration for \"{$key}\" was not found"); return $options; @@ -70,7 +71,14 @@ class Minify_Controller_MinApp extends Minify_Controller_Base { $sources[] = $this->_getFileSource($realpath, $cOptions); } else { $this->log("The path \"{$file}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); - return $options; + if (null === $firstMissingResource) { + $firstMissingResource = basename($file); + continue; + } else { + $secondMissingResource = basename($file); + $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource'"); + return $options; + } } } if ($sources) { @@ -135,11 +143,12 @@ class Minify_Controller_MinApp extends Minify_Controller_Base { $realpath = realpath($path); if (false === $realpath || ! is_file($realpath)) { $this->log("The path \"{$path}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); - if (! $missingUri) { - $missingUri = $uri; + if (null === $firstMissingResource) { + $firstMissingResource = $uri; continue; } else { - $this->log("More than one file was missing: '$missingUri', '$uri'"); + $secondMissingResource = $uri; + $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource`'"); return $options; } } @@ -159,11 +168,13 @@ class Minify_Controller_MinApp extends Minify_Controller_Base { $this->selectionId .= implode(',', $basenames) . $ext; } if ($sources) { - if ($missingUri) { + if (null !== $firstMissingResource) { array_unshift($sources, new Minify_Source(array( 'id' => 'missingFile' + // should not cause cache invalidation ,'lastModified' => 0 - ,'content' => "/* Minify: missing file '" . ltrim($missingUri, '/') . "' */\n" + // due to caching, filename is unreliable. + ,'content' => "/* Minify: at least one missing file. See " . Minify::URL_DEBUG . " */\n" ,'minifier' => '' ))); } diff --git a/min/lib/Minify/DebugDetector.php b/min/lib/Minify/DebugDetector.php new file mode 100644 index 0000000..1def974 --- /dev/null +++ b/min/lib/Minify/DebugDetector.php @@ -0,0 +1,26 @@ + + */ +class Minify_DebugDetector { + public static function shouldDebugRequest($cookie, $get, $requestUri) + { + if (isset($get['debug'])) { + return true; + } + if (! empty($cookie['minifyDebug'])) { + foreach (preg_split('/\\s+/', $cookie['minifyDebug']) as $debugUri) { + $pattern = '@' . preg_quote($debugUri, '@') . '@i'; + $pattern = str_replace(array('\\*', '\\?'), array('.*', '.'), $pattern); + if (preg_match($pattern, $requestUri)) { + return true; + } + } + } + return false; + } +}