1
0
mirror of https://github.com/mrclay/minify.git synced 2025-08-17 19:37:22 +02:00

Merge branch 'master' of github.com:mrclay/minify

This commit is contained in:
Steve Clay
2011-09-18 21:36:11 -04:00
8 changed files with 140 additions and 103 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
# / # /
/test /test
/docs /docs
.idea/

View File

@@ -2,37 +2,37 @@
* Minify URI Builder * Minify URI Builder
*/ */
var MUB = { var MUB = {
_uid : 0 _uid : 0,
,_minRoot : '/min/?' _minRoot : '/min/?',
,checkRewrite : function () { checkRewrite : function () {
var testUri = location.pathname.replace(/\/[^\/]*$/, '/rewriteTest.js').substr(1); var testUri = location.pathname.replace(/\/[^\/]*$/, '/rewriteTest.js').substr(1);
function fail() { function fail() {
$('#minRewriteFailed')[0].className = 'topNote'; $('#minRewriteFailed')[0].className = 'topNote';
}; }
$.ajax({ $.ajax({
url : '../f=' + testUri + '&' + (new Date()).getTime() url : '../f=' + testUri + '&' + (new Date()).getTime(),
,success : function (data) { success : function (data) {
if (data === '1') { if (data === '1') {
MUB._minRoot = '/min/'; MUB._minRoot = '/min/';
$('span.minRoot').html('/min/'); $('span.minRoot').html('/min/');
} else } else
fail(); fail();
} },
,error : fail error : fail
}); });
} },
/** /**
* Get markup for new source LI element * Get markup for new source LI element
*/ */
,newLi : function () { newLi : function () {
return '<li id="li' + MUB._uid + '">http://' + location.host + '/<input type=text size=20>' return '<li id="li' + MUB._uid + '">http://' + location.host + '/<input type=text size=20>' +
+ ' <button title="Remove">x</button> <button title="Include Earlier">&uarr;</button>' ' <button title="Remove">x</button> <button title="Include Earlier">&uarr;</button>' +
+ ' <button title="Include Later">&darr;</button> <span></span></li>'; ' <button title="Include Later">&darr;</button> <span></span></li>';
} },
/** /**
* Add new empty source LI and attach handlers to buttons * Add new empty source LI and attach handlers to buttons
*/ */
,addLi : function () { addLi : function () {
$('#sources').append(MUB.newLi()); $('#sources').append(MUB.newLi());
var li = $('#li' + MUB._uid)[0]; var li = $('#li' + MUB._uid)[0];
$('button[title=Remove]', li).click(function () { $('button[title=Remove]', li).click(function () {
@@ -61,22 +61,22 @@ var MUB = {
}); });
}); });
++MUB._uid; ++MUB._uid;
} },
/** /**
* In the context of a source LI element, this will analyze the URI in * In the context of a source LI element, this will analyze the URI in
* the INPUT and check the URL on the site. * 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) if (! $('input', this)[0].value)
return; return;
var li = this; var li = this;
$('span', this).html(''); $('span', this).html('');
var url = 'http://' + location.host + '/' var url = 'http://' + location.host + '/' +
+ $('input', this)[0].value.replace(/^\//, ''); $('input', this)[0].value.replace(/^\//, '');
$.ajax({ $.ajax({
url : url url : url,
,complete : function (xhr, stat) { complete : function (xhr, stat) {
if ('success' == stat) if ('success' === stat)
$('span', li).html('&#x2713;'); $('span', li).html('&#x2713;');
else { else {
$('span', li).html('<button><b>404! </b> recheck</button>') $('span', li).html('<button><b>404! </b> recheck</button>')
@@ -84,16 +84,16 @@ var MUB = {
MUB.liUpdateTestLink.call(li); MUB.liUpdateTestLink.call(li);
}); });
} }
} },
,dataType : 'text' dataType : 'text'
}); });
} },
/** /**
* Check all source URLs * Check all source URLs
*/ */
,updateAllTestLinks : function () { updateAllTestLinks : function () {
$('#sources li').each(MUB.liUpdateTestLink); $('#sources li').each(MUB.liUpdateTestLink);
} },
/** /**
* In a given array of strings, find the character they all have at * In a given array of strings, find the character they all have at
* a particular index * a particular index
@@ -101,25 +101,25 @@ var MUB = {
* @param Number pos index to check * @param Number pos index to check
* @return mixed a common char or '' if any do not match * @return mixed a common char or '' if any do not match
*/ */
,getCommonCharAtPos : function (arr, pos) { getCommonCharAtPos : function (arr, pos) {
var i var i,
,l = arr.length l = arr.length,
,c = arr[0].charAt(pos); c = arr[0].charAt(pos);
if (c === '' || l === 1) if (c === '' || l === 1)
return c; return c;
for (i = 1; i < l; ++i) for (i = 1; i < l; ++i)
if (arr[i].charAt(pos) !== c) if (arr[i].charAt(pos) !== c)
return ''; return '';
return c; return c;
} },
/** /**
* Get the shortest URI to minify the set of source files * Get the shortest URI to minify the set of source files
* @param Array sources URIs * @param Array sources URIs
*/ */
,getBestUri : function (sources) { getBestUri : function (sources) {
var pos = 0 var pos = 0,
,base = '' base = '',
,c; c;
while (true) { while (true) {
c = MUB.getCommonCharAtPos(sources, pos); c = MUB.getCommonCharAtPos(sources, pos);
if (c === '') if (c === '')
@@ -132,29 +132,28 @@ var MUB = {
var uri = MUB._minRoot + 'f=' + sources.join(','); var uri = MUB._minRoot + 'f=' + sources.join(',');
if (base.charAt(base.length - 1) === '/') { if (base.charAt(base.length - 1) === '/') {
// we have a base dir! // we have a base dir!
var basedSources = sources var basedSources = sources,
,i i,
,l = sources.length; l = sources.length;
for (i = 0; i < l; ++i) { for (i = 0; i < l; ++i) {
basedSources[i] = sources[i].substr(base.length); basedSources[i] = sources[i].substr(base.length);
} }
base = base.substr(0, base.length - 1); base = base.substr(0, base.length - 1);
var bUri = MUB._minRoot + 'b=' + base + '&f=' + basedSources.join(','); var bUri = MUB._minRoot + 'b=' + base + '&f=' + basedSources.join(',');
//window.console && console.log([uri, bUri]); //window.console && console.log([uri, bUri]);
uri = uri.length < bUri.length uri = uri.length < bUri.length ? uri : bUri;
? uri
: bUri;
} }
return uri; return uri;
} },
/** /**
* Create the Minify URI for the sources * Create the Minify URI for the sources
*/ */
,update : function () { update : function () {
MUB.updateAllTestLinks(); MUB.updateAllTestLinks();
var sources = [] var sources = [],
,ext = false ext = false,
,fail = false; fail = false,
markup;
$('#sources input').each(function () { $('#sources input').each(function () {
var m, val; var m, val;
if (! fail && this.value && (m = this.value.match(/\.(css|js)$/))) { if (! fail && this.value && (m = this.value.match(/\.(css|js)$/))) {
@@ -166,7 +165,7 @@ var MUB = {
return alert('extensions must match!'); return alert('extensions must match!');
} }
this.value = this.value.replace(/^\//, ''); this.value = this.value.replace(/^\//, '');
if (-1 != $.inArray(this.value, sources)) { if (-1 !== $.inArray(this.value, sources)) {
fail = true; fail = true;
return alert('duplicate file!'); return alert('duplicate file!');
} }
@@ -176,30 +175,31 @@ var MUB = {
if (fail || ! sources.length) if (fail || ! sources.length)
return; return;
$('#groupConfig').val(" 'keyName' => array('//" + sources.join("', '//") + "'),"); $('#groupConfig').val(" 'keyName' => array('//" + sources.join("', '//") + "'),");
var uri = MUB.getBestUri(sources) var uri = MUB.getBestUri(sources),
,uriH = uri.replace(/</, '&lt;').replace(/>/, '&gt;').replace(/&/, '&amp;'); uriH = uri.replace(/</, '&lt;').replace(/>/, '&gt;').replace(/&/, '&amp;');
$('#uriA').html(uriH)[0].href = uri; $('#uriA').html(uriH)[0].href = uri;
$('#uriHtml').val( if (ext === 'js') {
ext === 'js' markup = '<script type="text/javascript" src="' + uriH + '"></script>';
? '<script type="text/javascript" src="' + uriH + '"></script>' } else {
: '<link type="text/css" rel="stylesheet" href="' + uriH + '" />' markup = '<link type="text/css" rel="stylesheet" href="' + uriH + '" />';
); }
$('#uriHtml').val(markup);
$('#results').show(); $('#results').show();
} },
/** /**
* Handler for the "Add file +" button * Handler for the "Add file +" button
*/ */
,addButtonClick : function () { addButtonClick : function () {
$('#results').hide(); $('#results').hide();
MUB.addLi(); MUB.addLi();
MUB.updateAllTestLinks(); MUB.updateAllTestLinks();
$('#update').show().click(MUB.update); $('#update').show().click(MUB.update);
$('#sources li:last input')[0].focus(); $('#sources li:last input')[0].focus();
} },
/** /**
* Runs on DOMready * Runs on DOMready
*/ */
,init : function () { init : function () {
$('#jsDidntLoad').remove(); $('#jsDidntLoad').remove();
$('#app').show(); $('#app').show();
$('#sources').html(''); $('#sources').html('');
@@ -214,13 +214,13 @@ var MUB = {
if (location.hash) { if (location.hash) {
// make links out of URIs from bookmarklet // make links out of URIs from bookmarklet
$('#getBm').hide(); $('#getBm').hide();
$('#bmUris').html('<p><strong>Found by bookmarklet:</strong> /<a href=#>' $('#bmUris').html('<p><strong>Found by bookmarklet:</strong> /<a href=#>' +
+ location.hash.substr(1).split(',').join('</a> | /<a href=#>') location.hash.substr(1).split(',').join('</a> | /<a href=#>') +
+ '</a></p>' '</a></p>'
); );
$('#bmUris a').click(function () { $('#bmUris a').click(function () {
MUB.addButtonClick(); MUB.addButtonClick();
$('#sources li:last input').val(this.innerHTML) $('#sources li:last input').val(this.innerHTML);
MUB.liUpdateTestLink.call($('#sources li:last')[0]); MUB.liUpdateTestLink.call($('#sources li:last')[0]);
$('#results').hide(); $('#results').hide();
return false; return false;
@@ -228,24 +228,26 @@ var MUB = {
} else { } else {
// setup bookmarklet 1 // setup bookmarklet 1
$.ajax({ $.ajax({
url : '../?f=' + location.pathname.replace(/\/[^\/]*$/, '/bm.js').substr(1) url : '../?f=' + location.pathname.replace(/\/[^\/]*$/, '/bm.js').substr(1),
,success : function (code) { success : function (code) {
$('#bm')[0].href = code $('#bm')[0].href = code
.replace('%BUILDER_URL%', location.href) .replace('%BUILDER_URL%', location.href)
.replace(/\n/g, ' '); .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(); MUB.addButtonClick();
} }
// setup bookmarklet 2 // setup bookmarklet 2
$.ajax({ $.ajax({
url : '../?f=' + location.pathname.replace(/\/[^\/]*$/, '/bm2.js').substr(1) url : '../?f=' + location.pathname.replace(/\/[^\/]*$/, '/bm2.js').substr(1),
,success : function (code) { success : function (code) {
$('#bm2')[0].href = code.replace(/\n/g, ' '); $('#bm2')[0].href = code.replace(/\n/g, ' ');
} },
,dataType : 'text' dataType : 'text'
}); });
MUB.checkRewrite(); MUB.checkRewrite();
} }

View File

@@ -1,15 +1,15 @@
javascript:(function(){ javascript:(function(){
var d = document var d = document
,c = d.cookie ,c = d.cookie
,m = c.match(/\bminDebug=([^; ]+)/) ,m = c.match(/\bminifyDebug=([^; ]+)/)
,v = m ? decodeURIComponent(m[1]) : '' ,v = m ? decodeURIComponent(m[1]) : ''
,p = prompt('Debug Minify URIs on ' + location.hostname + ' which contain:' ,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; if (p === null) return;
p = p.replace(/^\s+|\s+$/, ''); p = p.replace(/^\s+|\s+$/, '');
v = (p === '') v = (p === '')
? 'minDebug=; expires=Fri, 27 Jul 2001 02:47:11 UTC; path=/' ? 'minifyDebug=; expires=Fri, 27 Jul 2001 02:47:11 UTC; path=/'
: 'minDebug=' + encodeURIComponent(p) + '; path=/'; : 'minifyDebug=' + encodeURIComponent(p) + '; path=/';
d.cookie = v; d.cookie = v;
})(); })();

View File

@@ -228,9 +228,6 @@ $(function () {
$content = ob_get_clean(); $content = ob_get_clean();
// setup Minify // setup Minify
if (0 === stripos(PHP_OS, 'win')) {
Minify::setDocRoot(); // we may be on IIS
}
Minify::setCache( Minify::setCache(
isset($min_cachePath) ? $min_cachePath : '' isset($min_cachePath) ? $min_cachePath : ''
,$min_cacheFileLocking ,$min_cacheFileLocking

View File

@@ -25,8 +25,7 @@ Minify::setCache(
if ($min_documentRoot) { if ($min_documentRoot) {
$_SERVER['DOCUMENT_ROOT'] = $min_documentRoot; $_SERVER['DOCUMENT_ROOT'] = $min_documentRoot;
} elseif (0 === stripos(PHP_OS, 'win')) { Minify::$isDocRootSet = true;
Minify::setDocRoot(); // IIS may need help
} }
$min_serveOptions['minifierOptions']['text/css']['symlinks'] = $min_symlinks; $min_serveOptions['minifierOptions']['text/css']['symlinks'] = $min_symlinks;
@@ -36,18 +35,8 @@ foreach ($min_symlinks as $uri => $target) {
} }
if ($min_allowDebugFlag) { if ($min_allowDebugFlag) {
if (! empty($_COOKIE['minDebug'])) { require_once 'Minify/DebugDetector.php';
foreach (preg_split('/\\s+/', $_COOKIE['minDebug']) as $debugUri) { $min_serveOptions['debug'] = Minify_DebugDetector::shouldDebugRequest($_COOKIE, $_GET, $_SERVER['REQUEST_URI']);
if (false !== strpos($_SERVER['REQUEST_URI'], $debugUri)) {
$min_serveOptions['debug'] = true;
break;
}
}
}
// allow GET to override
if (isset($_GET['debug'])) {
$min_serveOptions['debug'] = true;
}
} }
if ($min_errorLogger) { if ($min_errorLogger) {

View File

@@ -60,6 +60,13 @@ class Minify {
*/ */
public static $importWarning = "/* See http://code.google.com/p/minify/wiki/CommonProblems#@imports_can_appear_in_invalid_locations_in_combined_CSS_files */\n"; 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 * Specify a cache object (with identical interface as Minify_Cache_File) or
* a path to use with Minify_Cache_File. * a path to use with Minify_Cache_File.
@@ -160,6 +167,10 @@ class Minify {
*/ */
public static function serve($controller, $options = array()) public static function serve($controller, $options = array())
{ {
if (! self::$isDocRootSet && 0 === stripos(PHP_OS, 'win')) {
self::setDocRoot();
}
if (is_string($controller)) { if (is_string($controller)) {
// make $controller into object // make $controller into object
$class = 'Minify_Controller_' . $controller; $class = 'Minify_Controller_' . $controller;
@@ -252,7 +263,6 @@ class Minify {
if (self::$_options['contentType'] === self::TYPE_CSS if (self::$_options['contentType'] === self::TYPE_CSS
&& self::$_options['rewriteCssUris']) { && self::$_options['rewriteCssUris']) {
reset($controller->sources);
foreach($controller->sources as $key => $source) { foreach($controller->sources as $key => $source) {
if ($source->filepath if ($source->filepath
&& !isset($source->minifyOptions['currentDir']) && !isset($source->minifyOptions['currentDir'])
@@ -401,6 +411,7 @@ class Minify {
require_once 'Minify/Logger.php'; require_once 'Minify/Logger.php';
Minify_Logger::log("setDocRoot() set DOCUMENT_ROOT to \"{$_SERVER['DOCUMENT_ROOT']}\""); Minify_Logger::log("setDocRoot() set DOCUMENT_ROOT to \"{$_SERVER['DOCUMENT_ROOT']}\"");
} }
self::$isDocRootSet = true;
} }
/** /**

View File

@@ -35,7 +35,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
unset($options['minApp']); unset($options['minApp']);
$sources = array(); $sources = array();
$this->selectionId = ''; $this->selectionId = '';
$missingUri = ''; $firstMissingResource = null;
if (isset($_GET['g'])) { if (isset($_GET['g'])) {
// add group(s) // add group(s)
@@ -45,7 +45,8 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
$this->log("Duplicate group key found."); $this->log("Duplicate group key found.");
return $options; return $options;
} }
foreach (explode(',', $_GET['g']) as $key) { $keys = explode(',', $_GET['g']);
foreach ($keys as $key) {
if (! isset($cOptions['groups'][$key])) { if (! isset($cOptions['groups'][$key])) {
$this->log("A group configuration for \"{$key}\" was not found"); $this->log("A group configuration for \"{$key}\" was not found");
return $options; return $options;
@@ -70,7 +71,14 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
$sources[] = $this->_getFileSource($realpath, $cOptions); $sources[] = $this->_getFileSource($realpath, $cOptions);
} else { } else {
$this->log("The path \"{$file}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); $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) { if ($sources) {
@@ -135,11 +143,12 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
$realpath = realpath($path); $realpath = realpath($path);
if (false === $realpath || ! is_file($realpath)) { if (false === $realpath || ! is_file($realpath)) {
$this->log("The path \"{$path}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); $this->log("The path \"{$path}\" (realpath \"{$realpath}\") could not be found (or was not a file)");
if (! $missingUri) { if (null === $firstMissingResource) {
$missingUri = $uri; $firstMissingResource = $uri;
continue; continue;
} else { } 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; return $options;
} }
} }
@@ -159,11 +168,13 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
$this->selectionId .= implode(',', $basenames) . $ext; $this->selectionId .= implode(',', $basenames) . $ext;
} }
if ($sources) { if ($sources) {
if ($missingUri) { if (null !== $firstMissingResource) {
array_unshift($sources, new Minify_Source(array( array_unshift($sources, new Minify_Source(array(
'id' => 'missingFile' 'id' => 'missingFile'
// should not cause cache invalidation
,'lastModified' => 0 ,'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' => '' ,'minifier' => ''
))); )));
} }

View File

@@ -0,0 +1,26 @@
<?php
/**
* Detect whether request should be debugged
*
* @package Minify
* @author Stephen Clay <steve@mrclay.org>
*/
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;
}
}