mirror of
https://github.com/mrclay/minify.git
synced 2025-08-30 09:09:54 +02:00
cleaning trunk
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
RewriteRule ^([a-z]=.*) index.php?$1 [L,NE]
|
||||
</IfModule>
|
152
min/README.txt
152
min/README.txt
@@ -1,152 +0,0 @@
|
||||
The files in this directory represent the default Minify setup designed to ease
|
||||
integration with your site. This app will combine and minify your Javascript or
|
||||
CSS files and serve them with HTTP compression and cache headers.
|
||||
|
||||
|
||||
RECOMMENDED
|
||||
|
||||
It's recommended to edit config.php to set $min_cachePath to a writeable
|
||||
(by PHP) directory on your system. This will improve performance.
|
||||
|
||||
|
||||
GETTING STARTED
|
||||
|
||||
The quickest way to get started is to use the Minify URI Builder application
|
||||
on your website: http://example.com/min/builder/
|
||||
|
||||
|
||||
MINIFYING A SINGLE FILE
|
||||
|
||||
Let's say you want to serve this file:
|
||||
http://example.com/wp-content/themes/default/default.css
|
||||
|
||||
Here's the "Minify URL" for this file:
|
||||
http://example.com/min/?f=wp-content/themes/default/default.css
|
||||
|
||||
In other words, the "f" argument is set to the file path from root without the
|
||||
initial "/". As CSS files may contain relative URIs, Minify will automatically
|
||||
"fix" these by rewriting them as root relative.
|
||||
|
||||
|
||||
COMBINING MULTIPLE FILES IN ONE DOWNLOAD
|
||||
|
||||
Separate the paths given to "f" with commas.
|
||||
|
||||
Let's say you have CSS files at these URLs:
|
||||
http://example.com/scripts/jquery-1.2.6.js
|
||||
http://example.com/scripts/site.js
|
||||
|
||||
You can combine these files through Minify by requesting this URL:
|
||||
http://example.com/min/?f=scripts/jquery-1.2.6.js,scripts/site.js
|
||||
|
||||
|
||||
SIMPLIFYING URLS WITH A BASE PATH
|
||||
|
||||
If you're combining files that share the same ancestor directory, you can use
|
||||
the "b" argument to set the base directory for the "f" argument. Do not include
|
||||
the leading or trailing "/" characters.
|
||||
|
||||
E.g., the following URLs will serve the exact same content:
|
||||
http://example.com/min/?f=scripts/jquery-1.2.6.js,scripts/site.js,scripts/home.js
|
||||
http://example.com/min/?b=scripts&f=jquery-1.2.6.js,site.js,home.js
|
||||
|
||||
|
||||
MINIFY URLS IN HTML
|
||||
|
||||
In (X)HTML files, don't forget to replace any "&" characters with "&".
|
||||
|
||||
|
||||
SPECIFYING ALLOWED DIRECTORIES
|
||||
|
||||
By default, Minify will serve any *.css/*.js files within the DOCUMENT_ROOT. If
|
||||
you'd prefer to limit Minify's access to certain directories, set the
|
||||
$min_serveOptions['minApp']['allowDirs'] array in config.php. E.g. to limit
|
||||
to the /js and /themes/default directories, use:
|
||||
|
||||
$min_serveOptions['minApp']['allowDirs'] = array('//js', '//themes/default');
|
||||
|
||||
|
||||
GROUPS: SHORTER URLS
|
||||
|
||||
For the best performance, edit groupsConfig.php to pre-specify groups of files
|
||||
to be combined under preset keys (note: keys should not contain commas). E.g.,
|
||||
here's an example configuration in groupsConfig.php:
|
||||
|
||||
return array(
|
||||
'js' => array('//js/Class.js', '//js/email.js')
|
||||
);
|
||||
|
||||
This pre-selects the following files to be combined under the key "js":
|
||||
http://example.com/js/Class.js
|
||||
http://example.com/js/email.js
|
||||
|
||||
You can now serve these files with this simple URL:
|
||||
http://example.com/min/?g=js
|
||||
|
||||
|
||||
GROUPS: SPECIFYING FILES OUTSIDE THE DOC_ROOT
|
||||
|
||||
In the groupsConfig.php array, the "//" in the file paths is a shortcut for
|
||||
the DOCUMENT_ROOT, but you can also specify paths from the root of the filesystem
|
||||
or relative to the DOC_ROOT:
|
||||
|
||||
return array(
|
||||
'js' => array(
|
||||
'//js/file.js' // file within DOC_ROOT
|
||||
,'//../file.js' // file in parent directory of DOC_ROOT
|
||||
,'C:/Users/Steve/file.js' // file anywhere on filesystem
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
COMBINING GROUPS AND FILES
|
||||
|
||||
In a single URL you can combine multiple groups and files:
|
||||
http://example.com/min/?g=js1,js2&f=page1.js
|
||||
|
||||
Caveats:
|
||||
* Groups always come before files in the output
|
||||
E.g. /g=js1&f=page.js == /f=page.js&g=js1
|
||||
* Groups will be combined in the order specified.
|
||||
E.g. /g=js1,js2 != /g=js2,js1
|
||||
* Minify will NOT keep you from trying to combine Javascript and CSS.
|
||||
Combining the wrong files will cause an exception in JSMin or break CSS.
|
||||
|
||||
|
||||
FAR-FUTURE EXPIRES HEADERS
|
||||
|
||||
Minify can send far-future (one year) Expires headers. To enable this you must
|
||||
add a number to the querystring (e.g. /min/?g=js&1234 or /min/f=file.js&1234)
|
||||
and alter it whenever a source file is changed. If you have a build process you
|
||||
can use a build/source control revision number.
|
||||
|
||||
If you serve files as groups, you can use the utility function
|
||||
Minify_groupUri() to get a "versioned" Minify URI for use in your HTML. E.g.:
|
||||
|
||||
<?php
|
||||
// add /min/lib to your include_path first!
|
||||
require $_SERVER['DOCUMENT_ROOT'] . '/min/utils.php';
|
||||
|
||||
$jsUri = Minify_groupUri('js1,js2');
|
||||
echo "<script type='text/javascript' src='{$jsUri}'></script>";
|
||||
|
||||
|
||||
DEBUG MODE
|
||||
|
||||
In debug mode, instead of compressing files, Minify sends combined files with
|
||||
comments prepended to each line to show the line number in the original source
|
||||
file. To enable this, set $min_allowDebugFlag to true in config.php and append
|
||||
"&debug=1" to your URIs. E.g. /min/?f=script1.js,script2.js&debug
|
||||
|
||||
Known issue: files with comment-like strings/regexps can cause problems in this mode.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
|
||||
http://code.google.com/p/minify/wiki/CookBook
|
||||
|
||||
|
||||
QUESTIONS?
|
||||
|
||||
http://code.google.com/p/minify/wiki/CommonProblems
|
||||
http://groups.google.com/group/minify
|
@@ -1,242 +0,0 @@
|
||||
var MUB = {
|
||||
_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) {
|
||||
if (data === '1') {
|
||||
MUB._minRoot = '/min/';
|
||||
$('span.minRoot').html('/min/');
|
||||
} else
|
||||
fail();
|
||||
}
|
||||
,error : fail
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get markup for new source LI element
|
||||
*/
|
||||
,newLi : function () {
|
||||
return '<li id="li' + MUB._uid + '">http://' + location.host + '/<input type=text size=20>'
|
||||
+ ' <button title="Remove">x</button> <button title="Include Earlier">↑</button>'
|
||||
+ ' <button title="Include Later">↓</button> <span></span></li>';
|
||||
}
|
||||
/**
|
||||
* Add new empty source LI and attach handlers to buttons
|
||||
*/
|
||||
,addLi : function () {
|
||||
$('#sources').append(MUB.newLi());
|
||||
var li = $('#li' + MUB._uid)[0];
|
||||
$('button[title=Remove]', li).click(function () {
|
||||
$('#results').hide();
|
||||
var hadValue = !!$('input', li)[0].value;
|
||||
$(li).remove();
|
||||
});
|
||||
$('button[title$=Earlier]', li).click(function () {
|
||||
$(li).prev('li').find('input').each(function () {
|
||||
$('#results').hide();
|
||||
// this = previous li input
|
||||
var tmp = this.value;
|
||||
this.value = $('input', li).val();
|
||||
$('input', li).val(tmp);
|
||||
MUB.updateAllTestLinks();
|
||||
});
|
||||
});
|
||||
$('button[title$=Later]', li).click(function () {
|
||||
$(li).next('li').find('input').each(function () {
|
||||
$('#results').hide();
|
||||
// this = next li input
|
||||
var tmp = this.value;
|
||||
this.value = $('input', li).val();
|
||||
$('input', li).val(tmp);
|
||||
MUB.updateAllTestLinks();
|
||||
});
|
||||
});
|
||||
++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
|
||||
if (! $('input', this)[0].value)
|
||||
return;
|
||||
var li = this;
|
||||
$('span', this).html('');
|
||||
var url = 'http://' + location.host + '/'
|
||||
+ $('input', this)[0].value.replace(/^\//, '');
|
||||
$.ajax({
|
||||
url : url
|
||||
,complete : function (xhr, stat) {
|
||||
if ('success' == stat)
|
||||
$('span', li).html('✓');
|
||||
else {
|
||||
$('span', li).html('<button><b>404! </b> recheck</button>')
|
||||
.find('button').click(function () {
|
||||
MUB.liUpdateTestLink.call(li);
|
||||
});
|
||||
}
|
||||
}
|
||||
,dataType : 'text'
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Check all source URLs
|
||||
*/
|
||||
,updateAllTestLinks : function () {
|
||||
$('#sources li').each(MUB.liUpdateTestLink);
|
||||
}
|
||||
/**
|
||||
* In a given array of strings, find the character they all have at
|
||||
* a particular index
|
||||
* @param Array arr array of strings
|
||||
* @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);
|
||||
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;
|
||||
while (true) {
|
||||
c = MUB.getCommonCharAtPos(sources, pos);
|
||||
if (c === '')
|
||||
break;
|
||||
else
|
||||
base += c;
|
||||
++pos;
|
||||
}
|
||||
base = base.replace(/[^\/]+$/, '');
|
||||
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;
|
||||
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;
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
/**
|
||||
* Create the Minify URI for the sources
|
||||
*/
|
||||
,update : function () {
|
||||
MUB.updateAllTestLinks();
|
||||
var sources = []
|
||||
,ext = false
|
||||
,fail = false;
|
||||
$('#sources input').each(function () {
|
||||
var m, val;
|
||||
if (! fail && this.value && (m = this.value.match(/\.(css|js)$/))) {
|
||||
var thisExt = m[1];
|
||||
if (ext === false)
|
||||
ext = thisExt;
|
||||
else if (thisExt !== ext) {
|
||||
fail = true;
|
||||
return alert('extensions must match!');
|
||||
}
|
||||
this.value = this.value.replace(/^\//, '');
|
||||
if (-1 != $.inArray(this.value, sources)) {
|
||||
fail = true;
|
||||
return alert('duplicate file!');
|
||||
}
|
||||
sources.push(this.value);
|
||||
}
|
||||
});
|
||||
if (fail || ! sources.length)
|
||||
return;
|
||||
$('#groupConfig').val(" 'keyName' => array('//" + sources.join("', '//") + "'),");
|
||||
var uri = MUB.getBestUri(sources)
|
||||
,uriH = uri.replace(/</, '<').replace(/>/, '>').replace(/&/, '&');
|
||||
$('#uriA').html(uriH)[0].href = uri;
|
||||
$('#uriHtml').val(
|
||||
ext === 'js'
|
||||
? '<script type="text/javascript" src="' + uriH + '"></script>'
|
||||
: '<link type="text/css" rel="stylesheet" href="' + uriH + '" />'
|
||||
);
|
||||
$('#results').show();
|
||||
}
|
||||
/**
|
||||
* Handler for the "Add file +" button
|
||||
*/
|
||||
,addButtonClick : function () {
|
||||
$('#results').hide();
|
||||
MUB.addLi();
|
||||
MUB.updateAllTestLinks();
|
||||
$('#update').show().click(MUB.update);
|
||||
$('#sources li:last input')[0].focus();
|
||||
}
|
||||
/**
|
||||
* Runs on DOMready
|
||||
*/
|
||||
,init : function () {
|
||||
$('#app').show();
|
||||
$('#sources').html('');
|
||||
$('#add button').click(MUB.addButtonClick);
|
||||
// make easier to copy text out of
|
||||
$('#uriHtml, #groupConfig').click(function () {
|
||||
this.select();
|
||||
}).focus(function () {
|
||||
this.select();
|
||||
});
|
||||
$('a.ext').attr({target:'_blank'});
|
||||
if (location.hash) {
|
||||
// make links out of URIs from bookmarklet
|
||||
$('#getBm').hide();
|
||||
$('#bmUris').html('<p><strong>Found by bookmarklet:</strong> /<a href=#>'
|
||||
+ location.hash.substr(1).split(',').join('</a> | /<a href=#>')
|
||||
+ '</a></p>'
|
||||
);
|
||||
$('#bmUris a').click(function () {
|
||||
MUB.addButtonClick();
|
||||
$('#sources li:last input').val(this.innerHTML)
|
||||
MUB.liUpdateTestLink.call($('#sources li:last')[0]);
|
||||
$('#results').hide();
|
||||
return false;
|
||||
}).attr({title:'Add file +'});
|
||||
} else {
|
||||
// copy bookmarklet code into href
|
||||
var bmUri = location.pathname.replace(/\/[^\/]*$/, '/bm.js').substr(1);
|
||||
$.ajax({
|
||||
url : '../?f=' + bmUri
|
||||
,success : function (code) {
|
||||
$('#bm')[0].href = code
|
||||
.replace('%BUILDER_URL%', location.href)
|
||||
.replace(/\n/g, ' ');
|
||||
}
|
||||
,dataType : 'text'
|
||||
});
|
||||
$.browser.msie && $('#getBm p:last').append(' Sorry, not supported in MSIE!');
|
||||
MUB.addButtonClick();
|
||||
}
|
||||
MUB.checkRewrite();
|
||||
}
|
||||
};
|
||||
window.onload = MUB.init;
|
@@ -1,36 +0,0 @@
|
||||
javascript:(function() {
|
||||
var d = document
|
||||
,uris = []
|
||||
,i = 0
|
||||
,o
|
||||
,home = (location + '').split('/').splice(0, 3).join('/') + '/';
|
||||
function add(uri) {
|
||||
return (0 === uri.indexOf(home))
|
||||
&& (!/[\?&]/.test(uri))
|
||||
&& uris.push(escape(uri.substr(home.length)));
|
||||
};
|
||||
function sheet(ss) {
|
||||
// we must check the domain with add() before accessing ss.cssRules
|
||||
// otherwise a security exception will be thrown
|
||||
if (ss.href && add(ss.href) && ss.cssRules) {
|
||||
var i = 0, r;
|
||||
while (r = ss.cssRules[i++])
|
||||
r.styleSheet && sheet(r.styleSheet);
|
||||
}
|
||||
};
|
||||
while (o = d.getElementsByTagName('script')[i++])
|
||||
o.src && !(o.type && /vbs/i.test(o.type)) && add(o.src);
|
||||
i = 0;
|
||||
while (o = d.styleSheets[i++])
|
||||
/* http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-DocumentStyle-styleSheets
|
||||
document.styleSheet is a list property where [0] accesses the 1st element and
|
||||
[outOfRange] returns null. In IE, styleSheets is a function, and also throws an
|
||||
exception when you check the out of bounds index. (sigh) */
|
||||
sheet(o);
|
||||
if (uris.length)
|
||||
window.open('%BUILDER_URL%#' + uris.join(','));
|
||||
else
|
||||
alert('No js/css files found with URLs within "'
|
||||
+ home.split('/')[2]
|
||||
+ '".\n(This tool is limited to URLs with the same domain.)');
|
||||
})();
|
@@ -1,186 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (phpversion() < 5) {
|
||||
exit('Minify requires PHP5 or greater.');
|
||||
}
|
||||
|
||||
// check for auto-encoding
|
||||
$encodeOutput = (function_exists('gzdeflate')
|
||||
&& !ini_get('zlib.output_compression'));
|
||||
|
||||
require dirname(__FILE__) . '/../config.php';
|
||||
|
||||
if (! $min_enableBuilder) {
|
||||
header('Location: /');
|
||||
exit();
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<head>
|
||||
<meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
|
||||
<title>Minify URI Builder</title>
|
||||
<style type="text/css">
|
||||
body {margin:1em 60px;}
|
||||
h1, h2, h3 {margin-left:-25px; position:relative;}
|
||||
h1 {margin-top:0;}
|
||||
#sources {margin:0; padding:0;}
|
||||
#sources li {margin:0 0 0 40px}
|
||||
#sources li input {margin-left:2px}
|
||||
#add {margin:5px 0 1em 40px}
|
||||
.hide {display:none}
|
||||
#uriTable {border-collapse:collapse;}
|
||||
#uriTable td, #uriTable th {padding-top:10px;}
|
||||
#uriTable th {padding-right:10px;}
|
||||
#groupConfig {font-family:monospace;}
|
||||
b {color:#c00}
|
||||
.topNote {background: #ff9; display:inline-block; padding:.5em .6em; margin:0 0 1em;}
|
||||
.topWarning {background:#c00; color:#fff; padding:.5em .6em; margin:0 0 1em;}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<?php if (! isset($min_cachePath)): ?>
|
||||
<p class=topNote><strong>Note:</strong> Please set <code>$min_cachePath</code>
|
||||
in /min/config.php to improve performance.</p>
|
||||
<?php endIf; ?>
|
||||
|
||||
<p id=minRewriteFailed class="hide"><strong>Note:</strong> Your webserver does not seem to
|
||||
support mod_rewrite (used in /min/.htaccess). Your Minify URIs will contain "?", which
|
||||
<a href="http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/"
|
||||
>may reduce the benefit of proxy cache servers</a>.</p>
|
||||
|
||||
<h1>Minify URI Builder</h1>
|
||||
|
||||
<noscript><p class="topNote">Javascript and a browser supported by jQuery 1.2.6 is required
|
||||
for this application.</p></noscript>
|
||||
|
||||
<div id=app class=hide>
|
||||
|
||||
<p>Create a list of Javascript or CSS files (or 1 is fine) you'd like to combine
|
||||
and click [Update].</p>
|
||||
|
||||
<ol id=sources><li></li></ol>
|
||||
<div id=add><button>Add file +</button></div>
|
||||
|
||||
<div id=bmUris></div>
|
||||
|
||||
<p><button id=update class=hide>Update</button></p>
|
||||
|
||||
<div id=results class=hide>
|
||||
|
||||
<h2>Minify URI</h2>
|
||||
<p>Place this URI in your HTML to serve the files above combined, minified, compressed and
|
||||
with cache headers.</p>
|
||||
<table id=uriTable>
|
||||
<tr><th>URI</th><td><a id=uriA class=ext>/min</a> <small>(opens in new window)</small></td></tr>
|
||||
<tr><th>HTML</th><td><input id=uriHtml type=text size=100 readonly></td></tr>
|
||||
</table>
|
||||
|
||||
<h2>How to serve these files as a group</h2>
|
||||
<p>For the best performance you can serve these files as a pre-defined group with a URI
|
||||
like: <code><span class=minRoot>/min/?</span>g=keyName</code></p>
|
||||
<p>To do this, add a line like this to /min/groupsConfig.php:</p>
|
||||
|
||||
<pre><code>return array(
|
||||
<span style="color:#666">... your existing groups here ...</span>
|
||||
<input id=groupConfig size=100 type=text readonly>
|
||||
);</code></pre>
|
||||
|
||||
<p><em>Make sure to replace <code>keyName</code> with a unique key for this group.</em></p>
|
||||
</div>
|
||||
|
||||
<div id=getBm>
|
||||
<h3>Find URIs on a Page</h3>
|
||||
<p>You can use the bookmarklet below to fetch all CSS & Javascript URIs from a page
|
||||
on your site. When you active it, this page will open in a new window with a list of
|
||||
available URIs to add.</p>
|
||||
|
||||
<p><a id=bm>Create Minify URIs</a> <small>(right-click, add to bookmarks)</small></p>
|
||||
</div>
|
||||
|
||||
<h3>Combining CSS files that contain <code>@import</code></h3>
|
||||
<p>If your CSS files contain <code>@import</code> declarations, Minify will not
|
||||
remove them. Therefore, you will want to remove those that point to files already
|
||||
in your list, and move any others to the top of the first file in your list
|
||||
(imports below any styles will be ignored by browsers as invalid).</p>
|
||||
<p>If you desire, you can use Minify URIs in imports and they will not be touched
|
||||
by Minify. E.g. <code>@import "<span class=minRoot>/min/?</span>g=css2";</code></p>
|
||||
|
||||
</div><!-- #app -->
|
||||
|
||||
<hr>
|
||||
<p>Need help? Search or post to the <a class=ext
|
||||
href="http://groups.google.com/group/minify">Minify discussion list</a>.</p>
|
||||
<p><small>This app is minified :) <a class=ext
|
||||
href="http://code.google.com/p/minify/source/browse/trunk/min/builder/index.php">view
|
||||
source</a></small></p>
|
||||
|
||||
<script type="text/javascript"
|
||||
src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
// detection of double output encoding
|
||||
var msg = '<\p class=topWarning><\strong>Warning:<\/strong> ';
|
||||
var url = 'ocCheck.php?' + (new Date()).getTime();
|
||||
$.get(url, function (ocStatus) {
|
||||
$.get(url + '&hello=1', function (ocHello) {
|
||||
if (ocHello != 'World!') {
|
||||
msg += 'It appears output is being automatically compressed, interfering '
|
||||
+ ' with Minify\'s own compression. ';
|
||||
if (ocStatus == '1')
|
||||
msg += 'The option "zlib.output_compression" is enabled in your PHP configuration. '
|
||||
+ 'Minify set this to "0", but it had no effect. This option must be disabled '
|
||||
+ 'in php.ini or .htaccess.';
|
||||
else
|
||||
msg += 'The option "zlib.output_compression" is disabled in your PHP configuration '
|
||||
+ 'so this behavior is likely due to a server option.';
|
||||
$(document.body).prepend(msg + '<\/p>');
|
||||
} else
|
||||
if (ocStatus == '1')
|
||||
$(document.body).prepend('<\p class=topNote><\strong>Note:</\strong> The option '
|
||||
+ '"zlib.output_compression" is enabled in your PHP configuration, but has been '
|
||||
+ 'successfully disabled via ini_set(). If you experience mangled output you '
|
||||
+ 'may want to consider disabling this option in your PHP configuration.<\/p>'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
// workaround required to test when /min isn't child of web root
|
||||
var src = location.pathname.replace(/\/[^\/]*$/, '/_index.js').substr(1);
|
||||
document.write('<\script type="text/javascript" src="../?f=' + src + '"><\/script>');
|
||||
</script>
|
||||
|
||||
<?php
|
||||
|
||||
$serveOpts = array(
|
||||
'content' => ob_get_contents()
|
||||
,'id' => __FILE__
|
||||
,'lastModifiedTime' => max(
|
||||
// regenerate cache if either of these change
|
||||
filemtime(__FILE__)
|
||||
,filemtime(dirname(__FILE__) . '/../config.php')
|
||||
)
|
||||
,'minifyAll' => true
|
||||
,'encodeOutput' => $encodeOutput
|
||||
);
|
||||
ob_end_clean();
|
||||
|
||||
set_include_path(dirname(__FILE__) . '/../lib' . PATH_SEPARATOR . get_include_path());
|
||||
function min_autoload($name) {
|
||||
require str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php';
|
||||
}
|
||||
spl_autoload_register('min_autoload');
|
||||
|
||||
//require 'Minify.php';
|
||||
|
||||
if (0 === stripos(PHP_OS, 'win')) {
|
||||
Minify::setDocRoot(); // we may be on IIS
|
||||
}
|
||||
Minify::setCache(isset($min_cachePath) ? $min_cachePath : null);
|
||||
Minify::$uploaderHoursBehind = $min_uploaderHoursBehind;
|
||||
|
||||
Minify::serve('Page', $serveOpts);
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* AJAX checks for zlib.output_compression
|
||||
*
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
$_oc = ini_get('zlib.output_compression');
|
||||
|
||||
// allow access only if builder is enabled
|
||||
require dirname(__FILE__) . '/../config.php';
|
||||
if (! $min_enableBuilder) {
|
||||
header('Location: /');
|
||||
exit();
|
||||
}
|
||||
|
||||
if (isset($_GET['hello'])) {
|
||||
// echo 'World!'
|
||||
|
||||
// try to prevent double encoding (may not have an effect)
|
||||
ini_set('zlib.output_compression', '0');
|
||||
|
||||
require $min_libPath . '/HTTP/Encoder.php';
|
||||
HTTP_Encoder::$encodeToIe6 = true; // just in case
|
||||
$he = new HTTP_Encoder(array(
|
||||
'content' => 'World!'
|
||||
,'method' => 'deflate'
|
||||
));
|
||||
$he->encode();
|
||||
$he->sendAll();
|
||||
|
||||
} else {
|
||||
// echo status "0" or "1"
|
||||
header('Content-Type: text/plain');
|
||||
echo (int)$_oc;
|
||||
}
|
@@ -1 +0,0 @@
|
||||
1
|
157
min/config.php
157
min/config.php
@@ -1,157 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Configuration for default Minify application
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* In 'debug' mode, Minify can combine files with no minification and
|
||||
* add comments to indicate line #s of the original files.
|
||||
*
|
||||
* To allow debugging, set this option to true and add "&debug=1" to
|
||||
* a URI. E.g. /min/?f=script1.js,script2.js&debug=1
|
||||
*/
|
||||
$min_allowDebugFlag = false;
|
||||
|
||||
|
||||
/**
|
||||
* Set to true to log messages to FirePHP (Firefox Firebug addon).
|
||||
* Set to false for no error logging (Minify may be slightly faster).
|
||||
* @link http://www.firephp.org/
|
||||
*
|
||||
* If you want to use a custom error logger, set this to your logger
|
||||
* instance. Your object should have a method log(string $message).
|
||||
*
|
||||
* @todo cache system does not have error logging yet.
|
||||
*/
|
||||
$min_errorLogger = false;
|
||||
|
||||
|
||||
/**
|
||||
* Allow use of the Minify URI Builder app. If you no longer need
|
||||
* this, set to false.
|
||||
**/
|
||||
$min_enableBuilder = true;
|
||||
|
||||
|
||||
/**
|
||||
* For best performance, specify your temp directory here. Otherwise Minify
|
||||
* will have to load extra code to guess. Some examples below:
|
||||
*/
|
||||
//$min_cachePath = 'c:\\WINDOWS\\Temp';
|
||||
//$min_cachePath = '/tmp';
|
||||
//$min_cachePath = preg_replace('/^\\d+;/', '', session_save_path());
|
||||
|
||||
|
||||
/**
|
||||
* Leave an empty string to use PHP's $_SERVER['DOCUMENT_ROOT'].
|
||||
*
|
||||
* On some servers, this value may be misconfigured or missing. If so, set this
|
||||
* to your full document root path with no trailing slash.
|
||||
* E.g. '/home/accountname/public_html' or 'c:\\xampp\\htdocs'
|
||||
*
|
||||
* If /min/ is directly inside your document root, just uncomment the
|
||||
* second line. The third line might work on some Apache servers.
|
||||
*/
|
||||
$min_documentRoot = '';
|
||||
//$min_documentRoot = substr(__FILE__, 0, strlen(__FILE__) - 15);
|
||||
//$min_documentRoot = $_SERVER['SUBDOMAIN_DOCUMENT_ROOT'];
|
||||
|
||||
|
||||
/**
|
||||
* Cache file locking. Set to false if filesystem is NFS. On at least one
|
||||
* NFS system flock-ing attempts stalled PHP for 30 seconds!
|
||||
*/
|
||||
$min_cacheFileLocking = true;
|
||||
|
||||
|
||||
/**
|
||||
* Combining multiple CSS files can place @import declarations after rules, which
|
||||
* is invalid. Minify will attempt to detect when this happens and place a
|
||||
* warning comment at the top of the CSS output. To resolve this you can either
|
||||
* move the @imports within your CSS files, or enable this option, which will
|
||||
* move all @imports to the top of the output. Note that moving @imports could
|
||||
* affect CSS values (which is why this option is disabled by default).
|
||||
*/
|
||||
$min_serveOptions['bubbleCssImports'] = false;
|
||||
|
||||
|
||||
/**
|
||||
* Maximum age of browser cache in seconds. After this period, the browser
|
||||
* will send another conditional GET. Use a longer period for lower traffic
|
||||
* but you may want to shorten this before making changes if it's crucial
|
||||
* those changes are seen immediately.
|
||||
*
|
||||
* Note: Despite this setting, if you include a number at the end of the
|
||||
* querystring, maxAge will be set to one year. E.g. /min/f=hello.css&123456
|
||||
*/
|
||||
$min_serveOptions['maxAge'] = 1800;
|
||||
|
||||
|
||||
/**
|
||||
* If you'd like to restrict the "f" option to files within/below
|
||||
* particular directories below DOCUMENT_ROOT, set this here.
|
||||
* You will still need to include the directory in the
|
||||
* f or b GET parameters.
|
||||
*
|
||||
* // = shortcut for DOCUMENT_ROOT
|
||||
*/
|
||||
//$min_serveOptions['minApp']['allowDirs'] = array('//js', '//css');
|
||||
|
||||
/**
|
||||
* Set to true to disable the "f" GET parameter for specifying files.
|
||||
* Only the "g" parameter will be considered.
|
||||
*/
|
||||
$min_serveOptions['minApp']['groupsOnly'] = false;
|
||||
|
||||
/**
|
||||
* Maximum # of files that can be specified in the "f" GET parameter
|
||||
*/
|
||||
$min_serveOptions['minApp']['maxFiles'] = 10;
|
||||
|
||||
|
||||
/**
|
||||
* If you minify CSS files stored in symlink-ed directories, the URI rewriting
|
||||
* algorithm can fail. To prevent this, provide an array of link paths to
|
||||
* target paths, where the link paths are within the document root.
|
||||
*
|
||||
* Because paths need to be normalized for this to work, use "//" to substitute
|
||||
* the doc root in the link paths (the array keys). E.g.:
|
||||
* <code>
|
||||
* array('//symlink' => '/real/target/path') // unix
|
||||
* array('//static' => 'D:\\staticStorage') // Windows
|
||||
* </code>
|
||||
*/
|
||||
$min_symlinks = array();
|
||||
|
||||
|
||||
/**
|
||||
* If you upload files from Windows to a non-Windows server, Windows may report
|
||||
* incorrect mtimes for the files. This may cause Minify to keep serving stale
|
||||
* cache files when source file changes are made too frequently (e.g. more than
|
||||
* once an hour).
|
||||
*
|
||||
* Immediately after modifying and uploading a file, use the touch command to
|
||||
* update the mtime on the server. If the mtime jumps ahead by a number of hours,
|
||||
* set this variable to that number. If the mtime moves back, this should not be
|
||||
* needed.
|
||||
*
|
||||
* In the Windows SFTP client WinSCP, there's an option that may fix this
|
||||
* issue without changing the variable below. Under login > environment,
|
||||
* select the option "Adjust remote timestamp with DST".
|
||||
* @link http://winscp.net/eng/docs/ui_login_environment#daylight_saving_time
|
||||
*/
|
||||
$min_uploaderHoursBehind = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Path to Minify's lib folder. If you happen to move it, change
|
||||
* this accordingly.
|
||||
*/
|
||||
$min_libPath = dirname(__FILE__) . '/lib';
|
||||
|
||||
|
||||
// try to disable output_compression (may not have an effect)
|
||||
ini_set('zlib.output_compression', '0');
|
||||
ini_set('output_handler', '');
|
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Groups configuration for default Minify implementation
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* You may wish to use the Minify URI Builder app to suggest
|
||||
* changes. http://yourdomain/min/builder/
|
||||
**/
|
||||
|
||||
return array(
|
||||
// 'js' => array('//js/file1.js', '//js/file2.js'),
|
||||
// 'css' => array('//css/file1.css', '//css/file2.css'),
|
||||
|
||||
// custom source example
|
||||
// see http://code.google.com/p/minify/wiki/CustomSource
|
||||
/*'js2' => array(
|
||||
dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
|
||||
// do NOT process this file
|
||||
new Minify_Source(array(
|
||||
'filepath' => dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
|
||||
'minifier' => ''
|
||||
))
|
||||
),//*/
|
||||
|
||||
/*'js3' => array(
|
||||
dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
|
||||
// do NOT process this file
|
||||
new Minify_Source(array(
|
||||
'filepath' => dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
|
||||
'minifier' => array('Minify_Packer', 'minify')
|
||||
))
|
||||
),//*/
|
||||
|
||||
// testing
|
||||
//'js' => array(dirname(__FILE__) . '/builder/_index.js'),
|
||||
);
|
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Front controller for default Minify implementation
|
||||
*
|
||||
* DO NOT EDIT! Configure this utility via config.php and groupsConfig.php
|
||||
*
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
define('MINIFY_MIN_DIR', dirname(__FILE__));
|
||||
|
||||
// load config
|
||||
require MINIFY_MIN_DIR . '/config.php';
|
||||
|
||||
// setup include path
|
||||
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
function min_autoload($name) {
|
||||
require str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php';
|
||||
}
|
||||
spl_autoload_register('min_autoload');
|
||||
|
||||
|
||||
Minify::$uploaderHoursBehind = $min_uploaderHoursBehind;
|
||||
Minify::setCache(
|
||||
isset($min_cachePath) ? $min_cachePath : ''
|
||||
,$min_cacheFileLocking
|
||||
);
|
||||
|
||||
if ($min_documentRoot) {
|
||||
$_SERVER['DOCUMENT_ROOT'] = $min_documentRoot;
|
||||
} elseif (0 === stripos(PHP_OS, 'win')) {
|
||||
Minify::setDocRoot(); // IIS may need help
|
||||
}
|
||||
$_SERVER['DOCUMENT_ROOT'] = rtrim($_SERVER['DOCUMENT_ROOT'], '/\\');
|
||||
|
||||
$min_serveOptions['minifierOptions']['text/css']['symlinks'] = $min_symlinks;
|
||||
|
||||
if ($min_allowDebugFlag && isset($_GET['debug'])) {
|
||||
$min_serveOptions['debug'] = true;
|
||||
}
|
||||
|
||||
if ($min_errorLogger) {
|
||||
//require_once $min_libPath . '/Minify/Logger.php';
|
||||
if (true === $min_errorLogger) {
|
||||
//require_once $min_libPath . '/FirePHP.php';
|
||||
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
||||
} else {
|
||||
Minify_Logger::setLogger($min_errorLogger);
|
||||
}
|
||||
}
|
||||
|
||||
// check for URI versioning
|
||||
if (preg_match('/&\\d/', $_SERVER['QUERY_STRING'])) {
|
||||
$min_serveOptions['maxAge'] = 31536000;
|
||||
}
|
||||
if (isset($_GET['g'])) {
|
||||
// we'll need groups config
|
||||
$min_serveOptions['minApp']['groups'] = (require MINIFY_MIN_DIR . '/groupsConfig.php');
|
||||
}
|
||||
if (isset($_GET['f']) || isset($_GET['g'])) {
|
||||
// serve!
|
||||
Minify::serve('MinApp', $min_serveOptions);
|
||||
|
||||
} elseif ($min_enableBuilder) {
|
||||
header('Location: builder/');
|
||||
exit();
|
||||
} else {
|
||||
header("Location: /");
|
||||
exit();
|
||||
}
|
1370
min/lib/FirePHP.php
1370
min/lib/FirePHP.php
File diff suppressed because it is too large
Load Diff
@@ -1,348 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class HTTP_ConditionalGet
|
||||
* @package Minify
|
||||
* @subpackage HTTP
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implement conditional GET via a timestamp or hash of content
|
||||
*
|
||||
* E.g. Content from DB with update time:
|
||||
* <code>
|
||||
* list($updateTime, $content) = getDbUpdateAndContent();
|
||||
* $cg = new HTTP_ConditionalGet(array(
|
||||
* 'lastModifiedTime' => $updateTime
|
||||
* ,'isPublic' => true
|
||||
* ));
|
||||
* $cg->sendHeaders();
|
||||
* if ($cg->cacheIsValid) {
|
||||
* exit();
|
||||
* }
|
||||
* echo $content;
|
||||
* </code>
|
||||
*
|
||||
* E.g. Shortcut for the above
|
||||
* <code>
|
||||
* HTTP_ConditionalGet::check($updateTime, true); // exits if client has cache
|
||||
* echo $content;
|
||||
* </code>
|
||||
*
|
||||
* E.g. Content from DB with no update time:
|
||||
* <code>
|
||||
* $content = getContentFromDB();
|
||||
* $cg = new HTTP_ConditionalGet(array(
|
||||
* 'contentHash' => md5($content)
|
||||
* ));
|
||||
* $cg->sendHeaders();
|
||||
* if ($cg->cacheIsValid) {
|
||||
* exit();
|
||||
* }
|
||||
* echo $content;
|
||||
* </code>
|
||||
*
|
||||
* E.g. Static content with some static includes:
|
||||
* <code>
|
||||
* // before content
|
||||
* $cg = new HTTP_ConditionalGet(array(
|
||||
* 'lastUpdateTime' => max(
|
||||
* filemtime(__FILE__)
|
||||
* ,filemtime('/path/to/header.inc')
|
||||
* ,filemtime('/path/to/footer.inc')
|
||||
* )
|
||||
* ));
|
||||
* $cg->sendHeaders();
|
||||
* if ($cg->cacheIsValid) {
|
||||
* exit();
|
||||
* }
|
||||
* </code>
|
||||
* @package Minify
|
||||
* @subpackage HTTP
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class HTTP_ConditionalGet {
|
||||
|
||||
/**
|
||||
* Does the client have a valid copy of the requested resource?
|
||||
*
|
||||
* You'll want to check this after instantiating the object. If true, do
|
||||
* not send content, just call sendHeaders() if you haven't already.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $cacheIsValid = null;
|
||||
|
||||
/**
|
||||
* @param array $spec options
|
||||
*
|
||||
* 'isPublic': (bool) if true, the Cache-Control header will contain
|
||||
* "public", allowing proxies to cache the content. Otherwise "private" will
|
||||
* be sent, allowing only browser caching. (default false)
|
||||
*
|
||||
* 'lastModifiedTime': (int) if given, both ETag AND Last-Modified headers
|
||||
* will be sent with content. This is recommended.
|
||||
*
|
||||
* 'encoding': (string) if set, the header "Vary: Accept-Encoding" will
|
||||
* always be sent and a truncated version of the encoding will be appended
|
||||
* to the ETag. E.g. "pub123456;gz". This will also trigger a more lenient
|
||||
* checking of the client's If-None-Match header, as the encoding portion of
|
||||
* the ETag will be stripped before comparison.
|
||||
*
|
||||
* 'contentHash': (string) if given, only the ETag header can be sent with
|
||||
* content (only HTTP1.1 clients can conditionally GET). The given string
|
||||
* should be short with no quote characters and always change when the
|
||||
* resource changes (recommend md5()). This is not needed/used if
|
||||
* lastModifiedTime is given.
|
||||
*
|
||||
* 'eTag': (string) if given, this will be used as the ETag header rather
|
||||
* than values based on lastModifiedTime or contentHash. Also the encoding
|
||||
* string will not be appended to the given value as described above.
|
||||
*
|
||||
* 'invalidate': (bool) if true, the client cache will be considered invalid
|
||||
* without testing. Effectively this disables conditional GET.
|
||||
* (default false)
|
||||
*
|
||||
* 'maxAge': (int) if given, this will set the Cache-Control max-age in
|
||||
* seconds, and also set the Expires header to the equivalent GMT date.
|
||||
* After the max-age period has passed, the browser will again send a
|
||||
* conditional GET to revalidate its cache.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function __construct($spec)
|
||||
{
|
||||
$scope = (isset($spec['isPublic']) && $spec['isPublic'])
|
||||
? 'public'
|
||||
: 'private';
|
||||
$maxAge = 0;
|
||||
// backwards compatibility (can be removed later)
|
||||
if (isset($spec['setExpires'])
|
||||
&& is_numeric($spec['setExpires'])
|
||||
&& ! isset($spec['maxAge'])) {
|
||||
$spec['maxAge'] = $spec['setExpires'] - $_SERVER['REQUEST_TIME'];
|
||||
}
|
||||
if (isset($spec['maxAge'])) {
|
||||
$maxAge = $spec['maxAge'];
|
||||
$this->_headers['Expires'] = self::gmtDate(
|
||||
$_SERVER['REQUEST_TIME'] + $spec['maxAge']
|
||||
);
|
||||
}
|
||||
$etagAppend = '';
|
||||
if (isset($spec['encoding'])) {
|
||||
$this->_stripEtag = true;
|
||||
$this->_headers['Vary'] = 'Accept-Encoding';
|
||||
if ('' !== $spec['encoding']) {
|
||||
if (0 === strpos($spec['encoding'], 'x-')) {
|
||||
$spec['encoding'] = substr($spec['encoding'], 2);
|
||||
}
|
||||
$etagAppend = ';' . substr($spec['encoding'], 0, 2);
|
||||
}
|
||||
}
|
||||
if (isset($spec['lastModifiedTime'])) {
|
||||
$this->_setLastModified($spec['lastModifiedTime']);
|
||||
if (isset($spec['eTag'])) { // Use it
|
||||
$this->_setEtag($spec['eTag'], $scope);
|
||||
} else { // base both headers on time
|
||||
$this->_setEtag($spec['lastModifiedTime'] . $etagAppend, $scope);
|
||||
}
|
||||
} elseif (isset($spec['eTag'])) { // Use it
|
||||
$this->_setEtag($spec['eTag'], $scope);
|
||||
} elseif (isset($spec['contentHash'])) { // Use the hash as the ETag
|
||||
$this->_setEtag($spec['contentHash'] . $etagAppend, $scope);
|
||||
}
|
||||
$this->_headers['Cache-Control'] = "max-age={$maxAge}, {$scope}";
|
||||
// invalidate cache if disabled, otherwise check
|
||||
$this->cacheIsValid = (isset($spec['invalidate']) && $spec['invalidate'])
|
||||
? false
|
||||
: $this->_isCacheValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of output headers to be sent
|
||||
*
|
||||
* In the case of 304 responses, this array will only contain the response
|
||||
* code header: array('_responseCode' => 'HTTP/1.0 304 Not Modified')
|
||||
*
|
||||
* Otherwise something like:
|
||||
* <code>
|
||||
* array(
|
||||
* 'Cache-Control' => 'max-age=0, public'
|
||||
* ,'ETag' => '"foobar"'
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->_headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Content-Length header in bytes
|
||||
*
|
||||
* With most PHP configs, as long as you don't flush() output, this method
|
||||
* is not needed and PHP will buffer all output and set Content-Length for
|
||||
* you. Otherwise you'll want to call this to let the client know up front.
|
||||
*
|
||||
* @param int $bytes
|
||||
*
|
||||
* @return int copy of input $bytes
|
||||
*/
|
||||
public function setContentLength($bytes)
|
||||
{
|
||||
return $this->_headers['Content-Length'] = $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send headers
|
||||
*
|
||||
* @see getHeaders()
|
||||
*
|
||||
* Note this doesn't "clear" the headers. Calling sendHeaders() will
|
||||
* call header() again (but probably have not effect) and getHeaders() will
|
||||
* still return the headers.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function sendHeaders()
|
||||
{
|
||||
$headers = $this->_headers;
|
||||
if (array_key_exists('_responseCode', $headers)) {
|
||||
header($headers['_responseCode']);
|
||||
unset($headers['_responseCode']);
|
||||
}
|
||||
foreach ($headers as $name => $val) {
|
||||
header($name . ': ' . $val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit if the client's cache is valid for this resource
|
||||
*
|
||||
* This is a convenience method for common use of the class
|
||||
*
|
||||
* @param int $lastModifiedTime if given, both ETag AND Last-Modified headers
|
||||
* will be sent with content. This is recommended.
|
||||
*
|
||||
* @param bool $isPublic (default false) if true, the Cache-Control header
|
||||
* will contain "public", allowing proxies to cache the content. Otherwise
|
||||
* "private" will be sent, allowing only browser caching.
|
||||
*
|
||||
* @param array $options (default empty) additional options for constructor
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public static function check($lastModifiedTime = null, $isPublic = false, $options = array())
|
||||
{
|
||||
if (null !== $lastModifiedTime) {
|
||||
$options['lastModifiedTime'] = (int)$lastModifiedTime;
|
||||
}
|
||||
$options['isPublic'] = (bool)$isPublic;
|
||||
$cg = new HTTP_ConditionalGet($options);
|
||||
$cg->sendHeaders();
|
||||
if ($cg->cacheIsValid) {
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a GMT formatted date for use in HTTP headers
|
||||
*
|
||||
* <code>
|
||||
* header('Expires: ' . HTTP_ConditionalGet::gmtdate($time));
|
||||
* </code>
|
||||
*
|
||||
* @param int $time unix timestamp
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function gmtDate($time)
|
||||
{
|
||||
return gmdate('D, d M Y H:i:s \G\M\T', $time);
|
||||
}
|
||||
|
||||
protected $_headers = array();
|
||||
protected $_lmTime = null;
|
||||
protected $_etag = null;
|
||||
protected $_stripEtag = false;
|
||||
|
||||
protected function _setEtag($hash, $scope)
|
||||
{
|
||||
$this->_etag = '"' . substr($scope, 0, 3) . $hash . '"';
|
||||
$this->_headers['ETag'] = $this->_etag;
|
||||
}
|
||||
|
||||
protected function _setLastModified($time)
|
||||
{
|
||||
$this->_lmTime = (int)$time;
|
||||
$this->_headers['Last-Modified'] = self::gmtDate($time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine validity of client cache and queue 304 header if valid
|
||||
*/
|
||||
protected function _isCacheValid()
|
||||
{
|
||||
if (null === $this->_etag) {
|
||||
// lmTime is copied to ETag, so this condition implies that the
|
||||
// server sent neither ETag nor Last-Modified, so the client can't
|
||||
// possibly has a valid cache.
|
||||
return false;
|
||||
}
|
||||
$isValid = ($this->resourceMatchedEtag() || $this->resourceNotModified());
|
||||
if ($isValid) {
|
||||
$this->_headers['_responseCode'] = 'HTTP/1.0 304 Not Modified';
|
||||
}
|
||||
return $isValid;
|
||||
}
|
||||
|
||||
protected function resourceMatchedEtag()
|
||||
{
|
||||
if (!isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
|
||||
return false;
|
||||
}
|
||||
$clientEtagList = get_magic_quotes_gpc()
|
||||
? stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])
|
||||
: $_SERVER['HTTP_IF_NONE_MATCH'];
|
||||
$clientEtags = explode(',', $clientEtagList);
|
||||
|
||||
$compareTo = $this->normalizeEtag($this->_etag);
|
||||
foreach ($clientEtags as $clientEtag) {
|
||||
if ($this->normalizeEtag($clientEtag) === $compareTo) {
|
||||
// respond with the client's matched ETag, even if it's not what
|
||||
// we would've sent by default
|
||||
$this->_headers['ETag'] = trim($clientEtag);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function normalizeEtag($etag) {
|
||||
$etag = trim($etag);
|
||||
return $this->_stripEtag
|
||||
? preg_replace('/;\\w\\w"$/', '"', $etag)
|
||||
: $etag;
|
||||
}
|
||||
|
||||
protected function resourceNotModified()
|
||||
{
|
||||
if (!isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
||||
return false;
|
||||
}
|
||||
$ifModifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
|
||||
if (false !== ($semicolon = strrpos($ifModifiedSince, ';'))) {
|
||||
// IE has tacked on extra data to this header, strip it
|
||||
$ifModifiedSince = substr($ifModifiedSince, 0, $semicolon);
|
||||
}
|
||||
if ($ifModifiedSince == self::gmtDate($this->_lmTime)) {
|
||||
// Apache 2.2's behavior. If there was no ETag match, send the
|
||||
// non-encoded version of the ETag value.
|
||||
$this->_headers['ETag'] = $this->normalizeEtag($this->_etag);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -1,326 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class HTTP_Encoder
|
||||
* @package Minify
|
||||
* @subpackage HTTP
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encode and send gzipped/deflated content
|
||||
*
|
||||
* The "Vary: Accept-Encoding" header is sent. If the client allows encoding,
|
||||
* Content-Encoding and Content-Length are added.
|
||||
*
|
||||
* <code>
|
||||
* // Send a CSS file, compressed if possible
|
||||
* $he = new HTTP_Encoder(array(
|
||||
* 'content' => file_get_contents($cssFile)
|
||||
* ,'type' => 'text/css'
|
||||
* ));
|
||||
* $he->encode();
|
||||
* $he->sendAll();
|
||||
* </code>
|
||||
*
|
||||
* <code>
|
||||
* // Shortcut to encoding output
|
||||
* header('Content-Type: text/css'); // needed if not HTML
|
||||
* HTTP_Encoder::output($css);
|
||||
* </code>
|
||||
*
|
||||
* <code>
|
||||
* // Just sniff for the accepted encoding
|
||||
* $encoding = HTTP_Encoder::getAcceptedEncoding();
|
||||
* </code>
|
||||
*
|
||||
* For more control over headers, use getHeaders() and getData() and send your
|
||||
* own output.
|
||||
*
|
||||
* Note: If you don't need header mgmt, use PHP's native gzencode, gzdeflate,
|
||||
* and gzcompress functions for gzip, deflate, and compress-encoding
|
||||
* respectively.
|
||||
*
|
||||
* @package Minify
|
||||
* @subpackage HTTP
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class HTTP_Encoder {
|
||||
|
||||
/**
|
||||
* Should the encoder allow HTTP encoding to IE6?
|
||||
*
|
||||
* If you have many IE6 users and the bandwidth savings is worth troubling
|
||||
* some of them, set this to true.
|
||||
*
|
||||
* By default, encoding is only offered to IE7+. When this is true,
|
||||
* getAcceptedEncoding() will return an encoding for IE6 if its user agent
|
||||
* string contains "SV1". This has been documented in many places as "safe",
|
||||
* but there seem to be remaining, intermittent encoding bugs in patched
|
||||
* IE6 on the wild web.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $encodeToIe6 = false;
|
||||
|
||||
|
||||
/**
|
||||
* Default compression level for zlib operations
|
||||
*
|
||||
* This level is used if encode() is not given a $compressionLevel
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public static $compressionLevel = 6;
|
||||
|
||||
|
||||
/**
|
||||
* Get an HTTP Encoder object
|
||||
*
|
||||
* @param array $spec options
|
||||
*
|
||||
* 'content': (string required) content to be encoded
|
||||
*
|
||||
* 'type': (string) if set, the Content-Type header will have this value.
|
||||
*
|
||||
* 'method: (string) only set this if you are forcing a particular encoding
|
||||
* method. If not set, the best method will be chosen by getAcceptedEncoding()
|
||||
* The available methods are 'gzip', 'deflate', 'compress', and '' (no
|
||||
* encoding)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function __construct($spec)
|
||||
{
|
||||
$this->_content = $spec['content'];
|
||||
$this->_headers['Content-Length'] = (string)strlen($this->_content);
|
||||
if (isset($spec['type'])) {
|
||||
$this->_headers['Content-Type'] = $spec['type'];
|
||||
}
|
||||
if (isset($spec['method'])
|
||||
&& in_array($spec['method'], array('gzip', 'deflate', 'compress', '')))
|
||||
{
|
||||
$this->_encodeMethod = array($spec['method'], $spec['method']);
|
||||
} else {
|
||||
$this->_encodeMethod = self::getAcceptedEncoding();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content in current form
|
||||
*
|
||||
* Call after encode() for encoded content.
|
||||
*
|
||||
* return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of output headers to be sent
|
||||
*
|
||||
* E.g.
|
||||
* <code>
|
||||
* array(
|
||||
* 'Content-Length' => '615'
|
||||
* ,'Content-Encoding' => 'x-gzip'
|
||||
* ,'Vary' => 'Accept-Encoding'
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->_headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send output headers
|
||||
*
|
||||
* You must call this before headers are sent and it probably cannot be
|
||||
* used in conjunction with zlib output buffering / mod_gzip. Errors are
|
||||
* not handled purposefully.
|
||||
*
|
||||
* @see getHeaders()
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function sendHeaders()
|
||||
{
|
||||
foreach ($this->_headers as $name => $val) {
|
||||
header($name . ': ' . $val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send output headers and content
|
||||
*
|
||||
* A shortcut for sendHeaders() and echo getContent()
|
||||
*
|
||||
* You must call this before headers are sent and it probably cannot be
|
||||
* used in conjunction with zlib output buffering / mod_gzip. Errors are
|
||||
* not handled purposefully.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function sendAll()
|
||||
{
|
||||
$this->sendHeaders();
|
||||
echo $this->_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the client's best encoding method from the HTTP Accept-Encoding
|
||||
* header.
|
||||
*
|
||||
* If no Accept-Encoding header is set, or the browser is IE before v6 SP2,
|
||||
* this will return ('', ''), the "identity" encoding.
|
||||
*
|
||||
* A syntax-aware scan is done of the Accept-Encoding, so the method must
|
||||
* be non 0. The methods are favored in order of gzip, deflate, then
|
||||
* compress. Deflate is always smallest and generally faster, but is
|
||||
* rarely sent by servers, so client support could be buggier.
|
||||
*
|
||||
* @param bool $allowCompress allow the older compress encoding
|
||||
*
|
||||
* @param bool $allowDeflate allow the more recent deflate encoding
|
||||
*
|
||||
* @return array two values, 1st is the actual encoding method, 2nd is the
|
||||
* alias of that method to use in the Content-Encoding header (some browsers
|
||||
* call gzip "x-gzip" etc.)
|
||||
*/
|
||||
public static function getAcceptedEncoding($allowCompress = true, $allowDeflate = true)
|
||||
{
|
||||
// @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
||||
|
||||
if (! isset($_SERVER['HTTP_ACCEPT_ENCODING'])
|
||||
|| self::_isBuggyIe())
|
||||
{
|
||||
return array('', '');
|
||||
}
|
||||
$ae = $_SERVER['HTTP_ACCEPT_ENCODING'];
|
||||
// gzip checks (quick)
|
||||
if (0 === strpos($ae, 'gzip,') // most browsers
|
||||
|| 0 === strpos($ae, 'deflate, gzip,') // opera
|
||||
) {
|
||||
return array('gzip', 'gzip');
|
||||
}
|
||||
// gzip checks (slow)
|
||||
if (preg_match(
|
||||
'@(?:^|,)\\s*((?:x-)?gzip)\\s*(?:$|,|;\\s*q=(?:0\\.|1))@'
|
||||
,$ae
|
||||
,$m)) {
|
||||
return array('gzip', $m[1]);
|
||||
}
|
||||
if ($allowDeflate) {
|
||||
// deflate checks
|
||||
$aeRev = strrev($ae);
|
||||
if (0 === strpos($aeRev, 'etalfed ,') // ie, webkit
|
||||
|| 0 === strpos($aeRev, 'etalfed,') // gecko
|
||||
|| 0 === strpos($ae, 'deflate,') // opera
|
||||
// slow parsing
|
||||
|| preg_match(
|
||||
'@(?:^|,)\\s*deflate\\s*(?:$|,|;\\s*q=(?:0\\.|1))@', $ae)) {
|
||||
return array('deflate', 'deflate');
|
||||
}
|
||||
}
|
||||
if ($allowCompress && preg_match(
|
||||
'@(?:^|,)\\s*((?:x-)?compress)\\s*(?:$|,|;\\s*q=(?:0\\.|1))@'
|
||||
,$ae
|
||||
,$m)) {
|
||||
return array('compress', $m[1]);
|
||||
}
|
||||
return array('', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode (compress) the content
|
||||
*
|
||||
* If the encode method is '' (none) or compression level is 0, or the 'zlib'
|
||||
* extension isn't loaded, we return false.
|
||||
*
|
||||
* Then the appropriate gz_* function is called to compress the content. If
|
||||
* this fails, false is returned.
|
||||
*
|
||||
* The header "Vary: Accept-Encoding" is added. If encoding is successful,
|
||||
* the Content-Length header is updated, and Content-Encoding is also added.
|
||||
*
|
||||
* @param int $compressionLevel given to zlib functions. If not given, the
|
||||
* class default will be used.
|
||||
*
|
||||
* @return bool success true if the content was actually compressed
|
||||
*/
|
||||
public function encode($compressionLevel = null)
|
||||
{
|
||||
$this->_headers['Vary'] = 'Accept-Encoding';
|
||||
if (null === $compressionLevel) {
|
||||
$compressionLevel = self::$compressionLevel;
|
||||
}
|
||||
if ('' === $this->_encodeMethod[0]
|
||||
|| ($compressionLevel == 0)
|
||||
|| !extension_loaded('zlib'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ($this->_encodeMethod[0] === 'deflate') {
|
||||
$encoded = gzdeflate($this->_content, $compressionLevel);
|
||||
} elseif ($this->_encodeMethod[0] === 'gzip') {
|
||||
$encoded = gzencode($this->_content, $compressionLevel);
|
||||
} else {
|
||||
$encoded = gzcompress($this->_content, $compressionLevel);
|
||||
}
|
||||
if (false === $encoded) {
|
||||
return false;
|
||||
}
|
||||
$this->_headers['Content-Length'] = strlen($encoded);
|
||||
$this->_headers['Content-Encoding'] = $this->_encodeMethod[1];
|
||||
$this->_content = $encoded;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode and send appropriate headers and content
|
||||
*
|
||||
* This is a convenience method for common use of the class
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
* @param int $compressionLevel given to zlib functions. If not given, the
|
||||
* class default will be used.
|
||||
*
|
||||
* @return bool success true if the content was actually compressed
|
||||
*/
|
||||
public static function output($content, $compressionLevel = null)
|
||||
{
|
||||
if (null === $compressionLevel) {
|
||||
$compressionLevel = self::$compressionLevel;
|
||||
}
|
||||
$he = new HTTP_Encoder(array('content' => $content));
|
||||
$ret = $he->encode($compressionLevel);
|
||||
$he->sendAll();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
protected $_content = '';
|
||||
protected $_headers = array();
|
||||
protected $_encodeMethod = array('', '');
|
||||
|
||||
/**
|
||||
* Is the browser an IE version earlier than 6 SP2?
|
||||
*/
|
||||
protected static function _isBuggyIe()
|
||||
{
|
||||
$ua = $_SERVER['HTTP_USER_AGENT'];
|
||||
// quick escape for non-IEs
|
||||
if (0 !== strpos($ua, 'Mozilla/4.0 (compatible; MSIE ')
|
||||
|| false !== strpos($ua, 'Opera')) {
|
||||
return false;
|
||||
}
|
||||
// no regex = faaast
|
||||
$version = (float)substr($ua, 30);
|
||||
return self::$encodeToIe6
|
||||
? ($version < 6 || ($version == 6 && false === strpos($ua, 'SV1')))
|
||||
: ($version < 7);
|
||||
}
|
||||
}
|
@@ -1,314 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* jsmin.php - PHP implementation of Douglas Crockford's JSMin.
|
||||
*
|
||||
* This is a direct port of jsmin.c to PHP with a few PHP performance tweaks and
|
||||
* modifications to preserve some comments (see below). Also, rather than using
|
||||
* stdin/stdout, JSMin::minify() accepts a string as input and returns another
|
||||
* string as output.
|
||||
*
|
||||
* Comments containing IE conditional compilation are preserved, as are multi-line
|
||||
* comments that begin with "/*!" (for documentation purposes). In the latter case
|
||||
* newlines are inserted around the comment to enhance readability.
|
||||
*
|
||||
* PHP 5 or higher is required.
|
||||
*
|
||||
* Permission is hereby granted to use this version of the library under the
|
||||
* same terms as jsmin.c, which has the following license:
|
||||
*
|
||||
* --
|
||||
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* The Software shall be used for Good, not Evil.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
* --
|
||||
*
|
||||
* @package JSMin
|
||||
* @author Ryan Grove <ryan@wonko.com> (PHP port)
|
||||
* @author Steve Clay <steve@mrclay.org> (modifications + cleanup)
|
||||
* @author Andrea Giammarchi <http://www.3site.eu> (spaceBeforeRegExp)
|
||||
* @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
|
||||
* @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://code.google.com/p/jsmin-php/
|
||||
*/
|
||||
|
||||
class JSMin {
|
||||
const ORD_LF = 10;
|
||||
const ORD_SPACE = 32;
|
||||
const ACTION_KEEP_A = 1;
|
||||
const ACTION_DELETE_A = 2;
|
||||
const ACTION_DELETE_A_B = 3;
|
||||
|
||||
protected $a = "\n";
|
||||
protected $b = '';
|
||||
protected $input = '';
|
||||
protected $inputIndex = 0;
|
||||
protected $inputLength = 0;
|
||||
protected $lookAhead = null;
|
||||
protected $output = '';
|
||||
|
||||
/**
|
||||
* Minify Javascript
|
||||
*
|
||||
* @param string $js Javascript to be minified
|
||||
* @return string
|
||||
*/
|
||||
public static function minify($js)
|
||||
{
|
||||
$jsmin = new JSMin($js);
|
||||
return $jsmin->min();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup process
|
||||
*/
|
||||
public function __construct($input)
|
||||
{
|
||||
$this->input = str_replace("\r\n", "\n", $input);
|
||||
$this->inputLength = strlen($this->input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform minification, return result
|
||||
*/
|
||||
public function min()
|
||||
{
|
||||
if ($this->output !== '') { // min already run
|
||||
return $this->output;
|
||||
}
|
||||
$this->action(self::ACTION_DELETE_A_B);
|
||||
|
||||
while ($this->a !== null) {
|
||||
// determine next command
|
||||
$command = self::ACTION_KEEP_A; // default
|
||||
if ($this->a === ' ') {
|
||||
if (! $this->isAlphaNum($this->b)) {
|
||||
$command = self::ACTION_DELETE_A;
|
||||
}
|
||||
} elseif ($this->a === "\n") {
|
||||
if ($this->b === ' ') {
|
||||
$command = self::ACTION_DELETE_A_B;
|
||||
} elseif (false === strpos('{[(+-', $this->b)
|
||||
&& ! $this->isAlphaNum($this->b)) {
|
||||
$command = self::ACTION_DELETE_A;
|
||||
}
|
||||
} elseif (! $this->isAlphaNum($this->a)) {
|
||||
if ($this->b === ' '
|
||||
|| ($this->b === "\n"
|
||||
&& (false === strpos('}])+-"\'', $this->a)))) {
|
||||
$command = self::ACTION_DELETE_A_B;
|
||||
}
|
||||
}
|
||||
$this->action($command);
|
||||
}
|
||||
$this->output = trim($this->output);
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* ACTION_KEEP_A = Output A. Copy B to A. Get the next B.
|
||||
* ACTION_DELETE_A = Copy B to A. Get the next B.
|
||||
* ACTION_DELETE_A_B = Get the next B.
|
||||
*/
|
||||
protected function action($command)
|
||||
{
|
||||
switch ($command) {
|
||||
case self::ACTION_KEEP_A:
|
||||
$this->output .= $this->a;
|
||||
// fallthrough
|
||||
case self::ACTION_DELETE_A:
|
||||
$this->a = $this->b;
|
||||
if ($this->a === "'" || $this->a === '"') { // string literal
|
||||
$str = $this->a; // in case needed for exception
|
||||
while (true) {
|
||||
$this->output .= $this->a;
|
||||
$this->a = $this->get();
|
||||
if ($this->a === $this->b) { // end quote
|
||||
break;
|
||||
}
|
||||
if (ord($this->a) <= self::ORD_LF) {
|
||||
throw new JSMin_UnterminatedStringException(
|
||||
'Unterminated String: ' . var_export($str, true));
|
||||
}
|
||||
$str .= $this->a;
|
||||
if ($this->a === '\\') {
|
||||
$this->output .= $this->a;
|
||||
$this->a = $this->get();
|
||||
$str .= $this->a;
|
||||
}
|
||||
}
|
||||
}
|
||||
// fallthrough
|
||||
case self::ACTION_DELETE_A_B:
|
||||
$this->b = $this->next();
|
||||
if ($this->b === '/' && $this->isRegexpLiteral()) { // RegExp literal
|
||||
$this->output .= $this->a . $this->b;
|
||||
$pattern = '/'; // in case needed for exception
|
||||
while (true) {
|
||||
$this->a = $this->get();
|
||||
$pattern .= $this->a;
|
||||
if ($this->a === '/') { // end pattern
|
||||
break; // while (true)
|
||||
} elseif ($this->a === '\\') {
|
||||
$this->output .= $this->a;
|
||||
$this->a = $this->get();
|
||||
$pattern .= $this->a;
|
||||
} elseif (ord($this->a) <= self::ORD_LF) {
|
||||
throw new JSMin_UnterminatedRegExpException(
|
||||
'Unterminated RegExp: '. var_export($pattern, true));
|
||||
}
|
||||
$this->output .= $this->a;
|
||||
}
|
||||
$this->b = $this->next();
|
||||
}
|
||||
// end case ACTION_DELETE_A_B
|
||||
}
|
||||
}
|
||||
|
||||
protected function isRegexpLiteral()
|
||||
{
|
||||
if (false !== strpos("\n{;(,=:[!&|?", $this->a)) { // we aren't dividing
|
||||
return true;
|
||||
}
|
||||
if (' ' === $this->a) {
|
||||
$length = strlen($this->output);
|
||||
if ($length < 2) { // weird edge case
|
||||
return true;
|
||||
}
|
||||
// you can't divide a keyword
|
||||
if (preg_match('/(?:case|else|in|return|typeof)$/', $this->output, $m)) {
|
||||
if ($this->output === $m[0]) { // odd but could happen
|
||||
return true;
|
||||
}
|
||||
// make sure it's a keyword, not end of an identifier
|
||||
$charBeforeKeyword = substr($this->output, $length - strlen($m[0]) - 1, 1);
|
||||
if (! $this->isAlphaNum($charBeforeKeyword)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next char. Convert ctrl char to space.
|
||||
*/
|
||||
protected function get()
|
||||
{
|
||||
$c = $this->lookAhead;
|
||||
$this->lookAhead = null;
|
||||
if ($c === null) {
|
||||
if ($this->inputIndex < $this->inputLength) {
|
||||
$c = $this->input[$this->inputIndex];
|
||||
$this->inputIndex += 1;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if ($c === "\r" || $c === "\n") {
|
||||
return "\n";
|
||||
}
|
||||
if (ord($c) < self::ORD_SPACE) { // control char
|
||||
return ' ';
|
||||
}
|
||||
return $c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next char. If is ctrl character, translate to a space or newline.
|
||||
*/
|
||||
protected function peek()
|
||||
{
|
||||
$this->lookAhead = $this->get();
|
||||
return $this->lookAhead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is $c a letter, digit, underscore, dollar sign, escape, or non-ASCII?
|
||||
*/
|
||||
protected function isAlphaNum($c)
|
||||
{
|
||||
return (preg_match('/^[0-9a-zA-Z_\\$\\\\]$/', $c) || ord($c) > 126);
|
||||
}
|
||||
|
||||
protected function singleLineComment()
|
||||
{
|
||||
$comment = '';
|
||||
while (true) {
|
||||
$get = $this->get();
|
||||
$comment .= $get;
|
||||
if (ord($get) <= self::ORD_LF) { // EOL reached
|
||||
// if IE conditional comment
|
||||
if (preg_match('/^\\/@(?:cc_on|if|elif|else|end)\\b/', $comment)) {
|
||||
return "/{$comment}";
|
||||
}
|
||||
return $get;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function multipleLineComment()
|
||||
{
|
||||
$this->get();
|
||||
$comment = '';
|
||||
while (true) {
|
||||
$get = $this->get();
|
||||
if ($get === '*') {
|
||||
if ($this->peek() === '/') { // end of comment reached
|
||||
$this->get();
|
||||
// if comment preserved by YUI Compressor
|
||||
if (0 === strpos($comment, '!')) {
|
||||
return "\n/*" . substr($comment, 1) . "*/\n";
|
||||
}
|
||||
// if IE conditional comment
|
||||
if (preg_match('/^@(?:cc_on|if|elif|else|end)\\b/', $comment)) {
|
||||
return "/*{$comment}*/";
|
||||
}
|
||||
return ' ';
|
||||
}
|
||||
} elseif ($get === null) {
|
||||
throw new JSMin_UnterminatedCommentException('Unterminated Comment: ' . var_export('/*' . $comment, true));
|
||||
}
|
||||
$comment .= $get;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next character, skipping over comments.
|
||||
* Some comments may be preserved.
|
||||
*/
|
||||
protected function next()
|
||||
{
|
||||
$get = $this->get();
|
||||
if ($get !== '/') {
|
||||
return $get;
|
||||
}
|
||||
switch ($this->peek()) {
|
||||
case '/': return $this->singleLineComment();
|
||||
case '*': return $this->multipleLineComment();
|
||||
default: return $get;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JSMin_UnterminatedStringException extends Exception {}
|
||||
class JSMin_UnterminatedCommentException extends Exception {}
|
||||
class JSMin_UnterminatedRegExpException extends Exception {}
|
File diff suppressed because it is too large
Load Diff
@@ -1,519 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Minify - Combines, minifies, and caches JavaScript and CSS files on demand.
|
||||
*
|
||||
* See README for usage instructions (for now).
|
||||
*
|
||||
* This library was inspired by {@link mailto:flashkot@mail.ru jscsscomp by Maxim Martynyuk}
|
||||
* and by the article {@link http://www.hunlock.com/blogs/Supercharged_Javascript "Supercharged JavaScript" by Patrick Hunlock}.
|
||||
*
|
||||
* Requires PHP 5.1.0.
|
||||
* Tested on PHP 5.1.6.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Ryan Grove <ryan@wonko.com>
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
* @copyright 2008 Ryan Grove, Stephen Clay. All rights reserved.
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @link http://code.google.com/p/minify/
|
||||
*/
|
||||
class Minify {
|
||||
|
||||
const VERSION = '2.1.3';
|
||||
const TYPE_CSS = 'text/css';
|
||||
const TYPE_HTML = 'text/html';
|
||||
// there is some debate over the ideal JS Content-Type, but this is the
|
||||
// Apache default and what Yahoo! uses..
|
||||
const TYPE_JS = 'application/x-javascript';
|
||||
|
||||
/**
|
||||
* How many hours behind are the file modification times of uploaded files?
|
||||
*
|
||||
* If you upload files from Windows to a non-Windows server, Windows may report
|
||||
* incorrect mtimes for the files. Immediately after modifying and uploading a
|
||||
* file, use the touch command to update the mtime on the server. If the mtime
|
||||
* jumps ahead by a number of hours, set this variable to that number. If the mtime
|
||||
* moves back, this should not be needed.
|
||||
*
|
||||
* @var int $uploaderHoursBehind
|
||||
*/
|
||||
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 */\n";
|
||||
|
||||
/**
|
||||
* Specify a cache object (with identical interface as Minify_Cache_File) or
|
||||
* a path to use with Minify_Cache_File.
|
||||
*
|
||||
* If not called, Minify will not use a cache and, for each 200 response, will
|
||||
* need to recombine files, minify and encode the output.
|
||||
*
|
||||
* @param mixed $cache object with identical interface as Minify_Cache_File or
|
||||
* a directory path, or null to disable caching. (default = '')
|
||||
*
|
||||
* @param bool $fileLocking (default = true) This only applies if the first
|
||||
* parameter is a string.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public static function setCache($cache = '', $fileLocking = true)
|
||||
{
|
||||
if (is_string($cache)) {
|
||||
self::$_cache = new Minify_Cache_File($cache, $fileLocking);
|
||||
} else {
|
||||
self::$_cache = $cache;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve a request for a minified file.
|
||||
*
|
||||
* Here are the available options and defaults in the base controller:
|
||||
*
|
||||
* 'isPublic' : send "public" instead of "private" in Cache-Control
|
||||
* headers, allowing shared caches to cache the output. (default true)
|
||||
*
|
||||
* 'quiet' : set to true to have serve() return an array rather than sending
|
||||
* any headers/output (default false)
|
||||
*
|
||||
* 'encodeOutput' : set to false to disable content encoding, and not send
|
||||
* the Vary header (default true)
|
||||
*
|
||||
* 'encodeMethod' : generally you should let this be determined by
|
||||
* HTTP_Encoder (leave null), but you can force a particular encoding
|
||||
* to be returned, by setting this to 'gzip' or '' (no encoding)
|
||||
*
|
||||
* 'encodeLevel' : level of encoding compression (0 to 9, default 9)
|
||||
*
|
||||
* 'contentTypeCharset' : appended to the Content-Type header sent. Set to a falsey
|
||||
* value to remove. (default 'utf-8')
|
||||
*
|
||||
* 'maxAge' : set this to the number of seconds the client should use its cache
|
||||
* before revalidating with the server. This sets Cache-Control: max-age and the
|
||||
* Expires header. Unlike the old 'setExpires' setting, this setting will NOT
|
||||
* prevent conditional GETs. Note this has nothing to do with server-side caching.
|
||||
*
|
||||
* '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()
|
||||
*
|
||||
* 'minifiers' : to override Minify's default choice of minifier function for
|
||||
* a particular content-type, specify your callback under the key of the
|
||||
* content-type:
|
||||
* <code>
|
||||
* // call customCssMinifier($css) for all CSS minification
|
||||
* $options['minifiers'][Minify::TYPE_CSS] = 'customCssMinifier';
|
||||
*
|
||||
* // don't minify Javascript at all
|
||||
* $options['minifiers'][Minify::TYPE_JS] = '';
|
||||
* </code>
|
||||
*
|
||||
* 'minifierOptions' : to send options to the minifier function, specify your options
|
||||
* under the key of the content-type. E.g. To send the CSS minifier an option:
|
||||
* <code>
|
||||
* // give CSS minifier array('optionName' => 'optionValue') as 2nd argument
|
||||
* $options['minifierOptions'][Minify::TYPE_CSS]['optionName'] = 'optionValue';
|
||||
* </code>
|
||||
*
|
||||
* 'contentType' : (optional) this is only needed if your file extension is not
|
||||
* js/css/html. The given content-type will be sent regardless of source file
|
||||
* extension, so this should not be used in a Groups config with other
|
||||
* Javascript/CSS files.
|
||||
*
|
||||
* Any controller options are documented in that controller's setupSources() method.
|
||||
*
|
||||
* @param mixed instance of subclass of Minify_Controller_Base or string name of
|
||||
* controller. E.g. 'Files'
|
||||
*
|
||||
* @param array $options controller/serve options
|
||||
*
|
||||
* @return mixed null, or, if the 'quiet' option is set to true, an array
|
||||
* with keys "success" (bool), "statusCode" (int), "content" (string), and
|
||||
* "headers" (array).
|
||||
*/
|
||||
public static function serve($controller, $options = array())
|
||||
{
|
||||
if (is_string($controller)) {
|
||||
// make $controller into object
|
||||
$class = 'Minify_Controller_' . $controller;
|
||||
$controller = new $class();
|
||||
}
|
||||
|
||||
// set up controller sources and mix remaining options with
|
||||
// controller defaults
|
||||
$options = $controller->setupSources($options);
|
||||
$options = $controller->analyzeSources($options);
|
||||
self::$_options = $controller->mixInDefaultOptions($options);
|
||||
|
||||
// check request validity
|
||||
if (! $controller->sources) {
|
||||
// invalid request!
|
||||
if (! self::$_options['quiet']) {
|
||||
header(self::$_options['badRequestHeader']);
|
||||
echo self::$_options['badRequestHeader'];
|
||||
return;
|
||||
} else {
|
||||
list(,$statusCode) = explode(' ', self::$_options['badRequestHeader']);
|
||||
return array(
|
||||
'success' => false
|
||||
,'statusCode' => (int)$statusCode
|
||||
,'content' => ''
|
||||
,'headers' => array()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self::$_controller = $controller;
|
||||
|
||||
if (self::$_options['debug']) {
|
||||
self::_setupDebug($controller->sources);
|
||||
self::$_options['maxAge'] = 0;
|
||||
}
|
||||
|
||||
// determine encoding
|
||||
if (self::$_options['encodeOutput']) {
|
||||
if (self::$_options['encodeMethod'] !== null) {
|
||||
// controller specifically requested this
|
||||
$contentEncoding = self::$_options['encodeMethod'];
|
||||
} else {
|
||||
// sniff request header
|
||||
// depending on what the client accepts, $contentEncoding may be
|
||||
// 'x-gzip' while our internal encodeMethod is 'gzip'. Calling
|
||||
// getAcceptedEncoding(false, false) leaves out compress and deflate as options.
|
||||
list(self::$_options['encodeMethod'], $contentEncoding) = HTTP_Encoder::getAcceptedEncoding(false, false);
|
||||
}
|
||||
} else {
|
||||
self::$_options['encodeMethod'] = ''; // identity (no encoding)
|
||||
}
|
||||
|
||||
// check client cache
|
||||
$cgOptions = array(
|
||||
'lastModifiedTime' => self::$_options['lastModifiedTime']
|
||||
,'isPublic' => self::$_options['isPublic']
|
||||
,'encoding' => self::$_options['encodeMethod']
|
||||
);
|
||||
if (self::$_options['maxAge'] > 0) {
|
||||
$cgOptions['maxAge'] = self::$_options['maxAge'];
|
||||
}
|
||||
$cg = new HTTP_ConditionalGet($cgOptions);
|
||||
if ($cg->cacheIsValid) {
|
||||
// client's cache is valid
|
||||
if (! self::$_options['quiet']) {
|
||||
$cg->sendHeaders();
|
||||
return;
|
||||
} else {
|
||||
return array(
|
||||
'success' => true
|
||||
,'statusCode' => 304
|
||||
,'content' => ''
|
||||
,'headers' => $cg->getHeaders()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// client will need output
|
||||
$headers = $cg->getHeaders();
|
||||
unset($cg);
|
||||
}
|
||||
|
||||
if (self::$_options['contentType'] === self::TYPE_CSS
|
||||
&& self::$_options['rewriteCssUris']) {
|
||||
reset($controller->sources);
|
||||
while (list($key, $source) = each($controller->sources)) {
|
||||
if ($source->filepath
|
||||
&& !isset($source->minifyOptions['currentDir'])
|
||||
&& !isset($source->minifyOptions['prependRelativePath'])
|
||||
) {
|
||||
$source->minifyOptions['currentDir'] = dirname($source->filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check server cache
|
||||
if (null !== self::$_cache) {
|
||||
// using cache
|
||||
// the goal is to use only the cache methods to sniff the length and
|
||||
// output the content, as they do not require ever loading the file into
|
||||
// memory.
|
||||
$cacheId = 'minify_' . self::_getCacheId();
|
||||
$fullCacheId = (self::$_options['encodeMethod'])
|
||||
? $cacheId . '.gz'
|
||||
: $cacheId;
|
||||
// check cache for valid entry
|
||||
$cacheIsReady = self::$_cache->isValid($fullCacheId, self::$_options['lastModifiedTime']);
|
||||
if ($cacheIsReady) {
|
||||
$cacheContentLength = self::$_cache->getSize($fullCacheId);
|
||||
} else {
|
||||
// generate & cache content
|
||||
$content = self::_combineMinify();
|
||||
self::$_cache->store($cacheId, $content);
|
||||
if (function_exists('gzencode')) {
|
||||
self::$_cache->store($cacheId . '.gz', gzencode($content, self::$_options['encodeLevel']));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no cache
|
||||
$cacheIsReady = false;
|
||||
$content = self::_combineMinify();
|
||||
}
|
||||
if (! $cacheIsReady && self::$_options['encodeMethod']) {
|
||||
// still need to encode
|
||||
$content = gzencode($content, self::$_options['encodeLevel']);
|
||||
}
|
||||
|
||||
// add headers
|
||||
$headers['Content-Length'] = $cacheIsReady
|
||||
? $cacheContentLength
|
||||
: strlen($content);
|
||||
$headers['Content-Type'] = self::$_options['contentTypeCharset']
|
||||
? self::$_options['contentType'] . '; charset=' . self::$_options['contentTypeCharset']
|
||||
: self::$_options['contentType'];
|
||||
if (self::$_options['encodeMethod'] !== '') {
|
||||
$headers['Content-Encoding'] = $contentEncoding;
|
||||
}
|
||||
if (self::$_options['encodeOutput']) {
|
||||
$headers['Vary'] = 'Accept-Encoding';
|
||||
}
|
||||
|
||||
if (! self::$_options['quiet']) {
|
||||
// output headers & content
|
||||
foreach ($headers as $name => $val) {
|
||||
header($name . ': ' . $val);
|
||||
}
|
||||
if ($cacheIsReady) {
|
||||
self::$_cache->display($fullCacheId);
|
||||
} else {
|
||||
echo $content;
|
||||
}
|
||||
} else {
|
||||
return array(
|
||||
'success' => true
|
||||
,'statusCode' => 200
|
||||
,'content' => $cacheIsReady
|
||||
? self::$_cache->fetch($fullCacheId)
|
||||
: $content
|
||||
,'headers' => $headers
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return combined minified content for a set of sources
|
||||
*
|
||||
* No internal caching will be used and the content will not be HTTP encoded.
|
||||
*
|
||||
* @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, $options = array())
|
||||
{
|
||||
$cache = self::$_cache;
|
||||
self::$_cache = null;
|
||||
$options = array_merge(array(
|
||||
'files' => (array)$sources
|
||||
,'quiet' => true
|
||||
,'encodeMethod' => ''
|
||||
,'lastModifiedTime' => 0
|
||||
), $options);
|
||||
$out = self::serve('Files', $options);
|
||||
self::$_cache = $cache;
|
||||
return $out['content'];
|
||||
}
|
||||
|
||||
/**
|
||||
* On IIS, create $_SERVER['DOCUMENT_ROOT']
|
||||
*
|
||||
* @param bool $unsetPathInfo (default false) if true, $_SERVER['PATH_INFO']
|
||||
* will be unset (it is inconsistent with Apache's setting)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public static function setDocRoot($unsetPathInfo = false)
|
||||
{
|
||||
if (isset($_SERVER['SERVER_SOFTWARE'])
|
||||
&& 0 === strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/')
|
||||
) {
|
||||
$_SERVER['DOCUMENT_ROOT'] = rtrim(substr(
|
||||
$_SERVER['PATH_TRANSLATED']
|
||||
,0
|
||||
,strlen($_SERVER['PATH_TRANSLATED']) - strlen($_SERVER['SCRIPT_NAME'])
|
||||
), '\\');
|
||||
if ($unsetPathInfo) {
|
||||
unset($_SERVER['PATH_INFO']);
|
||||
}
|
||||
Minify_Logger::log("setDocRoot() set DOCUMENT_ROOT to \"{$_SERVER['DOCUMENT_ROOT']}\"");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @var mixed Minify_Cache_* object or null (i.e. no server cache is used)
|
||||
*/
|
||||
private static $_cache = null;
|
||||
|
||||
/**
|
||||
* @var Minify_Controller active controller for current request
|
||||
*/
|
||||
protected static $_controller = null;
|
||||
|
||||
/**
|
||||
* @var array options for current request
|
||||
*/
|
||||
protected static $_options = null;
|
||||
|
||||
/**
|
||||
* Set up sources to use Minify_Lines
|
||||
*
|
||||
* @param array $sources Minify_Source instances
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
protected static function _setupDebug($sources)
|
||||
{
|
||||
foreach ($sources as $source) {
|
||||
$source->minifier = array('Minify_Lines', 'minify');
|
||||
$id = $source->getId();
|
||||
$source->minifyOptions = array(
|
||||
'id' => (is_file($id) ? basename($id) : $id)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines sources and minifies the result.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function _combineMinify()
|
||||
{
|
||||
$type = self::$_options['contentType']; // ease readability
|
||||
|
||||
// when combining scripts, make sure all statements separated and
|
||||
// trailing single line comment is terminated
|
||||
$implodeSeparator = ($type === self::TYPE_JS)
|
||||
? "\n;"
|
||||
: '';
|
||||
// allow the user to pass a particular array of options to each
|
||||
// minifier (designated by type). source objects may still override
|
||||
// these
|
||||
$defaultOptions = isset(self::$_options['minifierOptions'][$type])
|
||||
? self::$_options['minifierOptions'][$type]
|
||||
: array();
|
||||
// if minifier not set, default is no minification. source objects
|
||||
// may still override this
|
||||
$defaultMinifier = isset(self::$_options['minifiers'][$type])
|
||||
? self::$_options['minifiers'][$type]
|
||||
: false;
|
||||
|
||||
if (Minify_Source::haveNoMinifyPrefs(self::$_controller->sources)) {
|
||||
// all source have same options/minifier, better performance
|
||||
// to combine, then minify once
|
||||
foreach (self::$_controller->sources as $source) {
|
||||
$pieces[] = $source->getContent();
|
||||
}
|
||||
$content = implode($implodeSeparator, $pieces);
|
||||
if ($defaultMinifier) {
|
||||
self::$_controller->loadMinifier($defaultMinifier);
|
||||
$content = call_user_func($defaultMinifier, $content, $defaultOptions);
|
||||
}
|
||||
} else {
|
||||
// minify each source with its own options and minifier, then combine
|
||||
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
|
||||
$pieces[] = call_user_func($minifier, $source->getContent(), $options);
|
||||
} else {
|
||||
$pieces[] = $source->getContent();
|
||||
}
|
||||
}
|
||||
$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'];
|
||||
}
|
||||
if (self::$_options['postprocessor']) {
|
||||
$content = call_user_func(self::$_options['postprocessor'], $content, $type);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a unique cache id for for this request.
|
||||
*
|
||||
* Any settings that could affect output are taken into consideration
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function _getCacheId()
|
||||
{
|
||||
return md5(serialize(array(
|
||||
Minify_Source::getDigest(self::$_controller->sources)
|
||||
,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;
|
||||
}
|
||||
}
|
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Build
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
require_once 'Minify/Source.php';
|
||||
|
||||
/**
|
||||
* Maintain a single last modification time for a group of Minify sources to
|
||||
* allow use of far off Expires headers in Minify.
|
||||
*
|
||||
* <code>
|
||||
* // in config file
|
||||
* $groupSources = array(
|
||||
* 'js' => array('file1.js', 'file2.js')
|
||||
* ,'css' => array('file1.css', 'file2.css', 'file3.css')
|
||||
* )
|
||||
*
|
||||
* // during HTML generation
|
||||
* $jsBuild = new Minify_Build($groupSources['js']);
|
||||
* $cssBuild = new Minify_Build($groupSources['css']);
|
||||
*
|
||||
* $script = "<script type='text/javascript' src='"
|
||||
* . $jsBuild->uri('/min.php/js') . "'></script>";
|
||||
* $link = "<link rel='stylesheet' type='text/css' href='"
|
||||
* . $cssBuild->uri('/min.php/css') . "'>";
|
||||
*
|
||||
* // in min.php
|
||||
* Minify::serve('Groups', array(
|
||||
* 'groups' => $groupSources
|
||||
* ,'setExpires' => (time() + 86400 * 365)
|
||||
* ));
|
||||
* </code>
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_Build {
|
||||
|
||||
/**
|
||||
* Last modification time of all files in the build
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $lastModified = 0;
|
||||
|
||||
/**
|
||||
* String to use as ampersand in uri(). Set this to '&' if
|
||||
* you are not HTML-escaping URIs.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $ampersand = '&';
|
||||
|
||||
/**
|
||||
* Get a time-stamped URI
|
||||
*
|
||||
* <code>
|
||||
* echo $b->uri('/site.js');
|
||||
* // outputs "/site.js?1678242"
|
||||
*
|
||||
* echo $b->uri('/scriptaculous.js?load=effects');
|
||||
* // outputs "/scriptaculous.js?load=effects&1678242"
|
||||
* </code>
|
||||
*
|
||||
* @param string $uri
|
||||
* @param boolean $forceAmpersand (default = false) Force the use of ampersand to
|
||||
* append the timestamp to the URI.
|
||||
* @return string
|
||||
*/
|
||||
public function uri($uri, $forceAmpersand = false) {
|
||||
$sep = ($forceAmpersand || strpos($uri, '?') !== false)
|
||||
? self::$ampersand
|
||||
: '?';
|
||||
return "{$uri}{$sep}{$this->lastModified}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a build object
|
||||
*
|
||||
* @param array $sources array of Minify_Source objects and/or file paths
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function __construct($sources)
|
||||
{
|
||||
$max = 0;
|
||||
foreach ((array)$sources as $source) {
|
||||
if ($source instanceof Minify_Source) {
|
||||
$max = max($max, $source->lastModified);
|
||||
} elseif (is_string($source)) {
|
||||
if (0 === strpos($source, '//')) {
|
||||
$source = $_SERVER['DOCUMENT_ROOT'] . substr($source, 1);
|
||||
}
|
||||
if (is_file($source)) {
|
||||
$max = max($max, filemtime($source));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->lastModified = $max;
|
||||
}
|
||||
}
|
@@ -1,80 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_CSS
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Minify CSS
|
||||
*
|
||||
* This class uses Minify_CSS_Compressor and Minify_CSS_UriRewriter to
|
||||
* minify CSS and rewrite relative URIs.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
|
||||
*/
|
||||
class Minify_CSS {
|
||||
|
||||
/**
|
||||
* Minify a CSS string
|
||||
*
|
||||
* @param string $css
|
||||
*
|
||||
* @param array $options available options:
|
||||
*
|
||||
* 'preserveComments': (default true) multi-line comments that begin
|
||||
* with "/*!" will be preserved with newlines before and after to
|
||||
* enhance readability.
|
||||
*
|
||||
* 'prependRelativePath': (default null) if given, this string will be
|
||||
* prepended to all relative URIs in import/url declarations
|
||||
*
|
||||
* 'currentDir': (default null) if given, this is assumed to be the
|
||||
* directory of the current CSS file. Using this, minify will rewrite
|
||||
* all relative URIs in import/url declarations to correctly point to
|
||||
* the desired files. For this to work, the files *must* exist and be
|
||||
* visible by the PHP process.
|
||||
*
|
||||
* 'symlinks': (default = array()) If the CSS file is stored in
|
||||
* a symlink-ed directory, provide an array of link paths to
|
||||
* target paths, where the link paths are within the document root. Because
|
||||
* paths need to be normalized for this to work, use "//" to substitute
|
||||
* the doc root in the link paths (the array keys). E.g.:
|
||||
* <code>
|
||||
* array('//symlink' => '/real/target/path') // unix
|
||||
* array('//static' => 'D:\\staticStorage') // Windows
|
||||
* </code>
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function minify($css, $options = array())
|
||||
{
|
||||
if (isset($options['preserveComments'])
|
||||
&& !$options['preserveComments']) {
|
||||
$css = Minify_CSS_Compressor::process($css, $options);
|
||||
} else {
|
||||
$css = Minify_CommentPreserver::process(
|
||||
$css
|
||||
,array('Minify_CSS_Compressor', 'process')
|
||||
,array($options)
|
||||
);
|
||||
}
|
||||
if (! isset($options['currentDir']) && ! isset($options['prependRelativePath'])) {
|
||||
return $css;
|
||||
}
|
||||
if (isset($options['currentDir'])) {
|
||||
return Minify_CSS_UriRewriter::rewrite(
|
||||
$css
|
||||
,$options['currentDir']
|
||||
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
||||
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
||||
);
|
||||
} else {
|
||||
return Minify_CSS_UriRewriter::prepend(
|
||||
$css
|
||||
,$options['prependRelativePath']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,250 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_CSS_Compressor
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compress CSS
|
||||
*
|
||||
* This is a heavy regex-based removal of whitespace, unnecessary
|
||||
* comments and tokens, and some CSS value minimization, where practical.
|
||||
* Many steps have been taken to avoid breaking comment-based hacks,
|
||||
* including the ie5/mac filter (and its inversion), but expect tricky
|
||||
* hacks involving comment tokens in 'content' value strings to break
|
||||
* minimization badly. A test suite is available.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
|
||||
*/
|
||||
class Minify_CSS_Compressor {
|
||||
|
||||
/**
|
||||
* Minify a CSS string
|
||||
*
|
||||
* @param string $css
|
||||
*
|
||||
* @param array $options (currently ignored)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function process($css, $options = array())
|
||||
{
|
||||
$obj = new Minify_CSS_Compressor($options);
|
||||
return $obj->_process($css);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array options
|
||||
*/
|
||||
protected $_options = null;
|
||||
|
||||
/**
|
||||
* @var bool Are we "in" a hack?
|
||||
*
|
||||
* I.e. are some browsers targetted until the next comment?
|
||||
*/
|
||||
protected $_inHack = false;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options (currently ignored)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
private function __construct($options) {
|
||||
$this->_options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minify a CSS string
|
||||
*
|
||||
* @param string $css
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _process($css)
|
||||
{
|
||||
$css = str_replace("\r\n", "\n", $css);
|
||||
|
||||
// preserve empty comment after '>'
|
||||
// http://www.webdevout.net/css-hacks#in_css-selectors
|
||||
$css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
|
||||
|
||||
// preserve empty comment between property and value
|
||||
// http://css-discuss.incutio.com/?page=BoxModelHack
|
||||
$css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
|
||||
$css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
|
||||
|
||||
// apply callback to all valid comments (and strip out surrounding ws
|
||||
$css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@'
|
||||
,array($this, '_commentCB'), $css);
|
||||
|
||||
// remove ws around { } and last semicolon in declaration block
|
||||
$css = preg_replace('/\\s*{\\s*/', '{', $css);
|
||||
$css = preg_replace('/;?\\s*}\\s*/', '}', $css);
|
||||
|
||||
// remove ws surrounding semicolons
|
||||
$css = preg_replace('/\\s*;\\s*/', ';', $css);
|
||||
|
||||
// remove ws around urls
|
||||
$css = preg_replace('/
|
||||
url\\( # url(
|
||||
\\s*
|
||||
([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
|
||||
\\s*
|
||||
\\) # )
|
||||
/x', 'url($1)', $css);
|
||||
|
||||
// remove ws between rules and colons
|
||||
$css = preg_replace('/
|
||||
\\s*
|
||||
([{;]) # 1 = beginning of block or rule separator
|
||||
\\s*
|
||||
([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
|
||||
\\s*
|
||||
:
|
||||
\\s*
|
||||
(\\b|[#\'"]) # 3 = first character of a value
|
||||
/x', '$1$2:$3', $css);
|
||||
|
||||
// remove ws in selectors
|
||||
$css = preg_replace_callback('/
|
||||
(?: # non-capture
|
||||
\\s*
|
||||
[^~>+,\\s]+ # selector part
|
||||
\\s*
|
||||
[,>+~] # combinators
|
||||
)+
|
||||
\\s*
|
||||
[^~>+,\\s]+ # selector part
|
||||
{ # open declaration block
|
||||
/x'
|
||||
,array($this, '_selectorsCB'), $css);
|
||||
|
||||
// minimize hex colors
|
||||
$css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i'
|
||||
, '$1#$2$3$4$5', $css);
|
||||
|
||||
// remove spaces between font families
|
||||
$css = preg_replace_callback('/font-family:([^;}]+)([;}])/'
|
||||
,array($this, '_fontFamilyCB'), $css);
|
||||
|
||||
$css = preg_replace('/@import\\s+url/', '@import url', $css);
|
||||
|
||||
// replace any ws involving newlines with a single newline
|
||||
$css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css);
|
||||
|
||||
// separate common descendent selectors w/ newlines (to limit line lengths)
|
||||
$css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css);
|
||||
|
||||
// Use newline after 1st numeric value (to limit line lengths).
|
||||
$css = preg_replace('/
|
||||
((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
|
||||
\\s+
|
||||
/x'
|
||||
,"$1\n", $css);
|
||||
|
||||
// prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
|
||||
$css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css);
|
||||
|
||||
return trim($css);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace what looks like a set of selectors
|
||||
*
|
||||
* @param array $m regex matches
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _selectorsCB($m)
|
||||
{
|
||||
// remove ws around the combinators
|
||||
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a comment and return a replacement
|
||||
*
|
||||
* @param array $m regex matches
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _commentCB($m)
|
||||
{
|
||||
$hasSurroundingWs = (trim($m[0]) !== $m[1]);
|
||||
$m = $m[1];
|
||||
// $m is the comment content w/o the surrounding tokens,
|
||||
// but the return value will replace the entire comment.
|
||||
if ($m === 'keep') {
|
||||
return '/**/';
|
||||
}
|
||||
if ($m === '" "') {
|
||||
// component of http://tantek.com/CSS/Examples/midpass.html
|
||||
return '/*" "*/';
|
||||
}
|
||||
if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
|
||||
// component of http://tantek.com/CSS/Examples/midpass.html
|
||||
return '/*";}}/* */';
|
||||
}
|
||||
if ($this->_inHack) {
|
||||
// inversion: feeding only to one browser
|
||||
if (preg_match('@
|
||||
^/ # comment started like /*/
|
||||
\\s*
|
||||
(\\S[\\s\\S]+?) # has at least some non-ws content
|
||||
\\s*
|
||||
/\\* # ends like /*/ or /**/
|
||||
@x', $m, $n)) {
|
||||
// end hack mode after this comment, but preserve the hack and comment content
|
||||
$this->_inHack = false;
|
||||
return "/*/{$n[1]}/**/";
|
||||
}
|
||||
}
|
||||
if (substr($m, -1) === '\\') { // comment ends like \*/
|
||||
// begin hack mode and preserve hack
|
||||
$this->_inHack = true;
|
||||
return '/*\\*/';
|
||||
}
|
||||
if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
|
||||
// begin hack mode and preserve hack
|
||||
$this->_inHack = true;
|
||||
return '/*/*/';
|
||||
}
|
||||
if ($this->_inHack) {
|
||||
// a regular comment ends hack mode but should be preserved
|
||||
$this->_inHack = false;
|
||||
return '/**/';
|
||||
}
|
||||
// Issue 107: if there's any surrounding whitespace, it may be important, so
|
||||
// replace the comment with a single space
|
||||
return $hasSurroundingWs // remove all other comments
|
||||
? ' '
|
||||
: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a font-family listing and return a replacement
|
||||
*
|
||||
* @param array $m regex matches
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _fontFamilyCB($m)
|
||||
{
|
||||
$m[1] = preg_replace('/
|
||||
\\s*
|
||||
(
|
||||
"[^"]+" # 1 = family in double qutoes
|
||||
|\'[^\']+\' # or 1 = family in single quotes
|
||||
|[\\w\\-]+ # or 1 = unquoted family
|
||||
)
|
||||
\\s*
|
||||
/x', '$1', $m[1]);
|
||||
return 'font-family:' . $m[1] . $m[2];
|
||||
}
|
||||
}
|
@@ -1,270 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_CSS_UriRewriter
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Rewrite file-relative URIs as root-relative in CSS files
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_CSS_UriRewriter {
|
||||
|
||||
/**
|
||||
* Defines which class to call as part of callbacks, change this
|
||||
* if you extend Minify_CSS_UriRewriter
|
||||
* @var string
|
||||
*/
|
||||
protected static $className = 'Minify_CSS_UriRewriter';
|
||||
|
||||
/**
|
||||
* rewrite() and rewriteRelative() append debugging information here
|
||||
* @var string
|
||||
*/
|
||||
public static $debugText = '';
|
||||
|
||||
/**
|
||||
* Rewrite file relative URIs as root relative in CSS files
|
||||
*
|
||||
* @param string $css
|
||||
*
|
||||
* @param string $currentDir The directory of the current CSS file.
|
||||
*
|
||||
* @param string $docRoot The document root of the web site in which
|
||||
* the CSS file resides (default = $_SERVER['DOCUMENT_ROOT']).
|
||||
*
|
||||
* @param array $symlinks (default = array()) If the CSS file is stored in
|
||||
* a symlink-ed directory, provide an array of link paths to
|
||||
* target paths, where the link paths are within the document root. Because
|
||||
* paths need to be normalized for this to work, use "//" to substitute
|
||||
* the doc root in the link paths (the array keys). E.g.:
|
||||
* <code>
|
||||
* array('//symlink' => '/real/target/path') // unix
|
||||
* array('//static' => 'D:\\staticStorage') // Windows
|
||||
* </code>
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = array())
|
||||
{
|
||||
self::$_docRoot = self::_realpath(
|
||||
$docRoot ? $docRoot : $_SERVER['DOCUMENT_ROOT']
|
||||
);
|
||||
self::$_currentDir = self::_realpath($currentDir);
|
||||
self::$_symlinks = array();
|
||||
|
||||
// normalize symlinks
|
||||
foreach ($symlinks as $link => $target) {
|
||||
$link = ($link === '//')
|
||||
? self::$_docRoot
|
||||
: str_replace('//', self::$_docRoot . '/', $link);
|
||||
$link = strtr($link, '/', DIRECTORY_SEPARATOR);
|
||||
self::$_symlinks[$link] = self::_realpath($target);
|
||||
}
|
||||
|
||||
self::$debugText .= "docRoot : " . self::$_docRoot . "\n"
|
||||
. "currentDir : " . self::$_currentDir . "\n";
|
||||
if (self::$_symlinks) {
|
||||
self::$debugText .= "symlinks : " . var_export(self::$_symlinks, 1) . "\n";
|
||||
}
|
||||
self::$debugText .= "\n";
|
||||
|
||||
$css = self::_trimUrls($css);
|
||||
|
||||
// rewrite
|
||||
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
||||
,array(self::$className, '_processUriCB'), $css);
|
||||
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
||||
,array(self::$className, '_processUriCB'), $css);
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend a path to relative URIs in CSS files
|
||||
*
|
||||
* @param string $css
|
||||
*
|
||||
* @param string $path The path to prepend.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function prepend($css, $path)
|
||||
{
|
||||
self::$_prependPath = $path;
|
||||
|
||||
$css = self::_trimUrls($css);
|
||||
|
||||
// append
|
||||
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
||||
,array(self::$className, '_processUriCB'), $css);
|
||||
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
||||
,array(self::$className, '_processUriCB'), $css);
|
||||
|
||||
self::$_prependPath = null;
|
||||
return $css;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @var string directory of this stylesheet
|
||||
*/
|
||||
private static $_currentDir = '';
|
||||
|
||||
/**
|
||||
* @var string DOC_ROOT
|
||||
*/
|
||||
private static $_docRoot = '';
|
||||
|
||||
/**
|
||||
* @var array directory replacements to map symlink targets back to their
|
||||
* source (within the document root) E.g. '/var/www/symlink' => '/var/realpath'
|
||||
*/
|
||||
private static $_symlinks = array();
|
||||
|
||||
/**
|
||||
* @var string path to prepend
|
||||
*/
|
||||
private static $_prependPath = null;
|
||||
|
||||
private static function _trimUrls($css)
|
||||
{
|
||||
return preg_replace('/
|
||||
url\\( # url(
|
||||
\\s*
|
||||
([^\\)]+?) # 1 = URI (assuming does not contain ")")
|
||||
\\s*
|
||||
\\) # )
|
||||
/x', 'url($1)', $css);
|
||||
}
|
||||
|
||||
private static function _processUriCB($m)
|
||||
{
|
||||
// $m matched either '/@import\\s+([\'"])(.*?)[\'"]/' or '/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
||||
$isImport = ($m[0][0] === '@');
|
||||
// determine URI and the quote character (if any)
|
||||
if ($isImport) {
|
||||
$quoteChar = $m[1];
|
||||
$uri = $m[2];
|
||||
} else {
|
||||
// $m[1] is either quoted or not
|
||||
$quoteChar = ($m[1][0] === "'" || $m[1][0] === '"')
|
||||
? $m[1][0]
|
||||
: '';
|
||||
$uri = ($quoteChar === '')
|
||||
? $m[1]
|
||||
: substr($m[1], 1, strlen($m[1]) - 2);
|
||||
}
|
||||
// analyze URI
|
||||
if ('/' !== $uri[0] // root-relative
|
||||
&& false === strpos($uri, '//') // protocol (non-data)
|
||||
&& 0 !== strpos($uri, 'data:') // data protocol
|
||||
) {
|
||||
// URI is file-relative: rewrite depending on options
|
||||
$uri = (self::$_prependPath !== null)
|
||||
? (self::$_prependPath . $uri)
|
||||
: self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks);
|
||||
}
|
||||
return $isImport
|
||||
? "@import {$quoteChar}{$uri}{$quoteChar}"
|
||||
: "url({$quoteChar}{$uri}{$quoteChar})";
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite a file relative URI as root relative
|
||||
*
|
||||
* <code>
|
||||
* Minify_CSS_UriRewriter::rewriteRelative(
|
||||
* '../img/hello.gif'
|
||||
* , '/home/user/www/css' // path of CSS file
|
||||
* , '/home/user/www' // doc root
|
||||
* );
|
||||
* // returns '/img/hello.gif'
|
||||
*
|
||||
* // example where static files are stored in a symlinked directory
|
||||
* Minify_CSS_UriRewriter::rewriteRelative(
|
||||
* 'hello.gif'
|
||||
* , '/var/staticFiles/theme'
|
||||
* , '/home/user/www'
|
||||
* , array('/home/user/www/static' => '/var/staticFiles')
|
||||
* );
|
||||
* // returns '/static/theme/hello.gif'
|
||||
* </code>
|
||||
*
|
||||
* @param string $uri file relative URI
|
||||
*
|
||||
* @param string $realCurrentDir realpath of the current file's directory.
|
||||
*
|
||||
* @param string $realDocRoot realpath of the site document root.
|
||||
*
|
||||
* @param array $symlinks (default = array()) If the file is stored in
|
||||
* a symlink-ed directory, provide an array of link paths to
|
||||
* real target paths, where the link paths "appear" to be within the document
|
||||
* root. E.g.:
|
||||
* <code>
|
||||
* array('/home/foo/www/not/real/path' => '/real/target/path') // unix
|
||||
* array('C:\\htdocs\\not\\real' => 'D:\\real\\target\\path') // Windows
|
||||
* </code>
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function rewriteRelative($uri, $realCurrentDir, $realDocRoot, $symlinks = array())
|
||||
{
|
||||
// prepend path with current dir separator (OS-independent)
|
||||
$path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR)
|
||||
. DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR);
|
||||
|
||||
self::$debugText .= "file-relative URI : {$uri}\n"
|
||||
. "path prepended : {$path}\n";
|
||||
|
||||
// "unresolve" a symlink back to doc root
|
||||
foreach ($symlinks as $link => $target) {
|
||||
if (0 === strpos($path, $target)) {
|
||||
// replace $target with $link
|
||||
$path = $link . substr($path, strlen($target));
|
||||
|
||||
self::$debugText .= "symlink unresolved : {$path}\n";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
// strip doc root
|
||||
$path = substr($path, strlen($realDocRoot));
|
||||
|
||||
self::$debugText .= "docroot stripped : {$path}\n";
|
||||
|
||||
// fix to root-relative URI
|
||||
|
||||
$uri = strtr($path, '/\\', '//');
|
||||
|
||||
// remove /./ and /../ where possible
|
||||
$uri = str_replace('/./', '/', $uri);
|
||||
// inspired by patch from Oleg Cherniy
|
||||
do {
|
||||
$uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, 1, $changed);
|
||||
} while ($changed);
|
||||
|
||||
self::$debugText .= "traversals removed : {$uri}\n\n";
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get realpath with any trailing slash removed. If realpath() fails,
|
||||
* just remove the trailing slash.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return mixed path with no trailing slash
|
||||
*/
|
||||
protected static function _realpath($path)
|
||||
{
|
||||
$realPath = realpath($path);
|
||||
if ($realPath !== false) {
|
||||
$path = $realPath;
|
||||
}
|
||||
return rtrim($path, '/\\');
|
||||
}
|
||||
}
|
@@ -1,130 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Cache_APC
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* APC-based cache class for Minify
|
||||
*
|
||||
* <code>
|
||||
* Minify::setCache(new Minify_Cache_APC());
|
||||
* </code>
|
||||
*
|
||||
* @package Minify
|
||||
* @author Chris Edwards
|
||||
**/
|
||||
class Minify_Cache_APC implements Minify_Cache_Interface {
|
||||
|
||||
/**
|
||||
* Create a Minify_Cache_APC object, to be passed to
|
||||
* Minify::setCache().
|
||||
*
|
||||
*
|
||||
* @param int $expire seconds until expiration (default = 0
|
||||
* meaning the item will not get an expiration date)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function __construct($expire = 0)
|
||||
{
|
||||
$this->_exp = $expire;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data to cache.
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
public function store($id, $data)
|
||||
{
|
||||
return apc_store($id, "{$_SERVER['REQUEST_TIME']}|{$data}", $this->_exp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of a cache entry
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @return int size in bytes
|
||||
*/
|
||||
public function getSize($id)
|
||||
{
|
||||
return $this->_fetch($id)
|
||||
? strlen($this->_data)
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a valid cache entry exist?
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @param int $srcMtime mtime of the original source file(s)
|
||||
*
|
||||
* @return bool exists
|
||||
*/
|
||||
public function isValid($id, $srcMtime)
|
||||
{
|
||||
return ($this->_fetch($id) && ($this->_lm >= $srcMtime));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the cached content to output
|
||||
*
|
||||
* @param string $id cache id
|
||||
*/
|
||||
public function display($id)
|
||||
{
|
||||
echo $this->_fetch($id)
|
||||
? $this->_data
|
||||
: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the cached content
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
return $this->_fetch($id)
|
||||
? $this->_data
|
||||
: '';
|
||||
}
|
||||
|
||||
private $_exp = null;
|
||||
|
||||
// cache of most recently fetched id
|
||||
private $_lm = null;
|
||||
private $_data = null;
|
||||
private $_id = null;
|
||||
|
||||
/**
|
||||
* Fetch data and timestamp from apc, store in instance
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
private function _fetch($id)
|
||||
{
|
||||
if ($this->_id === $id) {
|
||||
return true;
|
||||
}
|
||||
$ret = apc_fetch($id);
|
||||
if (false === $ret) {
|
||||
$this->_id = null;
|
||||
return false;
|
||||
}
|
||||
list($this->_lm, $this->_data) = explode('|', $ret, 2);
|
||||
$this->_id = $id;
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,125 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Cache_File
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
class Minify_Cache_File implements Minify_Cache_Interface {
|
||||
|
||||
public function __construct($path = '', $fileLocking = false)
|
||||
{
|
||||
if (! $path) {
|
||||
require_once 'Solar/Dir.php';
|
||||
$path = rtrim(Solar_Dir::tmp(), DIRECTORY_SEPARATOR);
|
||||
}
|
||||
$this->_locking = $fileLocking;
|
||||
$this->_path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data to cache.
|
||||
*
|
||||
* @param string $id cache id (e.g. a filename)
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
public function store($id, $data)
|
||||
{
|
||||
$flag = $this->_locking
|
||||
? LOCK_EX
|
||||
: null;
|
||||
if (is_file($this->_path . '/' . $id)) {
|
||||
@unlink($this->_path . '/' . $id);
|
||||
}
|
||||
if (! @file_put_contents($this->_path . '/' . $id, $data, $flag)) {
|
||||
return false;
|
||||
}
|
||||
// write control
|
||||
if ($data !== $this->fetch($id)) {
|
||||
@unlink($file);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of a cache entry
|
||||
*
|
||||
* @param string $id cache id (e.g. a filename)
|
||||
*
|
||||
* @return int size in bytes
|
||||
*/
|
||||
public function getSize($id)
|
||||
{
|
||||
return filesize($this->_path . '/' . $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a valid cache entry exist?
|
||||
*
|
||||
* @param string $id cache id (e.g. a filename)
|
||||
*
|
||||
* @param int $srcMtime mtime of the original source file(s)
|
||||
*
|
||||
* @return bool exists
|
||||
*/
|
||||
public function isValid($id, $srcMtime)
|
||||
{
|
||||
$file = $this->_path . '/' . $id;
|
||||
return (is_file($file) && (filemtime($file) >= $srcMtime));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the cached content to output
|
||||
*
|
||||
* @param string $id cache id (e.g. a filename)
|
||||
*/
|
||||
public function display($id)
|
||||
{
|
||||
if ($this->_locking) {
|
||||
$fp = fopen($this->_path . '/' . $id, 'rb');
|
||||
flock($fp, LOCK_SH);
|
||||
fpassthru($fp);
|
||||
flock($fp, LOCK_UN);
|
||||
fclose($fp);
|
||||
} else {
|
||||
readfile($this->_path . '/' . $id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the cached content
|
||||
*
|
||||
* @param string $id cache id (e.g. a filename)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
if ($this->_locking) {
|
||||
$fp = fopen($this->_path . '/' . $id, 'rb');
|
||||
flock($fp, LOCK_SH);
|
||||
$ret = stream_get_contents($fp);
|
||||
flock($fp, LOCK_UN);
|
||||
fclose($fp);
|
||||
return $ret;
|
||||
} else {
|
||||
return file_get_contents($this->_path . '/' . $id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the cache path used
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPath()
|
||||
{
|
||||
return $this->_path;
|
||||
}
|
||||
|
||||
private $_path = null;
|
||||
private $_locking = null;
|
||||
}
|
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Cache_Interface
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* @package Minify
|
||||
* @author Stephen Clay
|
||||
**/
|
||||
interface Minify_Cache_Interface {
|
||||
|
||||
/**
|
||||
* Write data to cache.
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
public function store($id, $data);
|
||||
|
||||
/**
|
||||
* Get the size of a cache entry
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @return int size in bytes
|
||||
*/
|
||||
public function getSize($id);
|
||||
|
||||
/**
|
||||
* Does a valid cache entry exist?
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @param int $srcMtime mtime of the original source file(s)
|
||||
*
|
||||
* @return bool exists
|
||||
*/
|
||||
public function isValid($id, $srcMtime);
|
||||
|
||||
/**
|
||||
* Send the cached content to output
|
||||
*
|
||||
* @param string $id cache id
|
||||
*/
|
||||
public function display($id);
|
||||
|
||||
/**
|
||||
* Fetch the cached content
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fetch($id);
|
||||
}
|
@@ -1,137 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Cache_Memcache
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Memcache-based cache class for Minify
|
||||
*
|
||||
* <code>
|
||||
* // fall back to disk caching if memcache can't connect
|
||||
* $memcache = new Memcache;
|
||||
* if ($memcache->connect('localhost', 11211)) {
|
||||
* Minify::setCache(new Minify_Cache_Memcache($memcache));
|
||||
* } else {
|
||||
* Minify::setCache();
|
||||
* }
|
||||
* </code>
|
||||
**/
|
||||
class Minify_Cache_Memcache implements Minify_Cache_Interface {
|
||||
|
||||
/**
|
||||
* Create a Minify_Cache_Memcache object, to be passed to
|
||||
* Minify::setCache().
|
||||
*
|
||||
* @param Memcache $memcache already-connected instance
|
||||
*
|
||||
* @param int $expire seconds until expiration (default = 0
|
||||
* meaning the item will not get an expiration date)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function __construct($memcache, $expire = 0)
|
||||
{
|
||||
$this->_mc = $memcache;
|
||||
$this->_exp = $expire;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data to cache.
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
public function store($id, $data)
|
||||
{
|
||||
return $this->_mc->set($id, "{$_SERVER['REQUEST_TIME']}|{$data}", 0, $this->_exp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the size of a cache entry
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @return int size in bytes
|
||||
*/
|
||||
public function getSize($id)
|
||||
{
|
||||
return $this->_fetch($id)
|
||||
? strlen($this->_data)
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a valid cache entry exist?
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @param int $srcMtime mtime of the original source file(s)
|
||||
*
|
||||
* @return bool exists
|
||||
*/
|
||||
public function isValid($id, $srcMtime)
|
||||
{
|
||||
return ($this->_fetch($id) && ($this->_lm >= $srcMtime));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the cached content to output
|
||||
*
|
||||
* @param string $id cache id
|
||||
*/
|
||||
public function display($id)
|
||||
{
|
||||
echo $this->_fetch($id)
|
||||
? $this->_data
|
||||
: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the cached content
|
||||
*
|
||||
* @param string $id cache id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
return $this->_fetch($id)
|
||||
? $this->_data
|
||||
: '';
|
||||
}
|
||||
|
||||
private $_mc = null;
|
||||
private $_exp = null;
|
||||
|
||||
// cache of most recently fetched id
|
||||
private $_lm = null;
|
||||
private $_data = null;
|
||||
private $_id = null;
|
||||
|
||||
/**
|
||||
* Fetch data and timestamp from memcache, store in instance
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
private function _fetch($id)
|
||||
{
|
||||
if ($this->_id === $id) {
|
||||
return true;
|
||||
}
|
||||
$ret = $this->_mc->get($id);
|
||||
if (false === $ret) {
|
||||
$this->_id = null;
|
||||
return false;
|
||||
}
|
||||
list($this->_lm, $this->_data) = explode('|', $ret, 2);
|
||||
$this->_id = $id;
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,90 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_CommentPreserver
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Process a string in pieces preserving C-style comments that begin with "/*!"
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_CommentPreserver {
|
||||
|
||||
/**
|
||||
* String to be prepended to each preserved comment
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $prepend = "\n";
|
||||
|
||||
/**
|
||||
* String to be appended to each preserved comment
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $append = "\n";
|
||||
|
||||
/**
|
||||
* Process a string outside of C-style comments that begin with "/*!"
|
||||
*
|
||||
* On each non-empty string outside these comments, the given processor
|
||||
* function will be called. The first "!" will be removed from the
|
||||
* preserved comments, and the comments will be surrounded by
|
||||
* Minify_CommentPreserver::$preprend and Minify_CommentPreserver::$append.
|
||||
*
|
||||
* @param string $content
|
||||
* @param callback $processor function
|
||||
* @param array $args array of extra arguments to pass to the processor
|
||||
* function (default = array())
|
||||
* @return string
|
||||
*/
|
||||
public static function process($content, $processor, $args = array())
|
||||
{
|
||||
$ret = '';
|
||||
while (true) {
|
||||
list($beforeComment, $comment, $afterComment) = self::_nextComment($content);
|
||||
if ('' !== $beforeComment) {
|
||||
$callArgs = $args;
|
||||
array_unshift($callArgs, $beforeComment);
|
||||
$ret .= call_user_func_array($processor, $callArgs);
|
||||
}
|
||||
if (false === $comment) {
|
||||
break;
|
||||
}
|
||||
$ret .= $comment;
|
||||
$content = $afterComment;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract comments that YUI Compressor preserves.
|
||||
*
|
||||
* @param string $in input
|
||||
*
|
||||
* @return array 3 elements are returned. If a YUI comment is found, the
|
||||
* 2nd element is the comment and the 1st and 2nd are the surrounding
|
||||
* strings. If no comment is found, the entire string is returned as the
|
||||
* 1st element and the other two are false.
|
||||
*/
|
||||
private static function _nextComment($in)
|
||||
{
|
||||
if (
|
||||
false === ($start = strpos($in, '/*!'))
|
||||
|| false === ($end = strpos($in, '*/', $start + 3))
|
||||
) {
|
||||
return array($in, false, false);
|
||||
}
|
||||
$ret = array(
|
||||
substr($in, 0, $start)
|
||||
,self::$prepend . '/*' . substr($in, $start + 3, $end - $start - 1) . self::$append
|
||||
);
|
||||
$endChars = (strlen($in) - $end - 2);
|
||||
$ret[] = (0 === $endChars)
|
||||
? ''
|
||||
: substr($in, -$endChars);
|
||||
return $ret;
|
||||
}
|
||||
}
|
@@ -1,204 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Controller_Base
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for Minify controller
|
||||
*
|
||||
* The controller class validates a request and uses it to create sources
|
||||
* for minification and set options like contentType. It's also responsible
|
||||
* for loading minifier code upon request.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
abstract class Minify_Controller_Base {
|
||||
|
||||
/**
|
||||
* Setup controller sources and set an needed options for Minify::source
|
||||
*
|
||||
* You must override this method in your subclass controller to set
|
||||
* $this->sources. If the request is NOT valid, make sure $this->sources
|
||||
* is left an empty array. Then strip any controller-specific options from
|
||||
* $options and return it. To serve files, $this->sources must be an array of
|
||||
* Minify_Source objects.
|
||||
*
|
||||
* @param array $options controller and Minify options
|
||||
*
|
||||
* return array $options Minify::serve options
|
||||
*/
|
||||
abstract public function setupSources($options);
|
||||
|
||||
/**
|
||||
* Get default Minify options for this controller.
|
||||
*
|
||||
* Override in subclass to change defaults
|
||||
*
|
||||
* @return array options for Minify
|
||||
*/
|
||||
public function getDefaultMinifyOptions() {
|
||||
return array(
|
||||
'isPublic' => true
|
||||
,'encodeOutput' => function_exists('gzdeflate')
|
||||
,'encodeMethod' => null // determine later
|
||||
,'encodeLevel' => 9
|
||||
,'minifierOptions' => array() // no minifier options
|
||||
,'contentTypeCharset' => 'utf-8'
|
||||
,'maxAge' => 1800 // 30 minutes
|
||||
,'rewriteCssUris' => true
|
||||
,'bubbleCssImports' => false
|
||||
,'quiet' => false // serve() will send headers and output
|
||||
,'debug' => false
|
||||
|
||||
// if you override this, the response code MUST be directly after
|
||||
// the first space.
|
||||
,'badRequestHeader' => 'HTTP/1.0 400 Bad Request'
|
||||
|
||||
// callback function to see/modify content of all sources
|
||||
,'postprocessor' => null
|
||||
// file to require to load preprocessor
|
||||
,'postprocessorRequire' => null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default minifiers for this controller.
|
||||
*
|
||||
* Override in subclass to change defaults
|
||||
*
|
||||
* @return array minifier callbacks for common types
|
||||
*/
|
||||
public function getDefaultMinifers() {
|
||||
$ret[Minify::TYPE_JS] = array('JSMin', 'minify');
|
||||
$ret[Minify::TYPE_CSS] = array('Minify_CSS', 'minify');
|
||||
$ret[Minify::TYPE_HTML] = array('Minify_HTML', 'minify');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load any code necessary to execute the given minifier callback.
|
||||
*
|
||||
* The controller is responsible for loading minification code on demand
|
||||
* via this method. This built-in function will only load classes for
|
||||
* static method callbacks where the class isn't already defined. It uses
|
||||
* the PEAR convention, so, given array('Jimmy_Minifier', 'minCss'), this
|
||||
* function will include 'Jimmy/Minifier.php'.
|
||||
*
|
||||
* If you need code loaded on demand and this doesn't suit you, you'll need
|
||||
* to override this function in your subclass.
|
||||
* @see Minify_Controller_Page::loadMinifier()
|
||||
*
|
||||
* @param callback $minifierCallback callback of minifier function
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function loadMinifier($minifierCallback)
|
||||
{
|
||||
// autoloading... may no longer be needed
|
||||
|
||||
/*if (is_array($minifierCallback)
|
||||
&& is_string($minifierCallback[0])
|
||||
&& !class_exists($minifierCallback[0], false)) {
|
||||
|
||||
require str_replace('_', '/', $minifierCallback[0]) . '.php';
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a user-given file within an allowable directory, existing,
|
||||
* and having an extension js/css/html/txt ?
|
||||
*
|
||||
* This is a convenience function for controllers that have to accept
|
||||
* user-given paths
|
||||
*
|
||||
* @param string $file full file path (already processed by realpath())
|
||||
*
|
||||
* @param array $safeDirs directories where files are safe to serve. Files can also
|
||||
* be in subdirectories of these directories.
|
||||
*
|
||||
* @return bool file is safe
|
||||
*/
|
||||
public static function _fileIsSafe($file, $safeDirs)
|
||||
{
|
||||
$pathOk = false;
|
||||
foreach ((array)$safeDirs as $safeDir) {
|
||||
if (strpos($file, $safeDir) === 0) {
|
||||
$pathOk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$base = basename($file);
|
||||
if (! $pathOk || ! is_file($file) || $base[0] === '.') {
|
||||
return false;
|
||||
}
|
||||
list($revExt) = explode('.', strrev($base));
|
||||
return in_array(strrev($revExt), array('js', 'css', 'html', 'txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array instances of Minify_Source, which provide content and
|
||||
* any individual minification needs.
|
||||
*
|
||||
* @see Minify_Source
|
||||
*/
|
||||
public $sources = array();
|
||||
|
||||
/**
|
||||
* Mix in default controller options with user-given options
|
||||
*
|
||||
* @param array $options user options
|
||||
*
|
||||
* @return array mixed options
|
||||
*/
|
||||
public final function mixInDefaultOptions($options)
|
||||
{
|
||||
$ret = array_merge(
|
||||
$this->getDefaultMinifyOptions(), $options
|
||||
);
|
||||
if (! isset($options['minifiers'])) {
|
||||
$options['minifiers'] = array();
|
||||
}
|
||||
$ret['minifiers'] = array_merge(
|
||||
$this->getDefaultMinifers(), $options['minifiers']
|
||||
);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze sources (if there are any) and set $options 'contentType'
|
||||
* and 'lastModifiedTime' if they already aren't.
|
||||
*
|
||||
* @param array $options options for Minify
|
||||
*
|
||||
* @return array options for Minify
|
||||
*/
|
||||
public final function analyzeSources($options = array())
|
||||
{
|
||||
if ($this->sources) {
|
||||
if (! isset($options['contentType'])) {
|
||||
$options['contentType'] = Minify_Source::getContentType($this->sources);
|
||||
}
|
||||
// last modified is needed for caching, even if setExpires is set
|
||||
if (! isset($options['lastModifiedTime'])) {
|
||||
$max = 0;
|
||||
foreach ($this->sources as $source) {
|
||||
$max = max($source->lastModified, $max);
|
||||
}
|
||||
$options['lastModifiedTime'] = $max;
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message to the Minify logger
|
||||
* @param string $msg
|
||||
* @return null
|
||||
*/
|
||||
protected function log($msg) {
|
||||
Minify_Logger::log($msg);
|
||||
}
|
||||
}
|
@@ -1,78 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Controller_Files
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
require_once 'Minify/Controller/Base.php';
|
||||
|
||||
/**
|
||||
* Controller class for minifying a set of files
|
||||
*
|
||||
* E.g. the following would serve the minified Javascript for a site
|
||||
* <code>
|
||||
* Minify::serve('Files', array(
|
||||
* 'files' => array(
|
||||
* '//js/jquery.js'
|
||||
* ,'//js/plugins.js'
|
||||
* ,'/home/username/file.js'
|
||||
* )
|
||||
* ));
|
||||
* </code>
|
||||
*
|
||||
* As a shortcut, the controller will replace "//" at the beginning
|
||||
* of a filename with $_SERVER['DOCUMENT_ROOT'] . '/'.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_Controller_Files extends Minify_Controller_Base {
|
||||
|
||||
/**
|
||||
* Set up file sources
|
||||
*
|
||||
* @param array $options controller and Minify options
|
||||
* @return array Minify options
|
||||
*
|
||||
* Controller options:
|
||||
*
|
||||
* 'files': (required) array of complete file paths, or a single path
|
||||
*/
|
||||
public function setupSources($options) {
|
||||
// strip controller options
|
||||
|
||||
$files = $options['files'];
|
||||
// if $files is a single object, casting will break it
|
||||
if (is_object($files)) {
|
||||
$files = array($files);
|
||||
} elseif (! is_array($files)) {
|
||||
$files = (array)$files;
|
||||
}
|
||||
unset($options['files']);
|
||||
|
||||
$sources = array();
|
||||
foreach ($files as $file) {
|
||||
if ($file instanceof Minify_Source) {
|
||||
$sources[] = $file;
|
||||
continue;
|
||||
}
|
||||
if (0 === strpos($file, '//')) {
|
||||
$file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1);
|
||||
}
|
||||
$realPath = realpath($file);
|
||||
if (is_file($realPath)) {
|
||||
$sources[] = new Minify_Source(array(
|
||||
'filepath' => $realPath
|
||||
));
|
||||
} else {
|
||||
$this->log("The path \"{$file}\" could not be found (or was not a file)");
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
if ($sources) {
|
||||
$this->sources = $sources;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
|
@@ -1,94 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Controller_Groups
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
require_once 'Minify/Controller/Base.php';
|
||||
|
||||
/**
|
||||
* Controller class for serving predetermined groups of minimized sets, selected
|
||||
* by PATH_INFO
|
||||
*
|
||||
* <code>
|
||||
* Minify::serve('Groups', array(
|
||||
* 'groups' => array(
|
||||
* 'css' => array('//css/type.css', '//css/layout.css')
|
||||
* ,'js' => array('//js/jquery.js', '//js/site.js')
|
||||
* )
|
||||
* ));
|
||||
* </code>
|
||||
*
|
||||
* If the above code were placed in /serve.php, it would enable the URLs
|
||||
* /serve.php/js and /serve.php/css
|
||||
*
|
||||
* As a shortcut, the controller will replace "//" at the beginning
|
||||
* of a filename with $_SERVER['DOCUMENT_ROOT'] . '/'.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_Controller_Groups extends Minify_Controller_Base {
|
||||
|
||||
/**
|
||||
* Set up groups of files as sources
|
||||
*
|
||||
* @param array $options controller and Minify options
|
||||
* @return array Minify options
|
||||
*
|
||||
* Controller options:
|
||||
*
|
||||
* 'groups': (required) array mapping PATH_INFO strings to arrays
|
||||
* of complete file paths. @see Minify_Controller_Groups
|
||||
*/
|
||||
public function setupSources($options) {
|
||||
// strip controller options
|
||||
$groups = $options['groups'];
|
||||
unset($options['groups']);
|
||||
|
||||
// mod_fcgid places PATH_INFO in ORIG_PATH_INFO
|
||||
$pi = isset($_SERVER['ORIG_PATH_INFO'])
|
||||
? substr($_SERVER['ORIG_PATH_INFO'], 1)
|
||||
: (isset($_SERVER['PATH_INFO'])
|
||||
? substr($_SERVER['PATH_INFO'], 1)
|
||||
: false
|
||||
);
|
||||
if (false === $pi || ! isset($groups[$pi])) {
|
||||
// no PATH_INFO or not a valid group
|
||||
$this->log("Missing PATH_INFO or no group set for \"$pi\"");
|
||||
return $options;
|
||||
}
|
||||
$sources = array();
|
||||
|
||||
$files = $groups[$pi];
|
||||
// if $files is a single object, casting will break it
|
||||
if (is_object($files)) {
|
||||
$files = array($files);
|
||||
} elseif (! is_array($files)) {
|
||||
$files = (array)$files;
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
if ($file instanceof Minify_Source) {
|
||||
$sources[] = $file;
|
||||
continue;
|
||||
}
|
||||
if (0 === strpos($file, '//')) {
|
||||
$file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1);
|
||||
}
|
||||
$realPath = realpath($file);
|
||||
if (is_file($realPath)) {
|
||||
$sources[] = new Minify_Source(array(
|
||||
'filepath' => $realPath
|
||||
));
|
||||
} else {
|
||||
$this->log("The path \"{$file}\" could not be found (or was not a file)");
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
if ($sources) {
|
||||
$this->sources = $sources;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
|
@@ -1,153 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Controller_MinApp
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controller class for requests to /min/index.php
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_Controller_MinApp extends Minify_Controller_Base {
|
||||
|
||||
/**
|
||||
* Set up groups of files as sources
|
||||
*
|
||||
* If $_GET['g'] is set, it's split with "," and each piece is looked up as
|
||||
* a key in groupsConfig.php, and the found arrays are added to the sources.
|
||||
*
|
||||
* If $_GET['f'] is set and $options['groupsOnly'] is false, sources are
|
||||
* added based on validity of name and location.
|
||||
*
|
||||
* Caveat: Groups always come before files, but the groups are ordered as
|
||||
* requested. E.g.
|
||||
* /f=file.js&g=js1,js2 == /g=js1,js2&f=file.js != /g=js2,js1&f=file.js
|
||||
*
|
||||
* Caveat: If JS group(s) are specified, the method will still allow you to
|
||||
* add CSS files and vice-versa. E.g.:
|
||||
* /g=js1,js2&f=site.css => Minify will try to process site.css through the
|
||||
* Javascript minifier, possibly causing an exception.
|
||||
*
|
||||
* @param array $options controller and Minify options
|
||||
* @return array Minify options
|
||||
*/
|
||||
public function setupSources($options) {
|
||||
// filter controller options
|
||||
$cOptions = array_merge(
|
||||
array(
|
||||
'allowDirs' => '//'
|
||||
,'groupsOnly' => false
|
||||
,'groups' => array()
|
||||
,'maxFiles' => 10
|
||||
)
|
||||
,(isset($options['minApp']) ? $options['minApp'] : array())
|
||||
);
|
||||
unset($options['minApp']);
|
||||
$sources = array();
|
||||
if (isset($_GET['g'])) {
|
||||
// try groups
|
||||
$files = array();
|
||||
$keys = explode(',', $_GET['g']);
|
||||
// check for duplicate key
|
||||
// note: no check for duplicate files
|
||||
if ($keys != array_unique($keys)) {
|
||||
$this->log("Duplicate key given in \"{$_GET['g']}\"");
|
||||
return $options;
|
||||
}
|
||||
foreach ($keys as $key) {
|
||||
if (! isset($cOptions['groups'][$key])) {
|
||||
$this->log("A group configuration for \"{$key}\" was not set");
|
||||
return $options;
|
||||
}
|
||||
$groupFiles = $cOptions['groups'][$key];
|
||||
if (is_array($groupFiles)) {
|
||||
array_splice($files, count($files), 0, $groupFiles);
|
||||
} else {
|
||||
$files[] = $groupFiles;
|
||||
}
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
if ($file instanceof Minify_Source) {
|
||||
$sources[] = $file;
|
||||
continue;
|
||||
}
|
||||
if (0 === strpos($file, '//')) {
|
||||
$file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1);
|
||||
}
|
||||
$file = realpath($file);
|
||||
if (is_file($file)) {
|
||||
$sources[] = new Minify_Source(array(
|
||||
'filepath' => $file
|
||||
));
|
||||
} else {
|
||||
$this->log("The path \"{$file}\" could not be found (or was not a file)");
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! $cOptions['groupsOnly'] && isset($_GET['f'])) {
|
||||
// try user files
|
||||
// The following restrictions are to limit the URLs that minify will
|
||||
// respond to. Ideally there should be only one way to reference a file.
|
||||
if (// verify at least one file, files are single comma separated,
|
||||
// and are all same extension
|
||||
! preg_match('/^[^,]+\\.(css|js)(?:,[^,]+\\.\\1)*$/', $_GET['f'])
|
||||
// no "//"
|
||||
|| strpos($_GET['f'], '//') !== false
|
||||
// no "\"
|
||||
|| strpos($_GET['f'], '\\') !== false
|
||||
// no "./"
|
||||
|| preg_match('/(?:^|[^\\.])\\.\\//', $_GET['f'])
|
||||
) {
|
||||
$this->log("GET param 'f' invalid (see MinApp.php line 63)");
|
||||
return $options;
|
||||
}
|
||||
$files = explode(',', $_GET['f']);
|
||||
if (count($files) > $cOptions['maxFiles'] || $files != array_unique($files)) {
|
||||
$this->log("Too many or duplicate files specified");
|
||||
return $options;
|
||||
}
|
||||
if (isset($_GET['b'])) {
|
||||
// check for validity
|
||||
if (preg_match('@^[^/]+(?:/[^/]+)*$@', $_GET['b'])
|
||||
&& false === strpos($_GET['b'], '..')
|
||||
&& $_GET['b'] !== '.') {
|
||||
// valid base
|
||||
$base = "/{$_GET['b']}/";
|
||||
} else {
|
||||
$this->log("GET param 'b' invalid (see MinApp.php line 84)");
|
||||
return $options;
|
||||
}
|
||||
} else {
|
||||
$base = '/';
|
||||
}
|
||||
$allowDirs = array();
|
||||
foreach ((array)$cOptions['allowDirs'] as $allowDir) {
|
||||
$allowDirs[] = realpath(str_replace('//', $_SERVER['DOCUMENT_ROOT'] . '/', $allowDir));
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
$path = $_SERVER['DOCUMENT_ROOT'] . $base . $file;
|
||||
$file = realpath($path);
|
||||
if (false === $file) {
|
||||
$this->log("Path \"{$path}\" failed realpath()");
|
||||
return $options;
|
||||
} elseif (! parent::_fileIsSafe($file, $allowDirs)) {
|
||||
$this->log("Path \"{$path}\" failed Minify_Controller_Base::_fileIsSafe()");
|
||||
return $options;
|
||||
} else {
|
||||
$sources[] = new Minify_Source(array(
|
||||
'filepath' => $file
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($sources) {
|
||||
$this->sources = $sources;
|
||||
} else {
|
||||
$this->log("No sources to serve");
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
}
|
@@ -1,82 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Controller_Page
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controller class for serving a single HTML page
|
||||
*
|
||||
* @link http://code.google.com/p/minify/source/browse/trunk/web/examples/1/index.php#59
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_Controller_Page extends Minify_Controller_Base {
|
||||
|
||||
/**
|
||||
* Set up source of HTML content
|
||||
*
|
||||
* @param array $options controller and Minify options
|
||||
* @return array Minify options
|
||||
*
|
||||
* Controller options:
|
||||
*
|
||||
* 'content': (required) HTML markup
|
||||
*
|
||||
* 'id': (required) id of page (string for use in server-side caching)
|
||||
*
|
||||
* 'lastModifiedTime': timestamp of when this content changed. This
|
||||
* is recommended to allow both server and client-side caching.
|
||||
*
|
||||
* 'minifyAll': should all CSS and Javascript blocks be individually
|
||||
* minified? (default false)
|
||||
*
|
||||
*/
|
||||
public function setupSources($options) {
|
||||
if (isset($options['file'])) {
|
||||
$sourceSpec = array(
|
||||
'filepath' => $options['file']
|
||||
);
|
||||
unset($options['file']);
|
||||
} else {
|
||||
// strip controller options
|
||||
$sourceSpec = array(
|
||||
'content' => $options['content']
|
||||
,'id' => $options['id']
|
||||
);
|
||||
unset($options['content'], $options['id']);
|
||||
}
|
||||
if (isset($options['minifyAll'])) {
|
||||
// this will be the 2nd argument passed to Minify_HTML::minify()
|
||||
$sourceSpec['minifyOptions'] = array(
|
||||
'cssMinifier' => array('Minify_CSS', 'minify')
|
||||
,'jsMinifier' => array('JSMin', 'minify')
|
||||
);
|
||||
$this->_loadCssJsMinifiers = true;
|
||||
unset($options['minifyAll']);
|
||||
}
|
||||
$this->sources[] = new Minify_Source($sourceSpec);
|
||||
|
||||
$options['contentType'] = Minify::TYPE_HTML;
|
||||
return $options;
|
||||
}
|
||||
|
||||
protected $_loadCssJsMinifiers = false;
|
||||
|
||||
/**
|
||||
* @see Minify_Controller_Base::loadMinifier()
|
||||
*/
|
||||
public function loadMinifier($minifierCallback)
|
||||
{
|
||||
if ($this->_loadCssJsMinifiers) {
|
||||
// Minify will not call for these so we must manually load
|
||||
// them when Minify/HTML.php is called for.
|
||||
|
||||
// autoload
|
||||
//require_once 'Minify/CSS.php';
|
||||
//require_once 'JSMin.php';
|
||||
}
|
||||
parent::loadMinifier($minifierCallback); // load Minify/HTML.php
|
||||
}
|
||||
}
|
||||
|
@@ -1,116 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Controller_Version1
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controller class for emulating version 1 of minify.php
|
||||
*
|
||||
* <code>
|
||||
* Minify::serve('Version1');
|
||||
* </code>
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_Controller_Version1 extends Minify_Controller_Base {
|
||||
|
||||
/**
|
||||
* Set up groups of files as sources
|
||||
*
|
||||
* @param array $options controller and Minify options
|
||||
* @return array Minify options
|
||||
*
|
||||
*/
|
||||
public function setupSources($options) {
|
||||
self::_setupDefines();
|
||||
if (MINIFY_USE_CACHE) {
|
||||
$cacheDir = defined('MINIFY_CACHE_DIR')
|
||||
? MINIFY_CACHE_DIR
|
||||
: '';
|
||||
Minify::setCache($cacheDir);
|
||||
}
|
||||
$options['badRequestHeader'] = 'HTTP/1.0 404 Not Found';
|
||||
$options['contentTypeCharset'] = MINIFY_ENCODING;
|
||||
|
||||
// The following restrictions are to limit the URLs that minify will
|
||||
// respond to. Ideally there should be only one way to reference a file.
|
||||
if (! isset($_GET['files'])
|
||||
// verify at least one file, files are single comma separated,
|
||||
// and are all same extension
|
||||
|| ! preg_match('/^[^,]+\\.(css|js)(,[^,]+\\.\\1)*$/', $_GET['files'], $m)
|
||||
// no "//" (makes URL rewriting easier)
|
||||
|| strpos($_GET['files'], '//') !== false
|
||||
// no "\"
|
||||
|| strpos($_GET['files'], '\\') !== false
|
||||
// no "./"
|
||||
|| preg_match('/(?:^|[^\\.])\\.\\//', $_GET['files'])
|
||||
) {
|
||||
return $options;
|
||||
}
|
||||
$extension = $m[1];
|
||||
|
||||
$files = explode(',', $_GET['files']);
|
||||
if (count($files) > MINIFY_MAX_FILES) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
// strings for prepending to relative/absolute paths
|
||||
$prependRelPaths = dirname($_SERVER['SCRIPT_FILENAME'])
|
||||
. DIRECTORY_SEPARATOR;
|
||||
$prependAbsPaths = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
$sources = array();
|
||||
$goodFiles = array();
|
||||
$hasBadSource = false;
|
||||
|
||||
$allowDirs = isset($options['allowDirs'])
|
||||
? $options['allowDirs']
|
||||
: MINIFY_BASE_DIR;
|
||||
|
||||
foreach ($files as $file) {
|
||||
// prepend appropriate string for abs/rel paths
|
||||
$file = ($file[0] === '/' ? $prependAbsPaths : $prependRelPaths) . $file;
|
||||
// make sure a real file!
|
||||
$file = realpath($file);
|
||||
// don't allow unsafe or duplicate files
|
||||
if (parent::_fileIsSafe($file, $allowDirs)
|
||||
&& !in_array($file, $goodFiles))
|
||||
{
|
||||
$goodFiles[] = $file;
|
||||
$srcOptions = array(
|
||||
'filepath' => $file
|
||||
);
|
||||
$this->sources[] = new Minify_Source($srcOptions);
|
||||
} else {
|
||||
$hasBadSource = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($hasBadSource) {
|
||||
$this->sources = array();
|
||||
}
|
||||
if (! MINIFY_REWRITE_CSS_URLS) {
|
||||
$options['rewriteCssUris'] = false;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
private static function _setupDefines()
|
||||
{
|
||||
$defaults = array(
|
||||
'MINIFY_BASE_DIR' => realpath($_SERVER['DOCUMENT_ROOT'])
|
||||
,'MINIFY_ENCODING' => 'utf-8'
|
||||
,'MINIFY_MAX_FILES' => 16
|
||||
,'MINIFY_REWRITE_CSS_URLS' => true
|
||||
,'MINIFY_USE_CACHE' => true
|
||||
);
|
||||
foreach ($defaults as $const => $val) {
|
||||
if (! defined($const)) {
|
||||
define($const, $val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,245 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_HTML
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compress HTML
|
||||
*
|
||||
* This is a heavy regex-based removal of whitespace, unnecessary comments and
|
||||
* tokens. IE conditional comments are preserved. There are also options to have
|
||||
* STYLE and SCRIPT blocks compressed by callback functions.
|
||||
*
|
||||
* A test suite is available.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_HTML {
|
||||
|
||||
/**
|
||||
* "Minify" an HTML page
|
||||
*
|
||||
* @param string $html
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
||||
* elements.
|
||||
*
|
||||
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
||||
* elements. Note: the type attribute is ignored.
|
||||
*
|
||||
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
||||
* unset, minify will sniff for an XHTML doctype.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function minify($html, $options = array()) {
|
||||
$min = new Minify_HTML($html, $options);
|
||||
return $min->process();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a minifier object
|
||||
*
|
||||
* @param string $html
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
||||
* elements.
|
||||
*
|
||||
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
||||
* elements. Note: the type attribute is ignored.
|
||||
*
|
||||
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
||||
* unset, minify will sniff for an XHTML doctype.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function __construct($html, $options = array())
|
||||
{
|
||||
$this->_html = str_replace("\r\n", "\n", trim($html));
|
||||
if (isset($options['xhtml'])) {
|
||||
$this->_isXhtml = (bool)$options['xhtml'];
|
||||
}
|
||||
if (isset($options['cssMinifier'])) {
|
||||
$this->_cssMinifier = $options['cssMinifier'];
|
||||
}
|
||||
if (isset($options['jsMinifier'])) {
|
||||
$this->_jsMinifier = $options['jsMinifier'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Minify the markeup given in the constructor
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
if ($this->_isXhtml === null) {
|
||||
$this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
|
||||
}
|
||||
|
||||
$this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
|
||||
$this->_placeholders = array();
|
||||
|
||||
// replace SCRIPTs (and minify) with placeholders
|
||||
$this->_html = preg_replace_callback(
|
||||
'/(\\s*)(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
|
||||
,array($this, '_removeScriptCB')
|
||||
,$this->_html);
|
||||
|
||||
// replace STYLEs (and minify) with placeholders
|
||||
$this->_html = preg_replace_callback(
|
||||
'/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i'
|
||||
,array($this, '_removeStyleCB')
|
||||
,$this->_html);
|
||||
|
||||
// remove HTML comments (not containing IE conditional comments).
|
||||
$this->_html = preg_replace_callback(
|
||||
'/<!--([\\s\\S]*?)-->/'
|
||||
,array($this, '_commentCB')
|
||||
,$this->_html);
|
||||
|
||||
// replace PREs with placeholders
|
||||
$this->_html = preg_replace_callback('/\\s*(<pre\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
|
||||
,array($this, '_removePreCB')
|
||||
,$this->_html);
|
||||
|
||||
// replace TEXTAREAs with placeholders
|
||||
$this->_html = preg_replace_callback(
|
||||
'/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
||||
,array($this, '_removeTextareaCB')
|
||||
,$this->_html);
|
||||
|
||||
// trim each line.
|
||||
// @todo take into account attribute values that span multiple lines.
|
||||
$this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
|
||||
|
||||
// remove ws around block/undisplayed elements
|
||||
$this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
|
||||
.'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
|
||||
.'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
|
||||
.'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
|
||||
.'|ul)\\b[^>]*>)/i', '$1', $this->_html);
|
||||
|
||||
// remove ws outside of all elements
|
||||
$this->_html = preg_replace_callback(
|
||||
'/>([^<]+)</'
|
||||
,array($this, '_outsideTagCB')
|
||||
,$this->_html);
|
||||
|
||||
// use newlines before 1st attribute in open tags (to limit line lengths)
|
||||
$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
|
||||
|
||||
// fill placeholders
|
||||
$this->_html = str_replace(
|
||||
array_keys($this->_placeholders)
|
||||
,array_values($this->_placeholders)
|
||||
,$this->_html
|
||||
);
|
||||
return $this->_html;
|
||||
}
|
||||
|
||||
protected function _commentCB($m)
|
||||
{
|
||||
return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
|
||||
? $m[0]
|
||||
: '';
|
||||
}
|
||||
|
||||
protected function _reservePlace($content)
|
||||
{
|
||||
$placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
|
||||
$this->_placeholders[$placeholder] = $content;
|
||||
return $placeholder;
|
||||
}
|
||||
|
||||
protected $_isXhtml = null;
|
||||
protected $_replacementHash = null;
|
||||
protected $_placeholders = array();
|
||||
protected $_cssMinifier = null;
|
||||
protected $_jsMinifier = null;
|
||||
|
||||
protected function _outsideTagCB($m)
|
||||
{
|
||||
return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
|
||||
}
|
||||
|
||||
protected function _removePreCB($m)
|
||||
{
|
||||
return $this->_reservePlace($m[1]);
|
||||
}
|
||||
|
||||
protected function _removeTextareaCB($m)
|
||||
{
|
||||
return $this->_reservePlace($m[1]);
|
||||
}
|
||||
|
||||
protected function _removeStyleCB($m)
|
||||
{
|
||||
$openStyle = $m[1];
|
||||
$css = $m[2];
|
||||
// remove HTML comments
|
||||
$css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
|
||||
|
||||
// remove CDATA section markers
|
||||
$css = $this->_removeCdata($css);
|
||||
|
||||
// minify
|
||||
$minifier = $this->_cssMinifier
|
||||
? $this->_cssMinifier
|
||||
: 'trim';
|
||||
$css = call_user_func($minifier, $css);
|
||||
|
||||
return $this->_reservePlace($this->_needsCdata($css)
|
||||
? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
|
||||
: "{$openStyle}{$css}</style>"
|
||||
);
|
||||
}
|
||||
|
||||
protected function _removeScriptCB($m)
|
||||
{
|
||||
$openScript = $m[2];
|
||||
$js = $m[3];
|
||||
|
||||
// whitespace surrounding? preserve at least one space
|
||||
$ws1 = ($m[1] === '') ? '' : ' ';
|
||||
$ws2 = ($m[4] === '') ? '' : ' ';
|
||||
|
||||
// remove HTML comments (and ending "//" if present)
|
||||
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
|
||||
|
||||
// remove CDATA section markers
|
||||
$js = $this->_removeCdata($js);
|
||||
|
||||
// minify
|
||||
$minifier = $this->_jsMinifier
|
||||
? $this->_jsMinifier
|
||||
: 'trim';
|
||||
$js = call_user_func($minifier, $js);
|
||||
|
||||
return $this->_reservePlace($this->_needsCdata($js)
|
||||
? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
|
||||
: "{$ws1}{$openScript}{$js}</script>{$ws2}"
|
||||
);
|
||||
}
|
||||
|
||||
protected function _removeCdata($str)
|
||||
{
|
||||
return (false !== strpos($str, '<![CDATA['))
|
||||
? str_replace(array('<![CDATA[', ']]>'), '', $str)
|
||||
: $str;
|
||||
}
|
||||
|
||||
protected function _needsCdata($str)
|
||||
{
|
||||
return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
|
||||
}
|
||||
}
|
@@ -1,157 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_ImportProcessor
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Linearize a CSS/JS file by including content specified by CSS import
|
||||
* declarations. In CSS files, relative URIs are fixed.
|
||||
*
|
||||
* @imports will be processed regardless of where they appear in the source
|
||||
* files; i.e. @imports commented out or in string content will still be
|
||||
* processed!
|
||||
*
|
||||
* This has a unit test but should be considered "experimental".
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_ImportProcessor {
|
||||
|
||||
public static $filesIncluded = array();
|
||||
|
||||
public static function process($file)
|
||||
{
|
||||
self::$filesIncluded = array();
|
||||
self::$_isCss = (strtolower(substr($file, -4)) === '.css');
|
||||
$obj = new Minify_ImportProcessor(dirname($file));
|
||||
return $obj->_getContent($file);
|
||||
}
|
||||
|
||||
// allows callback funcs to know the current directory
|
||||
private $_currentDir = null;
|
||||
|
||||
// allows _importCB to write the fetched content back to the obj
|
||||
private $_importedContent = '';
|
||||
|
||||
private static $_isCss = null;
|
||||
|
||||
private function __construct($currentDir)
|
||||
{
|
||||
$this->_currentDir = $currentDir;
|
||||
}
|
||||
|
||||
private function _getContent($file)
|
||||
{
|
||||
$file = realpath($file);
|
||||
if (! $file
|
||||
|| in_array($file, self::$filesIncluded)
|
||||
|| false === ($content = @file_get_contents($file))
|
||||
) {
|
||||
// file missing, already included, or failed read
|
||||
return '';
|
||||
}
|
||||
self::$filesIncluded[] = realpath($file);
|
||||
$this->_currentDir = dirname($file);
|
||||
|
||||
// remove UTF-8 BOM if present
|
||||
if (pack("CCC",0xef,0xbb,0xbf) === substr($content, 0, 3)) {
|
||||
$content = substr($content, 3);
|
||||
}
|
||||
// ensure uniform EOLs
|
||||
$content = str_replace("\r\n", "\n", $content);
|
||||
|
||||
// process @imports
|
||||
$content = preg_replace_callback(
|
||||
'/
|
||||
@import\\s+
|
||||
(?:url\\(\\s*)? # maybe url(
|
||||
[\'"]? # maybe quote
|
||||
(.*?) # 1 = URI
|
||||
[\'"]? # maybe end quote
|
||||
(?:\\s*\\))? # maybe )
|
||||
([a-zA-Z,\\s]*)? # 2 = media list
|
||||
; # end token
|
||||
/x'
|
||||
,array($this, '_importCB')
|
||||
,$content
|
||||
);
|
||||
|
||||
if (self::$_isCss) {
|
||||
// rewrite remaining relative URIs
|
||||
$content = preg_replace_callback(
|
||||
'/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
||||
,array($this, '_urlCB')
|
||||
,$content
|
||||
);
|
||||
}
|
||||
|
||||
return $this->_importedContent . $content;
|
||||
}
|
||||
|
||||
private function _importCB($m)
|
||||
{
|
||||
$url = $m[1];
|
||||
$mediaList = preg_replace('/\\s+/', '', $m[2]);
|
||||
|
||||
if (strpos($url, '://') > 0) {
|
||||
// protocol, leave in place for CSS, comment for JS
|
||||
return self::$_isCss
|
||||
? $m[0]
|
||||
: "/* Minify_ImportProcessor will not include remote content */";
|
||||
}
|
||||
if ('/' === $url[0]) {
|
||||
// protocol-relative or root path
|
||||
$url = ltrim($url, '/');
|
||||
$file = realpath($_SERVER['DOCUMENT_ROOT']) . DIRECTORY_SEPARATOR
|
||||
. strtr($url, '/', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// relative to current path
|
||||
$file = $this->_currentDir . DIRECTORY_SEPARATOR
|
||||
. strtr($url, '/', DIRECTORY_SEPARATOR);
|
||||
}
|
||||
$obj = new Minify_ImportProcessor(dirname($file));
|
||||
$content = $obj->_getContent($file);
|
||||
if ('' === $content) {
|
||||
// failed. leave in place for CSS, comment for JS
|
||||
return self::$_isCss
|
||||
? $m[0]
|
||||
: "/* Minify_ImportProcessor could not fetch '{$file}' */";;
|
||||
}
|
||||
return (!self::$_isCss || preg_match('@(?:^$|\\ball\\b)@', $mediaList))
|
||||
? $content
|
||||
: "@media {$mediaList} {\n{$content}\n}\n";
|
||||
}
|
||||
|
||||
private function _urlCB($m)
|
||||
{
|
||||
// $m[1] is either quoted or not
|
||||
$quote = ($m[1][0] === "'" || $m[1][0] === '"')
|
||||
? $m[1][0]
|
||||
: '';
|
||||
$url = ($quote === '')
|
||||
? $m[1]
|
||||
: substr($m[1], 1, strlen($m[1]) - 2);
|
||||
if ('/' !== $url[0]) {
|
||||
if (strpos($url, '//') > 0) {
|
||||
// probably starts with protocol, do not alter
|
||||
} else {
|
||||
// prepend path with current dir separator (OS-independent)
|
||||
$path = $this->_currentDir
|
||||
. DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR);
|
||||
// strip doc root
|
||||
$path = substr($path, strlen(realpath($_SERVER['DOCUMENT_ROOT'])));
|
||||
// fix to absolute URL
|
||||
$url = strtr($path, '/\\', '//');
|
||||
// remove /./ and /../ where possible
|
||||
$url = str_replace('/./', '/', $url);
|
||||
// inspired by patch from Oleg Cherniy
|
||||
do {
|
||||
$url = preg_replace('@/[^/]+/\\.\\./@', '/', $url, 1, $changed);
|
||||
} while ($changed);
|
||||
}
|
||||
}
|
||||
return "url({$quote}{$url}{$quote})";
|
||||
}
|
||||
}
|
@@ -1,130 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Lines
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add line numbers in C-style comments for easier debugging of combined content
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
* @author Adam Pedersen (Issue 55 fix)
|
||||
*/
|
||||
class Minify_Lines {
|
||||
|
||||
/**
|
||||
* Add line numbers in C-style comments
|
||||
*
|
||||
* This uses a very basic parser easily fooled by comment tokens inside
|
||||
* strings or regexes, but, otherwise, generally clean code will not be
|
||||
* mangled. URI rewriting can also be performed.
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
* @param array $options available options:
|
||||
*
|
||||
* 'id': (optional) string to identify file. E.g. file name/path
|
||||
*
|
||||
* 'currentDir': (default null) if given, this is assumed to be the
|
||||
* directory of the current CSS file. Using this, minify will rewrite
|
||||
* all relative URIs in import/url declarations to correctly point to
|
||||
* the desired files, and prepend a comment with debugging information about
|
||||
* this process.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function minify($content, $options = array())
|
||||
{
|
||||
$id = (isset($options['id']) && $options['id'])
|
||||
? $options['id']
|
||||
: '';
|
||||
$content = str_replace("\r\n", "\n", $content);
|
||||
$lines = explode("\n", $content);
|
||||
$numLines = count($lines);
|
||||
// determine left padding
|
||||
$padTo = strlen($numLines);
|
||||
$inComment = false;
|
||||
$i = 0;
|
||||
$newLines = array();
|
||||
while (null !== ($line = array_shift($lines))) {
|
||||
if (('' !== $id) && (0 == $i % 50)) {
|
||||
array_push($newLines, '', "/* {$id} */", '');
|
||||
}
|
||||
++$i;
|
||||
$newLines[] = self::_addNote($line, $i, $inComment, $padTo);
|
||||
$inComment = self::_eolInComment($line, $inComment);
|
||||
}
|
||||
$content = implode("\n", $newLines) . "\n";
|
||||
|
||||
// check for desired URI rewriting
|
||||
if (isset($options['currentDir'])) {
|
||||
Minify_CSS_UriRewriter::$debugText = '';
|
||||
$content = Minify_CSS_UriRewriter::rewrite(
|
||||
$content
|
||||
,$options['currentDir']
|
||||
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
||||
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
||||
);
|
||||
$content = "/* Minify_CSS_UriRewriter::\$debugText\n\n"
|
||||
. Minify_CSS_UriRewriter::$debugText . "*/\n"
|
||||
. $content;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the parser within a C-style comment at the end of this line?
|
||||
*
|
||||
* @param string $line current line of code
|
||||
*
|
||||
* @param bool $inComment was the parser in a comment at the
|
||||
* beginning of the line?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function _eolInComment($line, $inComment)
|
||||
{
|
||||
while (strlen($line)) {
|
||||
$search = $inComment
|
||||
? '*/'
|
||||
: '/*';
|
||||
$pos = strpos($line, $search);
|
||||
if (false === $pos) {
|
||||
return $inComment;
|
||||
} else {
|
||||
if ($pos == 0
|
||||
|| ($inComment
|
||||
? substr($line, $pos, 3)
|
||||
: substr($line, $pos-1, 3)) != '*/*')
|
||||
{
|
||||
$inComment = ! $inComment;
|
||||
}
|
||||
$line = substr($line, $pos + 2);
|
||||
}
|
||||
}
|
||||
return $inComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend a comment (or note) to the given line
|
||||
*
|
||||
* @param string $line current line of code
|
||||
*
|
||||
* @param string $note content of note/comment
|
||||
*
|
||||
* @param bool $inComment was the parser in a comment at the
|
||||
* beginning of the line?
|
||||
*
|
||||
* @param int $padTo minimum width of comment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function _addNote($line, $note, $inComment, $padTo)
|
||||
{
|
||||
return $inComment
|
||||
? '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' *| ' . $line
|
||||
: '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' */ ' . $line;
|
||||
}
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Logger
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Message logging class
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_Logger {
|
||||
|
||||
/**
|
||||
* Set logger object.
|
||||
*
|
||||
* The object should have a method "log" that accepts a value as 1st argument and
|
||||
* an optional string label as the 2nd.
|
||||
*
|
||||
* @param mixed $obj or a "falsey" value to disable
|
||||
* @return null
|
||||
*/
|
||||
public static function setLogger($obj = null) {
|
||||
self::$_logger = $obj
|
||||
? $obj
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass a message to the logger (if set)
|
||||
*
|
||||
* @param string $msg message to log
|
||||
* @return null
|
||||
*/
|
||||
public static function log($msg, $label = 'Minify') {
|
||||
if (! self::$_logger) return;
|
||||
self::$_logger->log($msg, $label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var mixed logger object (like FirePHP) or null (i.e. no logger available)
|
||||
*/
|
||||
private static $_logger = null;
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Packer
|
||||
*
|
||||
* To use this class you must first download the PHP port of Packer
|
||||
* and place the file "class.JavaScriptPacker.php" in /lib (or your
|
||||
* include_path).
|
||||
* @link http://joliclic.free.fr/php/javascript-packer/en/
|
||||
*
|
||||
* Be aware that, as long as HTTP encoding is used, scripts minified with JSMin
|
||||
* will provide better client-side performance, as they need not be unpacked in
|
||||
* client-side code.
|
||||
*
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
if (false === (@include 'class.JavaScriptPacker.php')) {
|
||||
trigger_error(
|
||||
'The script "class.JavaScriptPacker.php" is required. Please see: http:'
|
||||
.'//code.google.com/p/minify/source/browse/trunk/min/lib/Minify/Packer.php'
|
||||
,E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Minify Javascript using Dean Edward's Packer
|
||||
*
|
||||
* @package Minify
|
||||
*/
|
||||
class Minify_Packer {
|
||||
public static function minify($code, $options = array())
|
||||
{
|
||||
// @todo: set encoding options based on $options :)
|
||||
$packer = new JavascriptPacker($code, 'Normal', true, false);
|
||||
return trim($packer->pack());
|
||||
}
|
||||
}
|
@@ -1,187 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_Source
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* A content source to be minified by Minify.
|
||||
*
|
||||
* This allows per-source minification options and the mixing of files with
|
||||
* content from other sources.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_Source {
|
||||
|
||||
/**
|
||||
* @var int time of last modification
|
||||
*/
|
||||
public $lastModified = null;
|
||||
|
||||
/**
|
||||
* @var callback minifier function specifically for this source.
|
||||
*/
|
||||
public $minifier = null;
|
||||
|
||||
/**
|
||||
* @var array minification options specific to this source.
|
||||
*/
|
||||
public $minifyOptions = null;
|
||||
|
||||
/**
|
||||
* @var string full path of file
|
||||
*/
|
||||
public $filepath = null;
|
||||
|
||||
/**
|
||||
* @var string HTTP Content Type (Minify requires one of the constants Minify::TYPE_*)
|
||||
*/
|
||||
public $contentType = null;
|
||||
|
||||
/**
|
||||
* Create a Minify_Source
|
||||
*
|
||||
* In the $spec array(), you can either provide a 'filepath' to an existing
|
||||
* file (existence will not be checked!) or give 'id' (unique string for
|
||||
* the content), 'content' (the string content) and 'lastModified'
|
||||
* (unixtime of last update).
|
||||
*
|
||||
* As a shortcut, the controller will replace "//" at the beginning
|
||||
* of a filepath with $_SERVER['DOCUMENT_ROOT'] . '/'.
|
||||
*
|
||||
* @param array $spec options
|
||||
*/
|
||||
public function __construct($spec)
|
||||
{
|
||||
if (isset($spec['filepath'])) {
|
||||
if (0 === strpos($spec['filepath'], '//')) {
|
||||
$spec['filepath'] = $_SERVER['DOCUMENT_ROOT'] . substr($spec['filepath'], 1);
|
||||
}
|
||||
$segments = explode('.', $spec['filepath']);
|
||||
$ext = strtolower(array_pop($segments));
|
||||
switch ($ext) {
|
||||
case 'js' : $this->contentType = 'application/x-javascript';
|
||||
break;
|
||||
case 'css' : $this->contentType = 'text/css';
|
||||
break;
|
||||
case 'htm' : // fallthrough
|
||||
case 'html' : $this->contentType = 'text/html';
|
||||
break;
|
||||
}
|
||||
$this->filepath = $spec['filepath'];
|
||||
$this->_id = $spec['filepath'];
|
||||
$this->lastModified = filemtime($spec['filepath'])
|
||||
// offset for Windows uploaders with out of sync clocks
|
||||
+ round(Minify::$uploaderHoursBehind * 3600);
|
||||
} elseif (isset($spec['id'])) {
|
||||
$this->_id = 'id::' . $spec['id'];
|
||||
if (isset($spec['content'])) {
|
||||
$this->_content = $spec['content'];
|
||||
} else {
|
||||
$this->_getContentFunc = $spec['getContentFunc'];
|
||||
}
|
||||
$this->lastModified = isset($spec['lastModified'])
|
||||
? $spec['lastModified']
|
||||
: time();
|
||||
}
|
||||
if (isset($spec['contentType'])) {
|
||||
$this->contentType = $spec['contentType'];
|
||||
}
|
||||
if (isset($spec['minifier'])) {
|
||||
$this->minifier = $spec['minifier'];
|
||||
}
|
||||
if (isset($spec['minifyOptions'])) {
|
||||
$this->minifyOptions = $spec['minifyOptions'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
$content = (null !== $this->filepath)
|
||||
? file_get_contents($this->filepath)
|
||||
: ((null !== $this->_content)
|
||||
? $this->_content
|
||||
: call_user_func($this->_getContentFunc, $this->_id)
|
||||
);
|
||||
// remove UTF-8 BOM if present
|
||||
return (pack("CCC",0xef,0xbb,0xbf) === substr($content, 0, 3))
|
||||
? substr($content, 3)
|
||||
: $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a single minification call can handle all sources
|
||||
*
|
||||
* @param array $sources Minify_Source instances
|
||||
*
|
||||
* @return bool true iff there no sources with specific minifier preferences.
|
||||
*/
|
||||
public static function haveNoMinifyPrefs($sources)
|
||||
{
|
||||
foreach ($sources as $source) {
|
||||
if (null !== $source->minifier
|
||||
|| null !== $source->minifyOptions) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unique string for a set of sources
|
||||
*
|
||||
* @param array $sources Minify_Source instances
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDigest($sources)
|
||||
{
|
||||
foreach ($sources as $source) {
|
||||
$info[] = array(
|
||||
$source->_id, $source->minifier, $source->minifyOptions
|
||||
);
|
||||
}
|
||||
return md5(serialize($info));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content type from a group of sources
|
||||
*
|
||||
* This is called if the user doesn't pass in a 'contentType' options
|
||||
*
|
||||
* @param array $sources Minify_Source instances
|
||||
*
|
||||
* @return string content type. e.g. 'text/css'
|
||||
*/
|
||||
public static function getContentType($sources)
|
||||
{
|
||||
foreach ($sources as $source) {
|
||||
if ($source->contentType !== null) {
|
||||
return $source->contentType;
|
||||
}
|
||||
}
|
||||
return 'text/plain';
|
||||
}
|
||||
|
||||
protected $_content = null;
|
||||
protected $_getContentFunc = null;
|
||||
protected $_id = null;
|
||||
}
|
||||
|
@@ -1,139 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Minify_YUICompressor
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compress Javascript/CSS using the YUI Compressor
|
||||
*
|
||||
* You must set $jarFile and $tempDir before calling the minify functions.
|
||||
* Also, depending on your shell's environment, you may need to specify
|
||||
* the full path to java in $javaExecutable or use putenv() to setup the
|
||||
* Java environment.
|
||||
*
|
||||
* <code>
|
||||
* Minify_YUICompressor::$jarFile = '/path/to/yuicompressor-2.3.5.jar';
|
||||
* Minify_YUICompressor::$tempDir = '/tmp';
|
||||
* $code = Minify_YUICompressor::minifyJs(
|
||||
* $code
|
||||
* ,array('nomunge' => true, 'line-break' => 1000)
|
||||
* );
|
||||
* </code>
|
||||
*
|
||||
* @todo unit tests, $options docs
|
||||
*
|
||||
* @package Minify
|
||||
* @author Stephen Clay <steve@mrclay.org>
|
||||
*/
|
||||
class Minify_YUICompressor {
|
||||
|
||||
/**
|
||||
* Filepath of the YUI Compressor jar file. This must be set before
|
||||
* calling minifyJs() or minifyCss().
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $jarFile = null;
|
||||
|
||||
/**
|
||||
* Writable temp directory. This must be set before calling minifyJs()
|
||||
* or minifyCss().
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $tempDir = null;
|
||||
|
||||
/**
|
||||
* Filepath of "java" executable (may be needed if not in shell's PATH)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $javaExecutable = 'java';
|
||||
|
||||
/**
|
||||
* Minify a Javascript string
|
||||
*
|
||||
* @param string $js
|
||||
*
|
||||
* @param array $options (verbose is ignored)
|
||||
*
|
||||
* @see http://www.julienlecomte.net/yuicompressor/README
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function minifyJs($js, $options = array())
|
||||
{
|
||||
return self::_minify('js', $js, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Minify a CSS string
|
||||
*
|
||||
* @param string $css
|
||||
*
|
||||
* @param array $options (verbose is ignored)
|
||||
*
|
||||
* @see http://www.julienlecomte.net/yuicompressor/README
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function minifyCss($css, $options = array())
|
||||
{
|
||||
return self::_minify('css', $css, $options);
|
||||
}
|
||||
|
||||
private static function _minify($type, $content, $options)
|
||||
{
|
||||
self::_prepare();
|
||||
if (! ($tmpFile = tempnam(self::$tempDir, 'yuic_'))) {
|
||||
throw new Exception('Minify_YUICompressor : could not create temp file.');
|
||||
}
|
||||
file_put_contents($tmpFile, $content);
|
||||
exec(self::_getCmd($options, $type, $tmpFile), $output);
|
||||
unlink($tmpFile);
|
||||
return implode("\n", $output);
|
||||
}
|
||||
|
||||
private static function _getCmd($userOptions, $type, $tmpFile)
|
||||
{
|
||||
$o = array_merge(
|
||||
array(
|
||||
'charset' => ''
|
||||
,'line-break' => 5000
|
||||
,'type' => $type
|
||||
,'nomunge' => false
|
||||
,'preserve-semi' => false
|
||||
,'disable-optimizations' => false
|
||||
)
|
||||
,$userOptions
|
||||
);
|
||||
$cmd = self::$javaExecutable . ' -jar ' . escapeshellarg(self::$jarFile)
|
||||
. " --type {$type}"
|
||||
. (preg_match('/^[a-zA-Z\\-]+$/', $o['charset'])
|
||||
? " --charset {$o['charset']}"
|
||||
: '')
|
||||
. (is_numeric($o['line-break']) && $o['line-break'] >= 0
|
||||
? ' --line-break ' . (int)$o['line-break']
|
||||
: '');
|
||||
if ($type === 'js') {
|
||||
foreach (array('nomunge', 'preserve-semi', 'disable-optimizations') as $opt) {
|
||||
$cmd .= $o[$opt]
|
||||
? " --{$opt}"
|
||||
: '';
|
||||
}
|
||||
}
|
||||
return $cmd . ' ' . escapeshellarg($tmpFile);
|
||||
}
|
||||
|
||||
private static function _prepare()
|
||||
{
|
||||
if (! is_file(self::$jarFile)
|
||||
|| ! is_dir(self::$tempDir)
|
||||
|| ! is_writable(self::$tempDir)
|
||||
) {
|
||||
throw new Exception('Minify_YUICompressor : $jarFile and $tempDir must be set.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,199 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* Utility class for static directory methods.
|
||||
*
|
||||
* @category Solar
|
||||
*
|
||||
* @package Solar
|
||||
*
|
||||
* @author Paul M. Jones <pmjones@solarphp.com>
|
||||
*
|
||||
* @license http://opensource.org/licenses/bsd-license.php BSD
|
||||
*
|
||||
* @version $Id: Dir.php 2926 2007-11-09 16:25:44Z pmjones $
|
||||
*
|
||||
*/
|
||||
class Solar_Dir {
|
||||
|
||||
/**
|
||||
*
|
||||
* The OS-specific temporary directory location.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
*/
|
||||
protected static $_tmp;
|
||||
|
||||
/**
|
||||
*
|
||||
* Hack for [[php::is_dir() | ]] that checks the include_path.
|
||||
*
|
||||
* Use this to see if a directory exists anywhere in the include_path.
|
||||
*
|
||||
* {{code: php
|
||||
* $dir = Solar_Dir::exists('path/to/dir')
|
||||
* if ($dir) {
|
||||
* $files = scandir($dir);
|
||||
* } else {
|
||||
* echo "Not found in the include-path.";
|
||||
* }
|
||||
* }}
|
||||
*
|
||||
* @param string $dir Check for this directory in the include_path.
|
||||
*
|
||||
* @return mixed If the directory exists in the include_path, returns the
|
||||
* absolute path; if not, returns boolean false.
|
||||
*
|
||||
*/
|
||||
public static function exists($dir)
|
||||
{
|
||||
// no file requested?
|
||||
$dir = trim($dir);
|
||||
if (! $dir) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// using an absolute path for the file?
|
||||
// dual check for Unix '/' and Windows '\',
|
||||
// or Windows drive letter and a ':'.
|
||||
$abs = ($dir[0] == '/' || $dir[0] == '\\' || $dir[1] == ':');
|
||||
if ($abs && is_dir($dir)) {
|
||||
return $dir;
|
||||
}
|
||||
|
||||
// using a relative path on the file
|
||||
$path = explode(PATH_SEPARATOR, ini_get('include_path'));
|
||||
foreach ($path as $base) {
|
||||
// strip Unix '/' and Windows '\'
|
||||
$target = rtrim($base, '\\/') . DIRECTORY_SEPARATOR . $dir;
|
||||
if (is_dir($target)) {
|
||||
return $target;
|
||||
}
|
||||
}
|
||||
|
||||
// never found it
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* "Fixes" a directory string for the operating system.
|
||||
*
|
||||
* Use slashes anywhere you need a directory separator. Then run the
|
||||
* string through fixdir() and the slashes will be converted to the
|
||||
* proper separator (for example '\' on Windows).
|
||||
*
|
||||
* Always adds a final trailing separator.
|
||||
*
|
||||
* @param string $dir The directory string to 'fix'.
|
||||
*
|
||||
* @return string The "fixed" directory string.
|
||||
*
|
||||
*/
|
||||
public static function fix($dir)
|
||||
{
|
||||
$dir = str_replace('/', DIRECTORY_SEPARATOR, $dir);
|
||||
return rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Convenience method for dirname() and higher-level directories.
|
||||
*
|
||||
* @param string $file Get the dirname() of this file.
|
||||
*
|
||||
* @param int $up Move up in the directory structure this many
|
||||
* times, default 0.
|
||||
*
|
||||
* @return string The dirname() of the file.
|
||||
*
|
||||
*/
|
||||
public static function name($file, $up = 0)
|
||||
{
|
||||
$dir = dirname($file);
|
||||
while ($up --) {
|
||||
$dir = dirname($dir);
|
||||
}
|
||||
return $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the OS-specific directory for temporary files.
|
||||
*
|
||||
* @param string $sub Add this subdirectory to the returned temporary
|
||||
* directory name.
|
||||
*
|
||||
* @return string The temporary directory path.
|
||||
*
|
||||
*/
|
||||
public static function tmp($sub = '')
|
||||
{
|
||||
// find the tmp dir if needed
|
||||
if (! Solar_Dir::$_tmp) {
|
||||
|
||||
// use the system if we can
|
||||
if (function_exists('sys_get_temp_dir')) {
|
||||
$tmp = sys_get_temp_dir();
|
||||
} else {
|
||||
$tmp = Solar_Dir::_tmp();
|
||||
}
|
||||
|
||||
// remove trailing separator and save
|
||||
Solar_Dir::$_tmp = rtrim($tmp, DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
// do we have a subdirectory request?
|
||||
$sub = trim($sub);
|
||||
if ($sub) {
|
||||
// remove leading and trailing separators, and force exactly
|
||||
// one trailing separator
|
||||
$sub = trim($sub, DIRECTORY_SEPARATOR)
|
||||
. DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
return Solar_Dir::$_tmp . DIRECTORY_SEPARATOR . $sub;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the OS-specific temporary directory location.
|
||||
*
|
||||
* @return string The temp directory path.
|
||||
*
|
||||
*/
|
||||
protected static function _tmp()
|
||||
{
|
||||
// non-Windows system?
|
||||
if (strtolower(substr(PHP_OS, 0, 3)) != 'win') {
|
||||
$tmp = empty($_ENV['TMPDIR']) ? getenv('TMPDIR') : $_ENV['TMPDIR'];
|
||||
if ($tmp) {
|
||||
return $tmp;
|
||||
} else {
|
||||
return '/tmp';
|
||||
}
|
||||
}
|
||||
|
||||
// Windows 'TEMP'
|
||||
$tmp = empty($_ENV['TEMP']) ? getenv('TEMP') : $_ENV['TEMP'];
|
||||
if ($tmp) {
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
// Windows 'TMP'
|
||||
$tmp = empty($_ENV['TMP']) ? getenv('TMP') : $_ENV['TMP'];
|
||||
if ($tmp) {
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
// Windows 'windir'
|
||||
$tmp = empty($_ENV['windir']) ? getenv('windir') : $_ENV['windir'];
|
||||
if ($tmp) {
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
// final fallback for Windows
|
||||
return getenv('SystemRoot') . '\\temp';
|
||||
}
|
||||
}
|
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Include for serving HTML pages through Minify
|
||||
*
|
||||
* DO NOT EDIT! Configure this utility via pageConfig.php
|
||||
*
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
$_min_preIncludedFiles = get_included_files();
|
||||
|
||||
function min_autoload($name) {
|
||||
require str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php';
|
||||
}
|
||||
spl_autoload_register('min_autoload');
|
||||
|
||||
function ob_minify_page($content) {
|
||||
global $min_serveOptions, $min_cacheMaxAge;
|
||||
|
||||
$includedFiles = array_diff(
|
||||
$GLOBALS['_min_preIncludedFiles'], get_included_files()
|
||||
);
|
||||
$includedFiles[] = realpath($_SERVER['SCRIPT_FILENAME']);
|
||||
$mtime = 0;
|
||||
foreach ($includedFiles as $file) {
|
||||
$mtime = max($mtime, filemtime($file));
|
||||
}
|
||||
|
||||
define('MINIFY_MIN_DIR', dirname(__FILE__));
|
||||
|
||||
// load config
|
||||
require MINIFY_MIN_DIR . '/pageConfig.php';
|
||||
|
||||
// setup include path
|
||||
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
Minify::$uploaderHoursBehind = $min_uploaderHoursBehind;
|
||||
Minify::setCache(
|
||||
isset($min_cachePath) ? $min_cachePath : ''
|
||||
,$min_cacheFileLocking
|
||||
);
|
||||
|
||||
if ($min_errorLogger) {
|
||||
if (true === $min_errorLogger) {
|
||||
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
||||
} else {
|
||||
Minify_Logger::setLogger($min_errorLogger);
|
||||
}
|
||||
}
|
||||
|
||||
// some array keys may already be set in globals
|
||||
$min_serveOptions['id'] = $_SERVER['SCRIPT_FILENAME'];
|
||||
$min_serveOptions['content'] = $content;
|
||||
$min_serveOptions['lastModified'] = $mtime;
|
||||
$min_serveOptions['minifyAll'] = true;
|
||||
$min_serveOptions['quiet'] = true;
|
||||
|
||||
// page option: $min_lastModified
|
||||
if (isset($GLOBALS['min_lastModified'])) {
|
||||
$min_serveOptions['lastModified'] = $GLOBALS['min_lastModified'];
|
||||
}
|
||||
|
||||
if ($min_cacheMaxAge) {
|
||||
$min_serveOptions['lastModified'] = _steppedTime(
|
||||
$min_cacheMaxAge, $_SERVER['SCRIPT_FILENAME']);
|
||||
}
|
||||
|
||||
$out = Minify::serve('Page', $min_serveOptions);
|
||||
|
||||
foreach ($out['headers'] as $prop => $value) {
|
||||
header($prop === '_responseCode' ? $value : "{$prop}: {$value}");
|
||||
}
|
||||
return $out['content'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a stepped version of time with a random-like constistent offset
|
||||
*
|
||||
* This emulates the mtime() of a file being modified regularly. The offset
|
||||
* allows you to use the same period in several instances without them all
|
||||
* stepping up simultaneously. Offsets should be evenly distributed.
|
||||
*
|
||||
* @param int $period in seconds
|
||||
* @param string $instanceId
|
||||
* @return int
|
||||
*/
|
||||
function _steppedTime($period, $instanceId = '') {
|
||||
$hashInt = hexdec(substr(md5($instanceId), 0, 8));
|
||||
$t = $_SERVER['REQUEST_TIME'];
|
||||
return $t - ($t % $period) - ($hashInt % $period);
|
||||
}
|
||||
|
||||
ob_start('ob_minify_page');
|
@@ -1,82 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Configuration for pageBuffer.php
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Set to true to log messages to FirePHP (Firefox Firebug addon).
|
||||
* Set to false for no error logging (Minify may be slightly faster).
|
||||
* @link http://www.firephp.org/
|
||||
*
|
||||
* If you want to use a custom error logger, set this to your logger
|
||||
* instance. Your object should have a method log(string $message).
|
||||
*
|
||||
* @todo cache system does not have error logging yet.
|
||||
*/
|
||||
$min_errorLogger = false;
|
||||
|
||||
|
||||
/**
|
||||
* For best performance, specify your temp directory here. Otherwise Minify
|
||||
* will have to load extra code to guess. Some examples below:
|
||||
*/
|
||||
//$min_cachePath = 'c:\\WINDOWS\\Temp';
|
||||
//$min_cachePath = '/tmp';
|
||||
//$min_cachePath = preg_replace('/^\\d+;/', '', session_save_path());
|
||||
|
||||
|
||||
/**
|
||||
* Cache file locking. Set to false if filesystem is NFS. On at least one
|
||||
* NFS system flock-ing attempts stalled PHP for 30 seconds!
|
||||
*/
|
||||
$min_cacheFileLocking = true;
|
||||
|
||||
|
||||
/**
|
||||
* Maximum age of browser cache in seconds. After this period, the browser
|
||||
* will send another conditional GET. Use a longer period for lower traffic
|
||||
* but you may want to shorten this before making changes if it's crucial
|
||||
* those changes are seen immediately.
|
||||
*/
|
||||
$min_serveOptions['maxAge'] = 1800;
|
||||
|
||||
|
||||
/**
|
||||
* By default Minify will check the mtime of the loaded page and any pages it
|
||||
* includes to determine the last modified time. If you would rather have it
|
||||
* regularly rebuild the cache, set this to the period, in seconds, that the
|
||||
* cache should be rebuilt (note this only occurs if a request is made).
|
||||
*/
|
||||
$min_cacheMaxAge = false;
|
||||
|
||||
|
||||
/**
|
||||
* If you upload files from Windows to a non-Windows server, Windows may report
|
||||
* incorrect mtimes for the files. This may cause Minify to keep serving stale
|
||||
* cache files when source file changes are made too frequently (e.g. more than
|
||||
* once an hour).
|
||||
*
|
||||
* Immediately after modifying and uploading a file, use the touch command to
|
||||
* update the mtime on the server. If the mtime jumps ahead by a number of hours,
|
||||
* set this variable to that number. If the mtime moves back, this should not be
|
||||
* needed.
|
||||
*
|
||||
* In the Windows SFTP client WinSCP, there's an option that may fix this
|
||||
* issue without changing the variable below. Under login > environment,
|
||||
* select the option "Adjust remote timestamp with DST".
|
||||
* @link http://winscp.net/eng/docs/ui_login_environment#daylight_saving_time
|
||||
*/
|
||||
$min_uploaderHoursBehind = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Path to Minify's lib folder. If you happen to move it, change
|
||||
* this accordingly.
|
||||
*/
|
||||
$min_libPath = dirname(__FILE__) . '/lib';
|
||||
|
||||
|
||||
// try to disable output_compression (may not have an effect)
|
||||
ini_set('zlib.output_compression', '0');
|
@@ -1,182 +0,0 @@
|
||||
<?php
|
||||
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
require dirname(__FILE__) . '/../config.php';
|
||||
|
||||
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
// set cache path and doc root if configured
|
||||
$minifyCachePath = isset($min_cachePath)
|
||||
? $min_cachePath
|
||||
: '';
|
||||
|
||||
if ($min_documentRoot) {
|
||||
$_SERVER['DOCUMENT_ROOT'] = $min_documentRoot;
|
||||
} elseif (0 === stripos(PHP_OS, 'win')) {
|
||||
require_once 'Minify.php';
|
||||
Minify::setDocRoot(); // IIS may need help
|
||||
}
|
||||
$_SERVER['DOCUMENT_ROOT'] = rtrim($_SERVER['DOCUMENT_ROOT'], '/\\');
|
||||
|
||||
// default log to FirePHP
|
||||
require_once 'Minify/Logger.php';
|
||||
require_once 'FirePHP.php';
|
||||
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
||||
|
||||
if (! isset($min_cachePath)) {
|
||||
$min_cachePath = '';
|
||||
}
|
||||
// code in Minify::setCache()
|
||||
if (is_string($min_cachePath)) {
|
||||
require_once 'Minify/Cache/File.php';
|
||||
$cache = new Minify_Cache_File($min_cachePath, $min_cacheFileLocking);
|
||||
} else {
|
||||
$cache = $min_cachePath;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pTest - PHP Unit Tester
|
||||
* @param mixed $test Condition to test, evaluated as boolean
|
||||
* @param string $html Descriptive message to output upon test
|
||||
* @url http://www.sitepoint.com/blogs/2007/08/13/ptest-php-unit-tester-in-9-lines-of-code/
|
||||
* @return bool success
|
||||
*/
|
||||
function assertTrue($test, $html)
|
||||
{
|
||||
$outMode = $test ? 'PASS' : '!FAIL';
|
||||
$class = $test ? 'assert pass' : 'assert fail';
|
||||
printf("<p class='%s'><strong>%s</strong>: %s</p>", $class, $outMode, $html);
|
||||
return (bool)$test;
|
||||
}
|
||||
|
||||
function h($txt)
|
||||
{
|
||||
return htmlspecialchars($txt);
|
||||
}
|
||||
|
||||
function e($value)
|
||||
{
|
||||
return htmlspecialchars(var_export($value, 1));
|
||||
}
|
||||
|
||||
function _gzdecode($data)
|
||||
{
|
||||
$filename = $error = '';
|
||||
return _phpman_gzdecode($data, $filename, $error);
|
||||
}
|
||||
|
||||
// http://www.php.net/manual/en/function.gzdecode.php#82930
|
||||
function _phpman_gzdecode($data, &$filename='', &$error='', $maxlength=null)
|
||||
{
|
||||
$len = strlen($data);
|
||||
if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) {
|
||||
$error = "Not in GZIP format.";
|
||||
return null; // Not GZIP format (See RFC 1952)
|
||||
}
|
||||
$method = ord(substr($data,2,1)); // Compression method
|
||||
$flags = ord(substr($data,3,1)); // Flags
|
||||
if ($flags & 31 != $flags) {
|
||||
$error = "Reserved bits not allowed.";
|
||||
return null;
|
||||
}
|
||||
// NOTE: $mtime may be negative (PHP integer limitations)
|
||||
$mtime = unpack("V", substr($data,4,4));
|
||||
$mtime = $mtime[1];
|
||||
$xfl = substr($data,8,1);
|
||||
$os = substr($data,8,1);
|
||||
$headerlen = 10;
|
||||
$extralen = 0;
|
||||
$extra = "";
|
||||
if ($flags & 4) {
|
||||
// 2-byte length prefixed EXTRA data in header
|
||||
if ($len - $headerlen - 2 < 8) {
|
||||
return false; // invalid
|
||||
}
|
||||
$extralen = unpack("v",substr($data,8,2));
|
||||
$extralen = $extralen[1];
|
||||
if ($len - $headerlen - 2 - $extralen < 8) {
|
||||
return false; // invalid
|
||||
}
|
||||
$extra = substr($data,10,$extralen);
|
||||
$headerlen += 2 + $extralen;
|
||||
}
|
||||
$filenamelen = 0;
|
||||
$filename = "";
|
||||
if ($flags & 8) {
|
||||
// C-style string
|
||||
if ($len - $headerlen - 1 < 8) {
|
||||
return false; // invalid
|
||||
}
|
||||
$filenamelen = strpos(substr($data,$headerlen),chr(0));
|
||||
if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {
|
||||
return false; // invalid
|
||||
}
|
||||
$filename = substr($data,$headerlen,$filenamelen);
|
||||
$headerlen += $filenamelen + 1;
|
||||
}
|
||||
$commentlen = 0;
|
||||
$comment = "";
|
||||
if ($flags & 16) {
|
||||
// C-style string COMMENT data in header
|
||||
if ($len - $headerlen - 1 < 8) {
|
||||
return false; // invalid
|
||||
}
|
||||
$commentlen = strpos(substr($data,$headerlen),chr(0));
|
||||
if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {
|
||||
return false; // Invalid header format
|
||||
}
|
||||
$comment = substr($data,$headerlen,$commentlen);
|
||||
$headerlen += $commentlen + 1;
|
||||
}
|
||||
$headercrc = "";
|
||||
if ($flags & 2) {
|
||||
// 2-bytes (lowest order) of CRC32 on header present
|
||||
if ($len - $headerlen - 2 < 8) {
|
||||
return false; // invalid
|
||||
}
|
||||
$calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;
|
||||
$headercrc = unpack("v", substr($data,$headerlen,2));
|
||||
$headercrc = $headercrc[1];
|
||||
if ($headercrc != $calccrc) {
|
||||
$error = "Header checksum failed.";
|
||||
return false; // Bad header CRC
|
||||
}
|
||||
$headerlen += 2;
|
||||
}
|
||||
// GZIP FOOTER
|
||||
$datacrc = unpack("V",substr($data,-8,4));
|
||||
$datacrc = sprintf('%u',$datacrc[1] & 0xFFFFFFFF);
|
||||
$isize = unpack("V",substr($data,-4));
|
||||
$isize = $isize[1];
|
||||
// decompression:
|
||||
$bodylen = $len-$headerlen-8;
|
||||
if ($bodylen < 1) {
|
||||
// IMPLEMENTATION BUG!
|
||||
return null;
|
||||
}
|
||||
$body = substr($data,$headerlen,$bodylen);
|
||||
$data = "";
|
||||
if ($bodylen > 0) {
|
||||
switch ($method) {
|
||||
case 8:
|
||||
// Currently the only supported compression method:
|
||||
$data = gzinflate($body,$maxlength);
|
||||
break;
|
||||
default:
|
||||
$error = "Unknown compression method.";
|
||||
return false;
|
||||
}
|
||||
} // zero-byte body content is allowed
|
||||
// Verifiy CRC32
|
||||
$crc = sprintf("%u",crc32($data));
|
||||
$crcOK = $crc == $datacrc;
|
||||
$lenOK = $isize == strlen($data);
|
||||
if (!$lenOK || !$crcOK) {
|
||||
$error = ( $lenOK ? '' : 'Length check FAILED. ') . ( $crcOK ? '' : 'Checksum FAILED.');
|
||||
return false;
|
||||
}
|
||||
return $data;
|
||||
}
|
@@ -1,161 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
||||
// called directly
|
||||
if (isset($_GET['getOutputCompression'])) {
|
||||
echo (int)ini_get('zlib.output_compression');
|
||||
exit();
|
||||
}
|
||||
if (isset($_GET['hello'])) {
|
||||
// try to disable (may not work)
|
||||
ini_set('zlib.output_compression', '0');
|
||||
echo 'World!';
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
$origDocRoot = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once '_inc.php';
|
||||
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
|
||||
?><!doctype html>
|
||||
<title>Minify server environment/config tests</title>
|
||||
<style>
|
||||
.assert {margin:1em 0 0}
|
||||
.assert + .assert {margin:0}
|
||||
.pass strong {color:#090}
|
||||
.fail strong, .warn strong {color:#c00}
|
||||
dt {margin-top:.5em; font-weight:bold}
|
||||
</style>
|
||||
<h1>Minify server environment/config tests</h1>
|
||||
|
||||
<h2>Document Root</h2>
|
||||
<dl>
|
||||
<dt>Original <code>$_SERVER['DOCUMENT_ROOT']</code> (set by PHP/env)</dt>
|
||||
<dd><code><?= e($origDocRoot) ?></code></dd>
|
||||
<dt>Current <code>$_SERVER['DOCUMENT_ROOT']</code> (altered by Minify/your config.php)</dt>
|
||||
<dd><code><?= e($_SERVER['DOCUMENT_ROOT']) ?></code></dd>
|
||||
<dt><code>realpath($_SERVER['DOCUMENT_ROOT'])</code></dt>
|
||||
<dd><code><?= e(realpath($_SERVER['DOCUMENT_ROOT'])) ?></code></dd>
|
||||
<dt><code>__FILE__</code></dt>
|
||||
<dd><code><?= e(__FILE__) ?></code></dd>
|
||||
</dl>
|
||||
<?php
|
||||
|
||||
if (isset($_SERVER['SUBDOMAIN_DOCUMENT_ROOT'])) {
|
||||
echo "<p class='assert note'><strong>!NOTE</strong>: <code>\$_SERVER['SUBDOMAIN_DOCUMENT_ROOT']</code>"
|
||||
. " is set to " . e($_SERVER['SUBDOMAIN_DOCUMENT_ROOT']) . ". You may need to set"
|
||||
. " <code>\$min_documentRoot</code> to this in config.php.</p>";
|
||||
}
|
||||
|
||||
$passed = assertTrue(
|
||||
0 === strpos(__FILE__, realpath($_SERVER['DOCUMENT_ROOT']))
|
||||
,'<code>__FILE__</code> is within realpath of docroot'
|
||||
);
|
||||
if ($passed) {
|
||||
$thisPath = str_replace(
|
||||
'\\'
|
||||
,'/'
|
||||
,substr(__FILE__, strlen(realpath($_SERVER['DOCUMENT_ROOT'])))
|
||||
);
|
||||
} else {
|
||||
// try HTTP requests anyway
|
||||
$thisPath = '/min/test/index.php';
|
||||
}
|
||||
|
||||
if ($thisPath !== '/min/test/index.php') {
|
||||
echo "<p class='assert note'><strong>!NOTE</strong>: /min/ is not directly inside DOCUMENT_ROOT.</p>";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<h2>HTTP Encoding</h2>
|
||||
<?php
|
||||
|
||||
$thisUrl = 'http://'
|
||||
. $_SERVER['HTTP_HOST'] // avoid redirects when SERVER_NAME doesn't match
|
||||
. ('80' === $_SERVER['SERVER_PORT'] ? '' : ":{$_SERVER['SERVER_PORT']}")
|
||||
. $thisPath;
|
||||
|
||||
$oc = @file_get_contents($thisUrl . '?getOutputCompression=1');
|
||||
|
||||
if (false === $oc || ! preg_match('/^[01]$/', $oc)) {
|
||||
echo "<p class='assert warn'><strong>!WARN</strong>: Local HTTP request failed. Testing cannot continue.</p>";
|
||||
} else {
|
||||
if ('1' === $oc) {
|
||||
echo "<p class='assert note'><strong>!NOTE</strong>: zlib.output_compression"
|
||||
. " was enabled by default, but this is OK if the next test passes.</p>";
|
||||
}
|
||||
|
||||
$fp = fopen($thisUrl . '?hello=1', 'r', false, stream_context_create(array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'header' => "Accept-Encoding: deflate, gzip\r\n"
|
||||
)
|
||||
)));
|
||||
|
||||
$meta = stream_get_meta_data($fp);
|
||||
|
||||
$passed = true;
|
||||
foreach ($meta['wrapper_data'] as $i => $header) {
|
||||
if ((preg_match('@^Content-Length: (\\d+)$@i', $header, $m) && $m[1] !== '6')
|
||||
|| preg_match('@^Content-Encoding:@i', $header, $m)
|
||||
) {
|
||||
$passed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($passed && stream_get_contents($fp) !== 'World!') {
|
||||
$passed = false;
|
||||
}
|
||||
assertTrue(
|
||||
$passed
|
||||
,'PHP/server can serve non-encoded content'
|
||||
);
|
||||
fclose($fp);
|
||||
|
||||
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
||||
if (! $passed) {
|
||||
echo "<p>Returned content should be 6 bytes and not HTTP encoded.<br>"
|
||||
. "Headers returned by: <code>" . h($thisUrl . '?hello=1') . "</code></p>"
|
||||
. "<pre><code>" . h(var_export($meta['wrapper_data'], 1)) . "</code></pre>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (assertTrue(function_exists('gzencode'), 'gzencode() exists')) {
|
||||
// test encode/decode
|
||||
$data = str_repeat(md5('testing'), 160);
|
||||
$gzipped = @gzencode($data, 6);
|
||||
assertTrue(is_string($gzipped) && strlen($gzipped) < strlen($data), 'gzip works');
|
||||
assertTrue(_gzdecode($gzipped) === $data, 'gzdecode works');
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<h2>Cache</h2>
|
||||
<dl>
|
||||
<dt><code>$min_cachePath</code> in config.php</dt>
|
||||
<dd><code><?= e($min_cachePath) ?></code></dd>
|
||||
<dt>Resulting cache object</dt>
|
||||
<dd><pre><code><?= e($cache) ?></code></pre></dd>
|
||||
</dl>
|
||||
<?php
|
||||
|
||||
if ($min_cachePath === '') {
|
||||
echo "<p class='assert'><strong>!NOTE</strong>: Consider setting <code>\$min_cachePath</code> for best performance.</p>";
|
||||
}
|
||||
|
||||
$data = str_repeat(md5('testing'), 160);
|
||||
$id = 'Minify_test_cache';
|
||||
assertTrue(true === $cache->store($id, $data), 'Cache store');
|
||||
assertTrue(strlen($data) === $cache->getSize($id), 'Cache getSize');
|
||||
assertTrue(true === $cache->isValid($id, $_SERVER['REQUEST_TIME'] - 10), 'Cache isValid');
|
||||
ob_start();
|
||||
$cache->display($id);
|
||||
$displayed = ob_get_contents();
|
||||
ob_end_clean();
|
||||
assertTrue($data === $displayed, 'Cache display');
|
||||
assertTrue($data === $cache->fetch($id), 'Cache fetch');
|
@@ -1,96 +0,0 @@
|
||||
<?php
|
||||
require '../pageBuffer.php';
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
|
||||
<head>
|
||||
<!-- comments get removed -->
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<meta name="author" content="Dave Shea" />
|
||||
<!-- also whitespace around block or undisplayed elements -->
|
||||
<meta name="keywords" content="design, css, cascading, style, sheets, xhtml, graphic design, w3c, web standards, visual, display" />
|
||||
<meta name="description" content="A demonstration of what can be accomplished visually through CSS-based design." />
|
||||
<meta name="robots" content="all" />
|
||||
<title>css Zen Garden: The Beauty in CSS Design</title>
|
||||
|
||||
<!-- to correct the unsightly Flash of Unstyled Content. http://www.bluerobot.com/web/css/fouc.asp -->
|
||||
<script type="text/javascript"><!--
|
||||
// js comment inside SCRIPT element
|
||||
var is = {
|
||||
ie: navigator.appName == 'Microsoft Internet Explorer',
|
||||
java: navigator.javaEnabled(),
|
||||
ns: navigator.appName == 'Netscape',
|
||||
ua: navigator.userAgent.toLowerCase(),
|
||||
version: parseFloat(navigator.appVersion.substr(21)) ||
|
||||
parseFloat(navigator.appVersion),
|
||||
win: navigator.platform == 'Win32'
|
||||
}
|
||||
is.mac = is.ua.indexOf('mac') >= 0;
|
||||
if (is.ua.indexOf('opera') >= 0) {
|
||||
is.ie = is.ns = false;
|
||||
is.opera = true;
|
||||
}
|
||||
if (is.ua.indexOf('gecko') >= 0) {
|
||||
is.ie = is.ns = false;
|
||||
is.gecko = true;
|
||||
}
|
||||
// --></script>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var i = 0;
|
||||
while (++i < 10)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
/* <![CDATA[ */ i = 1; /* ]]> */
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
(i < 1); /* CDATA needed */
|
||||
</script>
|
||||
<!--[if IE 6]>
|
||||
<style type="text/css">
|
||||
/*! copyright: you'll need CDATA for this < & */
|
||||
body {background:white;}
|
||||
</style>
|
||||
<![endif]-->
|
||||
<style type="text/css" title="currentStyle" media="screen">
|
||||
@import "/001/001.css";
|
||||
/*\*/ css hack {} /* */
|
||||
/* normal CSS comment */
|
||||
/*/*/ css hack {} /* */
|
||||
css hack {
|
||||
display/**/:/**/none;
|
||||
display:none;
|
||||
}
|
||||
</style>
|
||||
<link
|
||||
rel="alternate"
|
||||
type="application/rss+xml"
|
||||
title="RSS"
|
||||
href="http://www.csszengarden.com/zengarden.xml" />
|
||||
</head>
|
||||
<body id="css-zen-garden">
|
||||
<!--[if !IE]>--><p>Browser != IE</p><!--<![endif]-->
|
||||
<div id="container">
|
||||
<div id="pageHeader">
|
||||
<h1><span>css Zen Garden</span></h1>
|
||||
<h2><span>The Beauty of <acronym title="Cascading Style Sheets">CSS</acronym>
|
||||
Design</span></h2>
|
||||
</div>
|
||||
<pre>
|
||||
White space is important here!
|
||||
</pre>
|
||||
<div id="quickSummary">
|
||||
<p class="p1"><span>A demonstration of what can be accomplished visually through <acronym title="Cascading Style Sheets">CSS</acronym>-based design. Select any style sheet from the list to load it into this page.</span></p>
|
||||
<p class="p2"><span>Download the sample <a href="/zengarden-sample.html" title="This page's source HTML code, not to be modified.">html file</a> and <a href="/zengarden-sample.css" title="This page's sample CSS, the file you may modify.">css file</a></span></p>
|
||||
</div>
|
||||
<textarea name="comment" id="comment" rows="6" class="maxwidth" cols="80">66666
|
||||
|
||||
1234567890</textarea>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Utility functions for generating group URIs in HTML files
|
||||
*
|
||||
* Before including this file, /min/lib must be in your include_path.
|
||||
*
|
||||
* @package Minify
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Get a timestamped URI to a minified resource using the default Minify install
|
||||
*
|
||||
* <code>
|
||||
* <link rel="stylesheet" type="text/css" href="<?php echo Minify_groupUri('css'); ?>" />
|
||||
* <script type="text/javascript" src="<?php echo Minify_groupUri('js'); ?>"></script>
|
||||
* </code>
|
||||
*
|
||||
* If you do not want ampersands as HTML entities, set Minify_Build::$ampersand = "&"
|
||||
* before using this function.
|
||||
*
|
||||
* @param string $group a key (or comma-separated keys) from groupsConfig.php
|
||||
* @param boolean $forceAmpersand (default false) Set to true if the RewriteRule
|
||||
* directives in .htaccess are functional. This will remove the "?" from URIs, making them
|
||||
* more cacheable by proxies.
|
||||
* @return string
|
||||
*/
|
||||
function Minify_groupUri($group, $forceAmpersand = false)
|
||||
{
|
||||
$path = $forceAmpersand
|
||||
? "/g={$group}"
|
||||
: "/?g={$group}";
|
||||
return _Minify_getBuild($group)->uri(
|
||||
'/' . basename(dirname(__FILE__)) . $path
|
||||
,$forceAmpersand
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the last modification time of the source js/css files used by Minify to
|
||||
* build the page.
|
||||
*
|
||||
* If you're caching the output of Minify_groupUri(), you'll want to rebuild
|
||||
* the cache if it's older than this timestamp.
|
||||
*
|
||||
* <code>
|
||||
* // simplistic HTML cache system
|
||||
* $file = '/path/to/cache/file';
|
||||
* if (! file_exists($file) || filemtime($file) < Minify_groupsMtime(array('js', 'css'))) {
|
||||
* // (re)build cache
|
||||
* $page = buildPage(); // this calls Minify_groupUri() for js and css
|
||||
* file_put_contents($file, $page);
|
||||
* echo $page;
|
||||
* exit();
|
||||
* }
|
||||
* readfile($file);
|
||||
* </code>
|
||||
*
|
||||
* @param array $groups an array of keys from groupsConfig.php
|
||||
* @return int Unix timestamp of the latest modification
|
||||
*/
|
||||
function Minify_groupsMtime($groups)
|
||||
{
|
||||
$max = 0;
|
||||
foreach ((array)$groups as $group) {
|
||||
$max = max($max, _Minify_getBuild($group)->lastModified);
|
||||
}
|
||||
return $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $group a key (or comma-separated keys) from groupsConfig.php
|
||||
* @return Minify_Build
|
||||
* @private
|
||||
*/
|
||||
function _Minify_getBuild($group)
|
||||
{
|
||||
static $builds = array();
|
||||
static $gc = false;
|
||||
if (false === $gc) {
|
||||
$gc = (require dirname(__FILE__) . '/groupsConfig.php');
|
||||
}
|
||||
if (! isset($builds[$group])) {
|
||||
$sources = array();
|
||||
foreach (explode(',', $group) as $key) {
|
||||
$val = $gc[$key];
|
||||
if (is_array($val)) {
|
||||
array_splice($sources, count($sources), 0, $val);
|
||||
} else {
|
||||
$sources[] = $val;
|
||||
}
|
||||
}
|
||||
$builds[$group] = new Minify_Build($sources);
|
||||
}
|
||||
return $builds[$group];
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
DO NOT leave this directory on a site in production. Some scripts within may be
|
||||
resource intensive and some allow file uploads.
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
This directory contains testing scripts and a few example applications built
|
||||
with the Minify library classes.
|
||||
|
||||
ab_tests/
|
||||
Windows batch files used to benchmark various Minify and Apache
|
||||
configurations using Apache ab.
|
||||
|
||||
tools/
|
||||
Two utility web apps that upload a file, alter it, and send it back to the
|
||||
user. One applies HTTP encoding, the other minifies CSS/JS/HTML.
|
@@ -1,10 +0,0 @@
|
||||
This is a little AB testing setup for Windows. Before committing any non-trivial
|
||||
change, these tests should be run so "results_summary.txt" will be an up-to-date
|
||||
document of each revision's performance.
|
||||
|
||||
Before testing make sure all cache locations are correct.
|
||||
|
||||
Double-click "test_all.bat" to run the tests. At the end, "results_summary.txt"
|
||||
will be opened in notepad. For more details see "results.txt".
|
||||
|
||||
Delete "results.txt" before committing. We don't need this much info in svn.
|
@@ -1,3 +0,0 @@
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* The goal with this file is to benchmark serving the file doing the absolute
|
||||
* least operations possible. E.g. we know we'll have to check for the file,
|
||||
* check its size and the mtimes of it and the src file.
|
||||
*/
|
||||
|
||||
$src = realpath(dirname(__FILE__) . '/../minify/before.js');
|
||||
$cached = realpath(dirname(__FILE__) . '/../type-map') . '/before.js.zd';
|
||||
|
||||
// clearstatcache() takes over 2ms on Athlon 64 X2 5600+! Avoid at all costs!
|
||||
//clearstatcache();
|
||||
|
||||
filemtime($src);
|
||||
file_exists($cached);
|
||||
filemtime($cached);
|
||||
|
||||
header('Cache-Control: public, max-age=31536000');
|
||||
header('Expires: '. gmdate('D, d M Y H:i:s \G\M\T', $_SERVER['REQUEST_TIME'] + (86400 * 365)));
|
||||
header('Content-Type: application/x-javascript; charset=utf-8');
|
||||
header('Content-Encoding: deflate');
|
||||
header('Content-Length: ' . filesize($cached));
|
||||
header('Vary: Accept-Encoding');
|
||||
|
||||
readfile($cached);
|
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
require '../../config.php';
|
||||
|
||||
// set in /min/config.php
|
||||
Minify::setCache($minifyCachePath);
|
||||
|
||||
Minify::serve('Files', array(
|
||||
'files' => array(
|
||||
dirname(__FILE__) . '/before.js'
|
||||
)
|
||||
,'maxAge' => 31536000 // 1 yr
|
||||
));
|
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
require '../../config.php';
|
||||
|
||||
|
||||
$mc = new Memcache;
|
||||
if (! @$mc->connect('localhost', 11211)) {
|
||||
file_put_contents(
|
||||
dirname(__FILE__) . '/../memcached_stats.txt'
|
||||
,"\nFailed connection.\n"
|
||||
,FILE_APPEND
|
||||
);
|
||||
die();
|
||||
}
|
||||
|
||||
if (0 == rand(0, 19)) {
|
||||
$stats = $mc->getStats();
|
||||
file_put_contents(
|
||||
dirname(__FILE__) . '/../memcached_stats.txt'
|
||||
,$stats['curr_connections'] . "\n"
|
||||
,FILE_APPEND
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Minify::setCache(new Minify_Cache_Memcache($mc));
|
||||
|
||||
Minify::serve('Files', array(
|
||||
'files' => array(
|
||||
dirname(__FILE__) . '/before.js'
|
||||
)
|
||||
,'maxAge' => 31536000 // 1 yr
|
||||
));
|
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
require '../../config.php';
|
||||
|
||||
// set in /min/config.php
|
||||
Minify::setCache($minifyCachePath);
|
||||
|
||||
Minify::serve('Groups', array(
|
||||
'groups' => array(
|
||||
'test' => array(dirname(__FILE__) . '/before.js')
|
||||
)
|
||||
,'maxAge' => 31536000 // 1 yr
|
||||
));
|
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
require '../../config.php';
|
||||
|
||||
define('MINIFY_BASE_DIR', realpath(
|
||||
dirname(__FILE__) . '/../minify'
|
||||
));
|
||||
// set in /min/config.php
|
||||
define('MINIFY_CACHE_DIR', $minifyCachePath);
|
||||
|
||||
Minify::serve('Version1');
|
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
$mc = new Memcache;
|
||||
if (! @$mc->connect('localhost', 11211)) {
|
||||
file_put_contents(
|
||||
dirname(__FILE__) . '/../memcached_stats.txt'
|
||||
,"Fail\n"
|
||||
,FILE_APPEND | LOCK_EX
|
||||
);
|
||||
die();
|
||||
}
|
||||
|
||||
$stats = $mc->getStats();
|
||||
file_put_contents(
|
||||
dirname(__FILE__) . '/../memcached_stats.txt'
|
||||
,$stats['curr_connections'] . "\n"
|
||||
,FILE_APPEND | LOCK_EX
|
||||
);
|
||||
|
@@ -1,30 +0,0 @@
|
||||
# turn off MultiViews if enabled
|
||||
Options -MultiViews
|
||||
|
||||
# Necessary to add charset while using type-map
|
||||
AddType application/x-javascript;charset=utf-8 js
|
||||
AddType text/css;charset=utf-8 css
|
||||
|
||||
# Below we remove the ETag header and set a far-off Expires
|
||||
# header. Since clients will aggressively cache, make sure
|
||||
# to modify the URL (querystring or via mod_rewrite) when
|
||||
# the resource changes
|
||||
|
||||
# remove ETag
|
||||
FileETag None
|
||||
|
||||
# requires mod_expires
|
||||
ExpiresActive On
|
||||
# sets Expires and Cache-Control: max-age, but not "public"
|
||||
ExpiresDefault "access plus 1 year"
|
||||
|
||||
# requires mod_headers
|
||||
# adds the "public" to Cache-Control.
|
||||
Header set Cache-Control "public, max-age=31536000"
|
||||
|
||||
# requires mod_deflate
|
||||
AddOutputFilterByType DEFLATE application/x-javascript text/css
|
||||
# IE 5 and 6 are the only ones we really care about
|
||||
BrowserMatch \bMSIE\s[56] no-gzip
|
||||
# but not if it's got the SV1 patch or is really Opera
|
||||
BrowserMatch \b(SV1|Opera)\b !no-gzip
|
@@ -1,374 +0,0 @@
|
||||
(function(){
|
||||
/*
|
||||
* jQuery 1.2.3 - New Wave Javascript
|
||||
*
|
||||
* Copyright (c) 2008 John Resig (jquery.com)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
*
|
||||
* $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $
|
||||
* $Rev: 4663 $
|
||||
*/
|
||||
if(window.jQuery)
|
||||
var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)
|
||||
var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])
|
||||
selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)
|
||||
if(elem.id!=match[3])
|
||||
return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}
|
||||
else
|
||||
selector=[];}}else
|
||||
return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))
|
||||
return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)
|
||||
ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)
|
||||
if(value==undefined)
|
||||
return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}
|
||||
return this.each(function(i){for(name in options)
|
||||
jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)
|
||||
value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)
|
||||
return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)
|
||||
ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])
|
||||
jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)
|
||||
elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)
|
||||
this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)
|
||||
this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else
|
||||
return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)
|
||||
this[expando]=null;});if(events===true)
|
||||
this.find("*").andSelf().each(function(i){if(this.nodeType==3)
|
||||
return;var events=jQuery.data(this,"events");for(var type in events)
|
||||
for(var handler in events[type])
|
||||
jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)
|
||||
if(isSimple.test(selector))
|
||||
return this.pushStack(jQuery.multiFilter(selector,this,true));else
|
||||
selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)
|
||||
return null;for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one)
|
||||
return value;values.push(value);}}
|
||||
return values;}else
|
||||
return(this[0].value||"").replace(/\r/g,"");}
|
||||
return undefined;}
|
||||
return this.each(function(){if(this.nodeType!=1)
|
||||
return;if(value.constructor==Array&&/radio|checkbox/.test(this.type))
|
||||
this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)
|
||||
this.selectedIndex=-1;}else
|
||||
this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)
|
||||
data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else
|
||||
return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)
|
||||
elems.reverse();}
|
||||
var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))
|
||||
obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)
|
||||
scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)
|
||||
jQuery.ajax({url:elem.src,async:false,dataType:"script"});else
|
||||
jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)
|
||||
elem.parentNode.removeChild(elem);}
|
||||
jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}
|
||||
if(typeof target!="object"&&typeof target!="function")
|
||||
target={};if(length==1){target=this;i=0;}
|
||||
for(;i<length;i++)
|
||||
if((options=arguments[i])!=null)
|
||||
for(var name in options){if(target===options[name])
|
||||
continue;if(deep&&options[name]&&typeof options[name]=="object"&&target[name]&&!options[name].nodeType)
|
||||
target[name]=jQuery.extend(target[name],options[name]);else if(options[name]!=undefined)
|
||||
target[name]=options[name];}
|
||||
return target;};var expando="jQuery"+(new Date()).getTime(),uuid=0,windowData={};var exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i;jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)
|
||||
window.jQuery=_jQuery;return jQuery;},isFunction:function(fn){return!!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/function/i.test(fn+"");},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body;},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie)
|
||||
script.text=data;else
|
||||
script.appendChild(document.createTextNode(data));head.appendChild(script);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)
|
||||
id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])
|
||||
jQuery.cache[id]={};if(data!=undefined)
|
||||
jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])
|
||||
break;if(!name)
|
||||
jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)
|
||||
elem.removeAttribute(expando);}
|
||||
delete jQuery.cache[id];}},each:function(object,callback,args){if(args){if(object.length==undefined){for(var name in object)
|
||||
if(callback.apply(object[name],args)===false)
|
||||
break;}else
|
||||
for(var i=0,length=object.length;i<length;i++)
|
||||
if(callback.apply(object[i],args)===false)
|
||||
break;}else{if(object.length==undefined){for(var name in object)
|
||||
if(callback.call(object[name],name,object[name])===false)
|
||||
break;}else
|
||||
for(var i=0,length=object.length,value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}
|
||||
return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))
|
||||
value=value.call(elem,i);return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))
|
||||
elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)
|
||||
elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}
|
||||
callback.call(elem);for(var name in options)
|
||||
elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}
|
||||
if(jQuery(elem).is(":visible"))
|
||||
getWH();else
|
||||
jQuery.swap(elem,props,getWH);return Math.max(0,val);}
|
||||
return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)
|
||||
return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}
|
||||
if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}
|
||||
if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}
|
||||
if(name.match(/float/i))
|
||||
name=styleFloat;if(!force&&elem.style&&elem.style[name])
|
||||
ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))
|
||||
name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))
|
||||
ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)
|
||||
stack.unshift(a);for(var i=0;i<stack.length;i++)
|
||||
if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block";}
|
||||
ret=name=="display"&&swap[stack.length-1]!=null?"none":(getComputedStyle&&getComputedStyle.getPropertyValue(name))||"";for(var i=0;i<swap.length;i++)
|
||||
if(swap[i]!=null)
|
||||
stack[i].style.display=swap[i];}
|
||||
if(name=="opacity"&&ret=="")
|
||||
ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var style=elem.style.left,runtimeStyle=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;elem.style.left=ret||0;ret=elem.style.pixelLeft+"px";elem.style.left=style;elem.runtimeStyle.left=runtimeStyle;}}
|
||||
return ret;},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=='undefined')
|
||||
context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;jQuery.each(elems,function(i,elem){if(!elem)
|
||||
return;if(elem.constructor==Number)
|
||||
elem=elem.toString();if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)
|
||||
div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j)
|
||||
if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)
|
||||
tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))
|
||||
div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}
|
||||
elem=jQuery.makeArray(div.childNodes);}
|
||||
if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))
|
||||
return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)
|
||||
ret.push(elem);else
|
||||
ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)
|
||||
return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)
|
||||
elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)
|
||||
elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")
|
||||
return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))
|
||||
return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)
|
||||
throw"type property can't be changed";elem.setAttribute(name,""+value);}
|
||||
if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))
|
||||
return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+
|
||||
(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}
|
||||
return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}
|
||||
name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)
|
||||
elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")
|
||||
for(var i=0,length=array.length;i<length;i++)
|
||||
ret.push(array[i]);else
|
||||
ret=array.slice(0);return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)
|
||||
if(array[i]==elem)
|
||||
return i;return-1;},merge:function(first,second){if(jQuery.browser.msie){for(var i=0;second[i];i++)
|
||||
if(second[i].nodeType!=8)
|
||||
first.push(second[i]);}else
|
||||
for(var i=0;second[i];i++)
|
||||
first.push(second[i]);return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}
|
||||
return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)
|
||||
if(!inv&&callback(elems[i],i)||inv&&!callback(elems[i],i))
|
||||
ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!==null&&value!=undefined){if(value.constructor!=Array)
|
||||
value=[value];ret=ret.concat(value);}}
|
||||
return ret;}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,innerHTML:"innerHTML",className:"className",value:"value",disabled:"disabled",checked:"checked",readonly:"readOnly",selected:"selected",maxlength:"maxLength",selectedIndex:"selectedIndex",defaultValue:"defaultValue",tagName:"tagName",nodeName:"nodeName"}});jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")
|
||||
ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret));};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++)
|
||||
jQuery(args[i])[original](this);});};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)
|
||||
this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)
|
||||
this.parentNode.removeChild(this);}},empty:function(){jQuery(">*",this).remove();while(this.firstChild)
|
||||
this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return i<m[3]-0;},gt:function(a,i,m){return i>m[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}
|
||||
return cur;},find:function(t,context){if(typeof t!="string")
|
||||
return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)
|
||||
return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)
|
||||
for(var c=ret[i].firstChild;c;c=c.nextSibling)
|
||||
if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))
|
||||
r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling)
|
||||
if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id])break;if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~")merge[id]=true;r.push(n);}
|
||||
if(m=="+")break;}}
|
||||
ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true;}}
|
||||
if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0])ret.shift();done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length);}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]];}else{re2=quickClass;m=re2.exec(t);}
|
||||
m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2])
|
||||
oid=jQuery('[@id="'+m[2]+'"]',elem)[0];ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[];}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object")
|
||||
tag="param";r=jQuery.merge(r,ret[i].getElementsByTagName(tag));}
|
||||
if(m[1]==".")
|
||||
r=jQuery.classFilter(r,m[2]);if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++)
|
||||
if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break;}
|
||||
r=tmp;}
|
||||
ret=r;}
|
||||
t=t.replace(re2,"");}}
|
||||
if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t);}}
|
||||
if(t)
|
||||
ret=[];if(ret&&context==ret[0])
|
||||
ret.shift();done=jQuery.merge(done,ret);return done;},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass)
|
||||
tmp.push(r[i]);}
|
||||
return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}
|
||||
if(!m)
|
||||
break;if(m[1]==":"&&m[2]=="not")
|
||||
r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")
|
||||
r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2]))
|
||||
z=jQuery.attr(a,m[2])||'';if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not)
|
||||
tmp.push(a);}
|
||||
r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling)
|
||||
if(n.nodeType==1)
|
||||
n.nodeIndex=c++;merge[id]=true;}
|
||||
var add=false;if(first==0){if(node.nodeIndex==last)
|
||||
add=true;}else if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0)
|
||||
add=true;if(add^not)
|
||||
tmp.push(node);}
|
||||
r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")
|
||||
fn=fn[m[2]];if(typeof fn=="string")
|
||||
fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}
|
||||
return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)
|
||||
matched.push(cur);cur=cur[dir];}
|
||||
return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])
|
||||
if(cur.nodeType==1&&++num==result)
|
||||
break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))
|
||||
r.push(n);}
|
||||
return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)
|
||||
return;if(jQuery.browser.msie&&elem.setInterval!=undefined)
|
||||
elem=window;if(!handler.guid)
|
||||
handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}
|
||||
var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)
|
||||
return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)
|
||||
elem.addEventListener(type,handle,false);else if(elem.attachEvent)
|
||||
elem.attachEvent("on"+type,handle);}}
|
||||
handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)
|
||||
return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))
|
||||
for(var type in events)
|
||||
this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}
|
||||
jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)
|
||||
delete events[type][handler.guid];else
|
||||
for(handler in events[type])
|
||||
if(!parts[1]||events[type][handler].type==parts[1])
|
||||
delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)
|
||||
elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)
|
||||
elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}
|
||||
ret=null;delete events[type];}}});}
|
||||
for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}
|
||||
if(!elem){if(this.global[type])
|
||||
jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)
|
||||
return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)
|
||||
data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)
|
||||
data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))
|
||||
val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)
|
||||
val=false;if(event)
|
||||
data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)
|
||||
val=ret;}
|
||||
if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}
|
||||
this.triggered=false;}
|
||||
return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)
|
||||
val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}
|
||||
if(jQuery.browser.msie)
|
||||
event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)
|
||||
originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)
|
||||
originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)
|
||||
event.target=event.srcElement||document;if(event.target.nodeType==3)
|
||||
event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)
|
||||
event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}
|
||||
if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))
|
||||
event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)
|
||||
event.metaKey=event.ctrlKey;if(!event.which&&event.button)
|
||||
event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])
|
||||
return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)
|
||||
fn.call(document,jQuery);else
|
||||
jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}
|
||||
jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)
|
||||
document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}
|
||||
jQuery.ready();})();if(jQuery.browser.opera)
|
||||
document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i<document.styleSheets.length;i++)
|
||||
if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return;}
|
||||
jQuery.ready();},false);if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady)return;if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return;}
|
||||
if(numStyles===undefined)
|
||||
numStyles=jQuery("style, link[rel=stylesheet]").length;if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return;}
|
||||
jQuery.ready();})();}
|
||||
jQuery.event.add(window,"load",jQuery.ready);}
|
||||
jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"+"submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem)try{parent=parent.parentNode;}catch(error){parent=elem;}
|
||||
return parent==elem;};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind();});jQuery.fn.extend({load:function(url,params,callback){if(jQuery.isFunction(url))
|
||||
return this.bind("load",url);var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}
|
||||
callback=callback||function(){};var type="GET";if(params)
|
||||
if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}
|
||||
var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")
|
||||
self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}
|
||||
return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}
|
||||
return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")
|
||||
s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))
|
||||
s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))
|
||||
s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}
|
||||
if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)
|
||||
s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}
|
||||
if(head)
|
||||
head.removeChild(script);};}
|
||||
if(s.dataType=="script"&&s.cache==null)
|
||||
s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}
|
||||
if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}
|
||||
if(s.global&&!jQuery.active++)
|
||||
jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)
|
||||
script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}
|
||||
head.appendChild(script);return undefined;}
|
||||
var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)
|
||||
xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)
|
||||
xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}
|
||||
if(s.beforeSend)
|
||||
s.beforeSend(xml);if(s.global)
|
||||
jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}
|
||||
status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}
|
||||
if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}
|
||||
if(s.ifModified&&modRes)
|
||||
jQuery.lastModified[s.url]=modRes;if(!jsonp)
|
||||
success();}else
|
||||
jQuery.handleError(s,xml,status);complete();if(s.async)
|
||||
xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)
|
||||
setTimeout(function(){if(xml){xml.abort();if(!requestDone)
|
||||
onreadystatechange("timeout");}},s.timeout);}
|
||||
try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}
|
||||
if(!s.async)
|
||||
onreadystatechange();function success(){if(s.success)
|
||||
s.success(data,status);if(s.global)
|
||||
jQuery.event.trigger("ajaxSuccess",[xml,s]);}
|
||||
function complete(){if(s.complete)
|
||||
s.complete(xml,status);if(s.global)
|
||||
jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)
|
||||
jQuery.event.trigger("ajaxStop");}
|
||||
return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)
|
||||
jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}
|
||||
return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}
|
||||
return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")
|
||||
throw"parsererror";if(type=="script")
|
||||
jQuery.globalEval(data);if(type=="json")
|
||||
data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)
|
||||
jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else
|
||||
for(var j in a)
|
||||
if(a[j]&&a[j].constructor==Array)
|
||||
jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else
|
||||
s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")
|
||||
this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)
|
||||
return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)
|
||||
return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}
|
||||
if(opt.overflow!=null)
|
||||
this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))
|
||||
e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}
|
||||
if(parts[1])
|
||||
end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else
|
||||
e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}
|
||||
if(!type||(typeof type=="string"&&!fn))
|
||||
return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)
|
||||
queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)
|
||||
fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)
|
||||
this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)
|
||||
if(timers[i].elem==this){if(gotoEnd)
|
||||
timers[i](true);timers.splice(i,1);}});if(!gotoEnd)
|
||||
this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)
|
||||
return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)
|
||||
q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)
|
||||
q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)
|
||||
jQuery(this).dequeue();if(jQuery.isFunction(opt.old))
|
||||
opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)
|
||||
options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)
|
||||
this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")
|
||||
this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)
|
||||
return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}
|
||||
t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++)
|
||||
if(!timers[i]())
|
||||
timers.splice(i--,1);if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height")
|
||||
this.elem.style[this.prop]="1px";jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=(new Date()).getTime();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)
|
||||
if(this.options.curAnim[i]!==true)
|
||||
done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")
|
||||
this.elem.style.display="block";}
|
||||
if(this.options.hide)
|
||||
this.elem.style.display="none";if(this.options.hide||this.options.show)
|
||||
for(var p in this.options.curAnim)
|
||||
jQuery.attr(this.elem.style,p,this.options.orig[p]);}
|
||||
if(done&&jQuery.isFunction(this.options.complete))
|
||||
this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}
|
||||
return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)
|
||||
border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")
|
||||
fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}
|
||||
while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))
|
||||
add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")
|
||||
border(parent);parent=parent.parentNode;}
|
||||
if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))
|
||||
add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)
|
||||
add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}
|
||||
results={top:top,left:left};}
|
||||
function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}
|
||||
function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}
|
||||
return results;};})();
|
@@ -1,37 +0,0 @@
|
||||
Document Path: /_3rd_party/minify/min_extras/ab_tests/ideal_php/before.php
|
||||
Document Length: 15993 bytes
|
||||
Requests per second: 354.57 [#/sec] (mean)
|
||||
--------------------------------------------------------------------------------
|
||||
Document Path: /_3rd_party/minify/min_extras/ab_tests/v1.0/minify.php?files=before.js
|
||||
Document Length: 54418 bytes
|
||||
Requests per second: 261.76 [#/sec] (mean)
|
||||
--------------------------------------------------------------------------------
|
||||
Document Path: /_3rd_party/minify/min_extras/ab_tests/minify/test_Files.php
|
||||
Document Length: 15993 bytes
|
||||
Requests per second: 203.82 [#/sec] (mean)
|
||||
--------------------------------------------------------------------------------
|
||||
Document Path: /_3rd_party/minify/min_extras/ab_tests/minify/test_Files_Memcache.php
|
||||
Document Length: 15993 bytes
|
||||
(Connect: 0, Length: 19, Exceptions: 0)
|
||||
Requests per second: 156.86 [#/sec] (mean)
|
||||
--------------------------------------------------------------------------------
|
||||
Document Path: /_3rd_party/minify/min_extras/ab_tests/minify/test_Groups.php/test
|
||||
Document Length: 15993 bytes
|
||||
Requests per second: 207.79 [#/sec] (mean)
|
||||
--------------------------------------------------------------------------------
|
||||
Document Path: /_3rd_party/minify/min_extras/ab_tests/minify/test_Version1.php?files=before.js
|
||||
Document Length: 15993 bytes
|
||||
Requests per second: 210.53 [#/sec] (mean)
|
||||
--------------------------------------------------------------------------------
|
||||
Document Path: /min/?f=_3rd_party/minify/min_extras/ab_tests/minify/before.js
|
||||
Document Length: 15993 bytes
|
||||
Requests per second: 231.46 [#/sec] (mean)
|
||||
--------------------------------------------------------------------------------
|
||||
Document Path: /_3rd_party/minify/min_extras/ab_tests/mod_deflate/before.js
|
||||
Document Length: 16053 bytes
|
||||
Requests per second: 185.78 [#/sec] (mean)
|
||||
--------------------------------------------------------------------------------
|
||||
Document Path: /_3rd_party/minify/min_extras/ab_tests/type-map/before.js.var
|
||||
Document Length: 15993 bytes
|
||||
Requests per second: 472.32 [#/sec] (mean)
|
||||
--------------------------------------------------------------------------------
|
@@ -1,67 +0,0 @@
|
||||
@SET PATH=%PATH%;C:\xampp\apache\bin
|
||||
|
||||
@SET DOMAIN=http://mc.dev
|
||||
|
||||
@SET ABCALL=ab -d -S -c 100 -n 2000 -H "Accept-Encoding: deflate, gzip"
|
||||
:: for priming cache
|
||||
@SET ABPRIM=ab -d -S -c 1 -n 2 -H "Accept-Encoding: deflate, gzip"
|
||||
|
||||
@SET ABTESTS=%DOMAIN%/min_extras/ab_tests
|
||||
|
||||
::@SET TXTVIEWER=notepad.exe
|
||||
@SET TXTVIEWER="C:\Program Files\Notepad++\notepad++.exe"
|
||||
|
||||
@SET DELIM=TYPE _delimiter
|
||||
|
||||
DEL results.txt
|
||||
|
||||
:: prime caches (though some may not need it)
|
||||
%ABPRIM% %ABTESTS%/ideal_php/before.php
|
||||
%ABPRIM% %ABTESTS%/v1.0/minify.php?files=before.js
|
||||
%ABPRIM% %ABTESTS%/minify/test_Files.php
|
||||
%ABPRIM% %ABTESTS%/minify/test_Files_Memcache.php
|
||||
%ABPRIM% %ABTESTS%/minify/test_Groups.php/test
|
||||
%ABPRIM% %ABTESTS%/minify/test_Version1.php?files=before.js
|
||||
%ABPRIM% %DOMAIN%/min/?f=min_extras/ab_tests/minify/before.js
|
||||
%ABPRIM% %ABTESTS%/mod_deflate/before.js
|
||||
%ABPRIM% %ABTESTS%/type-map/before.js.var
|
||||
|
||||
:: baseline PHP
|
||||
%ABCALL% %ABTESTS%/ideal_php/before.php >> results.txt
|
||||
@%DELIM% >> results.txt
|
||||
|
||||
:: 1.0 release
|
||||
%ABCALL% %ABTESTS%/v1.0/minify.php?files=before.js >> results.txt
|
||||
@%DELIM% >> results.txt
|
||||
|
||||
:: Files controller
|
||||
%ABCALL% %ABTESTS%/minify/test_Files.php >> results.txt
|
||||
@%DELIM% >> results.txt
|
||||
|
||||
:: Files controller w/ Memcache as cache
|
||||
%ABCALL% %ABTESTS%/minify/test_Files_Memcache.php >> results.txt
|
||||
@%DELIM% >> results.txt
|
||||
|
||||
:: Groups controller
|
||||
%ABCALL% %ABTESTS%/minify/test_Groups.php/test >> results.txt
|
||||
@%DELIM% >> results.txt
|
||||
|
||||
:: Version1 controller
|
||||
%ABCALL% %ABTESTS%/minify/test_Version1.php?files=before.js >> results.txt
|
||||
@%DELIM% >> results.txt
|
||||
|
||||
::/min application
|
||||
%ABCALL% %DOMAIN%/min/?f=min_extras/ab_tests/minify/before.js >> results.txt
|
||||
@%DELIM% >> results.txt
|
||||
|
||||
:: mod_deflate
|
||||
%ABCALL% %ABTESTS%/mod_deflate/before.js >> results.txt
|
||||
@%DELIM% >> results.txt
|
||||
|
||||
:: type-map
|
||||
%ABCALL% %ABTESTS%/type-map/before.js.var >> results.txt
|
||||
@%DELIM% >> results.txt
|
||||
|
||||
FINDSTR "Path: Length: Requests --" results.txt > results_summary.txt
|
||||
|
||||
START %TXTVIEWER% results_summary.txt
|
@@ -1,13 +0,0 @@
|
||||
@SET PATH=%PATH%;C:\xampp\apache\bin;C:\Program Files\GnuWin32\bin
|
||||
|
||||
@SET DOMAIN=http://localhost/minify
|
||||
|
||||
@SET ABTESTS=%DOMAIN%/min_extras/ab_tests
|
||||
|
||||
DEL results.txt
|
||||
|
||||
DEL memcached_stats.txt
|
||||
|
||||
ab -d -S -c 100 -n 1000 %ABTESTS%/minify/test_memcache.php >> results.txt
|
||||
|
||||
START "C:\Program Files\Notepad++\notepad++.exe" memcached_stats.txt
|
@@ -1,40 +0,0 @@
|
||||
# turn off MultiViews if enabled
|
||||
Options -MultiViews
|
||||
|
||||
# For *.var requests, negotiate using type-map
|
||||
AddHandler type-map .var
|
||||
|
||||
# use custom extensions so existing handlers for .gz/.Z don't interfere
|
||||
AddEncoding x-gzip .zg
|
||||
AddEncoding x-compress .zc
|
||||
AddEncoding deflate .zd
|
||||
|
||||
# Necessary to add charset while using type-map
|
||||
AddType application/x-javascript;charset=utf-8 js
|
||||
AddType text/css;charset=utf-8 css
|
||||
|
||||
# Below we remove the ETag header and set a far-off Expires
|
||||
# header. Since clients will aggressively cache, make sure
|
||||
# to modify the URL (querystring or via mod_rewrite) when
|
||||
# the resource changes
|
||||
|
||||
# remove ETag
|
||||
FileETag None
|
||||
|
||||
# requires mod_expires
|
||||
ExpiresActive On
|
||||
# sets Expires and Cache-Control: max-age, but not "public"
|
||||
ExpiresDefault "access plus 1 year"
|
||||
|
||||
# requires mod_headers
|
||||
# adds the "public" to Cache-Control.
|
||||
Header set Cache-Control "public, max-age=31536000"
|
||||
|
||||
# requires mod_rewrite
|
||||
RewriteEngine On
|
||||
RewriteBase /_3rd_party/minify/web/test/statics
|
||||
# IE 5 and 6 are the only ones we really care about
|
||||
RewriteCond %{HTTP_USER_AGENT} MSIE\ [56]
|
||||
# but not if it's got the SV1 patch or is really Opera
|
||||
RewriteCond %{HTTP_USER_AGENT} !(\ SV1|Opera)
|
||||
RewriteRule ^(.*)\.var$ $1 [L]
|
@@ -1,374 +0,0 @@
|
||||
(function(){
|
||||
/*
|
||||
* jQuery 1.2.3 - New Wave Javascript
|
||||
*
|
||||
* Copyright (c) 2008 John Resig (jquery.com)
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
*
|
||||
* $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $
|
||||
* $Rev: 4663 $
|
||||
*/
|
||||
if(window.jQuery)
|
||||
var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)
|
||||
var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])
|
||||
selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)
|
||||
if(elem.id!=match[3])
|
||||
return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}
|
||||
else
|
||||
selector=[];}}else
|
||||
return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))
|
||||
return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)
|
||||
ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)
|
||||
if(value==undefined)
|
||||
return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}
|
||||
return this.each(function(i){for(name in options)
|
||||
jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)
|
||||
value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)
|
||||
return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)
|
||||
ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])
|
||||
jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)
|
||||
elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)
|
||||
this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)
|
||||
this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else
|
||||
return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)
|
||||
this[expando]=null;});if(events===true)
|
||||
this.find("*").andSelf().each(function(i){if(this.nodeType==3)
|
||||
return;var events=jQuery.data(this,"events");for(var type in events)
|
||||
for(var handler in events[type])
|
||||
jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)
|
||||
if(isSimple.test(selector))
|
||||
return this.pushStack(jQuery.multiFilter(selector,this,true));else
|
||||
selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)
|
||||
return null;for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one)
|
||||
return value;values.push(value);}}
|
||||
return values;}else
|
||||
return(this[0].value||"").replace(/\r/g,"");}
|
||||
return undefined;}
|
||||
return this.each(function(){if(this.nodeType!=1)
|
||||
return;if(value.constructor==Array&&/radio|checkbox/.test(this.type))
|
||||
this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)
|
||||
this.selectedIndex=-1;}else
|
||||
this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)
|
||||
data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else
|
||||
return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)
|
||||
elems.reverse();}
|
||||
var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))
|
||||
obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)
|
||||
scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)
|
||||
jQuery.ajax({url:elem.src,async:false,dataType:"script"});else
|
||||
jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)
|
||||
elem.parentNode.removeChild(elem);}
|
||||
jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}
|
||||
if(typeof target!="object"&&typeof target!="function")
|
||||
target={};if(length==1){target=this;i=0;}
|
||||
for(;i<length;i++)
|
||||
if((options=arguments[i])!=null)
|
||||
for(var name in options){if(target===options[name])
|
||||
continue;if(deep&&options[name]&&typeof options[name]=="object"&&target[name]&&!options[name].nodeType)
|
||||
target[name]=jQuery.extend(target[name],options[name]);else if(options[name]!=undefined)
|
||||
target[name]=options[name];}
|
||||
return target;};var expando="jQuery"+(new Date()).getTime(),uuid=0,windowData={};var exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i;jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)
|
||||
window.jQuery=_jQuery;return jQuery;},isFunction:function(fn){return!!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/function/i.test(fn+"");},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body;},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie)
|
||||
script.text=data;else
|
||||
script.appendChild(document.createTextNode(data));head.appendChild(script);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)
|
||||
id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])
|
||||
jQuery.cache[id]={};if(data!=undefined)
|
||||
jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])
|
||||
break;if(!name)
|
||||
jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)
|
||||
elem.removeAttribute(expando);}
|
||||
delete jQuery.cache[id];}},each:function(object,callback,args){if(args){if(object.length==undefined){for(var name in object)
|
||||
if(callback.apply(object[name],args)===false)
|
||||
break;}else
|
||||
for(var i=0,length=object.length;i<length;i++)
|
||||
if(callback.apply(object[i],args)===false)
|
||||
break;}else{if(object.length==undefined){for(var name in object)
|
||||
if(callback.call(object[name],name,object[name])===false)
|
||||
break;}else
|
||||
for(var i=0,length=object.length,value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}
|
||||
return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))
|
||||
value=value.call(elem,i);return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))
|
||||
elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)
|
||||
elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}
|
||||
callback.call(elem);for(var name in options)
|
||||
elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}
|
||||
if(jQuery(elem).is(":visible"))
|
||||
getWH();else
|
||||
jQuery.swap(elem,props,getWH);return Math.max(0,val);}
|
||||
return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)
|
||||
return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}
|
||||
if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}
|
||||
if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}
|
||||
if(name.match(/float/i))
|
||||
name=styleFloat;if(!force&&elem.style&&elem.style[name])
|
||||
ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))
|
||||
name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))
|
||||
ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)
|
||||
stack.unshift(a);for(var i=0;i<stack.length;i++)
|
||||
if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block";}
|
||||
ret=name=="display"&&swap[stack.length-1]!=null?"none":(getComputedStyle&&getComputedStyle.getPropertyValue(name))||"";for(var i=0;i<swap.length;i++)
|
||||
if(swap[i]!=null)
|
||||
stack[i].style.display=swap[i];}
|
||||
if(name=="opacity"&&ret=="")
|
||||
ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var style=elem.style.left,runtimeStyle=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;elem.style.left=ret||0;ret=elem.style.pixelLeft+"px";elem.style.left=style;elem.runtimeStyle.left=runtimeStyle;}}
|
||||
return ret;},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=='undefined')
|
||||
context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;jQuery.each(elems,function(i,elem){if(!elem)
|
||||
return;if(elem.constructor==Number)
|
||||
elem=elem.toString();if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)
|
||||
div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j)
|
||||
if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)
|
||||
tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))
|
||||
div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}
|
||||
elem=jQuery.makeArray(div.childNodes);}
|
||||
if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))
|
||||
return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)
|
||||
ret.push(elem);else
|
||||
ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)
|
||||
return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)
|
||||
elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)
|
||||
elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")
|
||||
return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))
|
||||
return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)
|
||||
throw"type property can't be changed";elem.setAttribute(name,""+value);}
|
||||
if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))
|
||||
return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+
|
||||
(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}
|
||||
return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}
|
||||
name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)
|
||||
elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")
|
||||
for(var i=0,length=array.length;i<length;i++)
|
||||
ret.push(array[i]);else
|
||||
ret=array.slice(0);return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)
|
||||
if(array[i]==elem)
|
||||
return i;return-1;},merge:function(first,second){if(jQuery.browser.msie){for(var i=0;second[i];i++)
|
||||
if(second[i].nodeType!=8)
|
||||
first.push(second[i]);}else
|
||||
for(var i=0;second[i];i++)
|
||||
first.push(second[i]);return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}
|
||||
return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)
|
||||
if(!inv&&callback(elems[i],i)||inv&&!callback(elems[i],i))
|
||||
ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!==null&&value!=undefined){if(value.constructor!=Array)
|
||||
value=[value];ret=ret.concat(value);}}
|
||||
return ret;}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,innerHTML:"innerHTML",className:"className",value:"value",disabled:"disabled",checked:"checked",readonly:"readOnly",selected:"selected",maxlength:"maxLength",selectedIndex:"selectedIndex",defaultValue:"defaultValue",tagName:"tagName",nodeName:"nodeName"}});jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")
|
||||
ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret));};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++)
|
||||
jQuery(args[i])[original](this);});};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)
|
||||
this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)
|
||||
this.parentNode.removeChild(this);}},empty:function(){jQuery(">*",this).remove();while(this.firstChild)
|
||||
this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return i<m[3]-0;},gt:function(a,i,m){return i>m[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}
|
||||
return cur;},find:function(t,context){if(typeof t!="string")
|
||||
return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)
|
||||
return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)
|
||||
for(var c=ret[i].firstChild;c;c=c.nextSibling)
|
||||
if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))
|
||||
r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling)
|
||||
if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id])break;if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~")merge[id]=true;r.push(n);}
|
||||
if(m=="+")break;}}
|
||||
ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true;}}
|
||||
if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0])ret.shift();done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length);}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]];}else{re2=quickClass;m=re2.exec(t);}
|
||||
m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2])
|
||||
oid=jQuery('[@id="'+m[2]+'"]',elem)[0];ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[];}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object")
|
||||
tag="param";r=jQuery.merge(r,ret[i].getElementsByTagName(tag));}
|
||||
if(m[1]==".")
|
||||
r=jQuery.classFilter(r,m[2]);if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++)
|
||||
if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break;}
|
||||
r=tmp;}
|
||||
ret=r;}
|
||||
t=t.replace(re2,"");}}
|
||||
if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t);}}
|
||||
if(t)
|
||||
ret=[];if(ret&&context==ret[0])
|
||||
ret.shift();done=jQuery.merge(done,ret);return done;},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass)
|
||||
tmp.push(r[i]);}
|
||||
return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}
|
||||
if(!m)
|
||||
break;if(m[1]==":"&&m[2]=="not")
|
||||
r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")
|
||||
r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2]))
|
||||
z=jQuery.attr(a,m[2])||'';if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not)
|
||||
tmp.push(a);}
|
||||
r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling)
|
||||
if(n.nodeType==1)
|
||||
n.nodeIndex=c++;merge[id]=true;}
|
||||
var add=false;if(first==0){if(node.nodeIndex==last)
|
||||
add=true;}else if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0)
|
||||
add=true;if(add^not)
|
||||
tmp.push(node);}
|
||||
r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")
|
||||
fn=fn[m[2]];if(typeof fn=="string")
|
||||
fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}
|
||||
return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)
|
||||
matched.push(cur);cur=cur[dir];}
|
||||
return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])
|
||||
if(cur.nodeType==1&&++num==result)
|
||||
break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))
|
||||
r.push(n);}
|
||||
return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)
|
||||
return;if(jQuery.browser.msie&&elem.setInterval!=undefined)
|
||||
elem=window;if(!handler.guid)
|
||||
handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}
|
||||
var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)
|
||||
return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)
|
||||
elem.addEventListener(type,handle,false);else if(elem.attachEvent)
|
||||
elem.attachEvent("on"+type,handle);}}
|
||||
handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)
|
||||
return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))
|
||||
for(var type in events)
|
||||
this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}
|
||||
jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)
|
||||
delete events[type][handler.guid];else
|
||||
for(handler in events[type])
|
||||
if(!parts[1]||events[type][handler].type==parts[1])
|
||||
delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)
|
||||
elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)
|
||||
elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}
|
||||
ret=null;delete events[type];}}});}
|
||||
for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}
|
||||
if(!elem){if(this.global[type])
|
||||
jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)
|
||||
return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)
|
||||
data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)
|
||||
data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))
|
||||
val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)
|
||||
val=false;if(event)
|
||||
data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)
|
||||
val=ret;}
|
||||
if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}
|
||||
this.triggered=false;}
|
||||
return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)
|
||||
val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}
|
||||
if(jQuery.browser.msie)
|
||||
event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)
|
||||
originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)
|
||||
originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)
|
||||
event.target=event.srcElement||document;if(event.target.nodeType==3)
|
||||
event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)
|
||||
event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}
|
||||
if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))
|
||||
event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)
|
||||
event.metaKey=event.ctrlKey;if(!event.which&&event.button)
|
||||
event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])
|
||||
return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)
|
||||
fn.call(document,jQuery);else
|
||||
jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}
|
||||
jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)
|
||||
document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}
|
||||
jQuery.ready();})();if(jQuery.browser.opera)
|
||||
document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i<document.styleSheets.length;i++)
|
||||
if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return;}
|
||||
jQuery.ready();},false);if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady)return;if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return;}
|
||||
if(numStyles===undefined)
|
||||
numStyles=jQuery("style, link[rel=stylesheet]").length;if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return;}
|
||||
jQuery.ready();})();}
|
||||
jQuery.event.add(window,"load",jQuery.ready);}
|
||||
jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"+"submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem)try{parent=parent.parentNode;}catch(error){parent=elem;}
|
||||
return parent==elem;};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind();});jQuery.fn.extend({load:function(url,params,callback){if(jQuery.isFunction(url))
|
||||
return this.bind("load",url);var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}
|
||||
callback=callback||function(){};var type="GET";if(params)
|
||||
if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}
|
||||
var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")
|
||||
self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}
|
||||
return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}
|
||||
return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")
|
||||
s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))
|
||||
s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))
|
||||
s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}
|
||||
if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)
|
||||
s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}
|
||||
if(head)
|
||||
head.removeChild(script);};}
|
||||
if(s.dataType=="script"&&s.cache==null)
|
||||
s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}
|
||||
if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}
|
||||
if(s.global&&!jQuery.active++)
|
||||
jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)
|
||||
script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}
|
||||
head.appendChild(script);return undefined;}
|
||||
var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)
|
||||
xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)
|
||||
xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}
|
||||
if(s.beforeSend)
|
||||
s.beforeSend(xml);if(s.global)
|
||||
jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}
|
||||
status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}
|
||||
if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}
|
||||
if(s.ifModified&&modRes)
|
||||
jQuery.lastModified[s.url]=modRes;if(!jsonp)
|
||||
success();}else
|
||||
jQuery.handleError(s,xml,status);complete();if(s.async)
|
||||
xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)
|
||||
setTimeout(function(){if(xml){xml.abort();if(!requestDone)
|
||||
onreadystatechange("timeout");}},s.timeout);}
|
||||
try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}
|
||||
if(!s.async)
|
||||
onreadystatechange();function success(){if(s.success)
|
||||
s.success(data,status);if(s.global)
|
||||
jQuery.event.trigger("ajaxSuccess",[xml,s]);}
|
||||
function complete(){if(s.complete)
|
||||
s.complete(xml,status);if(s.global)
|
||||
jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)
|
||||
jQuery.event.trigger("ajaxStop");}
|
||||
return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)
|
||||
jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}
|
||||
return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}
|
||||
return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")
|
||||
throw"parsererror";if(type=="script")
|
||||
jQuery.globalEval(data);if(type=="json")
|
||||
data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)
|
||||
jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else
|
||||
for(var j in a)
|
||||
if(a[j]&&a[j].constructor==Array)
|
||||
jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else
|
||||
s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")
|
||||
this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)
|
||||
return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)
|
||||
return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}
|
||||
if(opt.overflow!=null)
|
||||
this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))
|
||||
e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}
|
||||
if(parts[1])
|
||||
end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else
|
||||
e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}
|
||||
if(!type||(typeof type=="string"&&!fn))
|
||||
return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)
|
||||
queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)
|
||||
fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)
|
||||
this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)
|
||||
if(timers[i].elem==this){if(gotoEnd)
|
||||
timers[i](true);timers.splice(i,1);}});if(!gotoEnd)
|
||||
this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)
|
||||
return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)
|
||||
q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)
|
||||
q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)
|
||||
jQuery(this).dequeue();if(jQuery.isFunction(opt.old))
|
||||
opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)
|
||||
options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)
|
||||
this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")
|
||||
this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)
|
||||
return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}
|
||||
t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++)
|
||||
if(!timers[i]())
|
||||
timers.splice(i--,1);if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height")
|
||||
this.elem.style[this.prop]="1px";jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=(new Date()).getTime();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)
|
||||
if(this.options.curAnim[i]!==true)
|
||||
done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")
|
||||
this.elem.style.display="block";}
|
||||
if(this.options.hide)
|
||||
this.elem.style.display="none";if(this.options.hide||this.options.show)
|
||||
for(var p in this.options.curAnim)
|
||||
jQuery.attr(this.elem.style,p,this.options.orig[p]);}
|
||||
if(done&&jQuery.isFunction(this.options.complete))
|
||||
this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}
|
||||
return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)
|
||||
border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")
|
||||
fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}
|
||||
while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))
|
||||
add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")
|
||||
border(parent);parent=parent.parentNode;}
|
||||
if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))
|
||||
add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)
|
||||
add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}
|
||||
results={top:top,left:left};}
|
||||
function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}
|
||||
function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}
|
||||
return results;};})();
|
@@ -1,14 +0,0 @@
|
||||
URI: before.js.zd
|
||||
Content-Type: application/x-javascript; qs=0.9
|
||||
Content-Encoding: deflate
|
||||
|
||||
URI: before.js.zg
|
||||
Content-Type: application/x-javascript; qs=0.8
|
||||
Content-Encoding: x-gzip
|
||||
|
||||
URI: before.js.zc
|
||||
Content-Type: application/x-javascript; qs=0.7
|
||||
Content-Encoding: x-compress
|
||||
|
||||
URI: before.js
|
||||
Content-Type: application/x-javascript; qs=0.6
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,500 +0,0 @@
|
||||
<?php
|
||||
// ab test of Minify 1.0, mostly to see how fast it can serve server-cached files.
|
||||
|
||||
require '../../config.php';
|
||||
|
||||
define('MINIFY_BASE_DIR', realpath(
|
||||
dirname(__FILE__) . '/../minify'
|
||||
));
|
||||
define('MINIFY_CACHE_DIR', $minifyCachePath);
|
||||
|
||||
/**
|
||||
* Minify - Combines, minifies, and caches JavaScript and CSS files on demand.
|
||||
*
|
||||
* See http://code.google.com/p/minify/ for usage instructions.
|
||||
*
|
||||
* This library was inspired by jscsscomp by Maxim Martynyuk <flashkot@mail.ru>
|
||||
* and by the article "Supercharged JavaScript" by Patrick Hunlock
|
||||
* <wb@hunlock.com>.
|
||||
*
|
||||
* JSMin was originally written by Douglas Crockford <douglas@crockford.com>.
|
||||
*
|
||||
* Requires PHP 5.2.1+.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Ryan Grove <ryan@wonko.com>
|
||||
* @copyright 2007 Ryan Grove. All rights reserved.
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version 1.1.0 (?)
|
||||
* @link http://code.google.com/p/minify/
|
||||
*/
|
||||
|
||||
if (!defined('MINIFY_BASE_DIR')) {
|
||||
/**
|
||||
* Base path from which all relative file paths should be resolved. By default
|
||||
* this is set to the document root.
|
||||
*/
|
||||
define('MINIFY_BASE_DIR', realpath($_SERVER['DOCUMENT_ROOT']));
|
||||
}
|
||||
|
||||
if (!defined('MINIFY_CACHE_DIR')) {
|
||||
/** Directory where compressed files will be cached. */
|
||||
define('MINIFY_CACHE_DIR', sys_get_temp_dir());
|
||||
}
|
||||
|
||||
if (!defined('MINIFY_ENCODING')) {
|
||||
/** Character set to use when outputting the minified files. */
|
||||
define('MINIFY_ENCODING', 'utf-8');
|
||||
}
|
||||
|
||||
if (!defined('MINIFY_MAX_FILES')) {
|
||||
/** Maximum number of files to combine in one request. */
|
||||
define('MINIFY_MAX_FILES', 16);
|
||||
}
|
||||
|
||||
if (!defined('MINIFY_REWRITE_CSS_URLS')) {
|
||||
/**
|
||||
* Whether or not Minify should attempt to rewrite relative URLs used in CSS
|
||||
* files so that they continue to point to the correct location after the file
|
||||
* is combined and minified.
|
||||
*
|
||||
* Minify is pretty good at getting this right, but occasionally it can make
|
||||
* mistakes. If you find that URL rewriting results in problems, you should
|
||||
* disable it.
|
||||
*/
|
||||
define('MINIFY_REWRITE_CSS_URLS', true);
|
||||
}
|
||||
|
||||
if (!defined('MINIFY_USE_CACHE')) {
|
||||
/**
|
||||
* Whether or not Minify should use a disk-based cache to increase
|
||||
* performance.
|
||||
*/
|
||||
define('MINIFY_USE_CACHE', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Minify is a library for combining, minifying, and caching JavaScript and CSS
|
||||
* files on demand before sending them to a web browser.
|
||||
*
|
||||
* @package Minify
|
||||
* @author Ryan Grove <ryan@wonko.com>
|
||||
* @copyright 2007 Ryan Grove. All rights reserved.
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version 1.1.0 (?)
|
||||
* @link http://code.google.com/p/minify/
|
||||
*/
|
||||
class Minify {
|
||||
const TYPE_CSS = 'text/css';
|
||||
const TYPE_HTML = 'text/html';
|
||||
const TYPE_JS = 'text/javascript';
|
||||
|
||||
protected $files = array();
|
||||
protected $type = self::TYPE_JS;
|
||||
|
||||
// -- Public Static Methods --------------------------------------------------
|
||||
|
||||
/**
|
||||
* Combines, minifies, and outputs the requested files.
|
||||
*
|
||||
* Inspects the $_GET array for a 'files' entry containing a comma-separated
|
||||
* list and uses this as the set of files to be combined and minified.
|
||||
*/
|
||||
public static function handleRequest() {
|
||||
// 404 if no files were requested.
|
||||
if (!isset($_GET['files'])) {
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
exit;
|
||||
}
|
||||
|
||||
$files = array_map('trim', explode(',', $_GET['files'], MINIFY_MAX_FILES));
|
||||
|
||||
// 404 if the $files array is empty for some weird reason.
|
||||
if (!count($files)) {
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Determine the content type based on the extension of the first file
|
||||
// requested.
|
||||
if (preg_match('/\.js$/iD', $files[0])) {
|
||||
$type = self::TYPE_JS;
|
||||
} else if (preg_match('/\.css$/iD', $files[0])) {
|
||||
$type = self::TYPE_CSS;
|
||||
} else {
|
||||
$type = self::TYPE_HTML;
|
||||
}
|
||||
|
||||
// Minify and spit out the result.
|
||||
try {
|
||||
$minify = new Minify($type, $files);
|
||||
|
||||
header("Content-Type: $type;charset=".MINIFY_ENCODING);
|
||||
|
||||
$minify->browserCache();
|
||||
echo $minify->combine();
|
||||
exit;
|
||||
}
|
||||
catch (MinifyException $e) {
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
echo htmlentities($e->getMessage());
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Minifies the specified string and returns it.
|
||||
*
|
||||
* @param string $string JavaScript, CSS, or HTML string to minify
|
||||
* @param string $type content type of the string (Minify::TYPE_CSS,
|
||||
* Minify::TYPE_HTML, or Minify::TYPE_JS)
|
||||
* @return string minified string
|
||||
*/
|
||||
public static function min($string, $type = self::TYPE_JS) {
|
||||
switch ($type) {
|
||||
case self::TYPE_CSS:
|
||||
return self::minifyCSS($string);
|
||||
break;
|
||||
|
||||
case self::TYPE_HTML:
|
||||
return self::minifyHTML($string);
|
||||
break;
|
||||
|
||||
case self::TYPE_JS:
|
||||
return self::minifyJS($string);
|
||||
break;
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
// -- Protected Static Methods -----------------------------------------------
|
||||
|
||||
/**
|
||||
* Minifies the specified CSS string and returns it.
|
||||
*
|
||||
* @param string $css CSS string
|
||||
* @return string minified string
|
||||
* @see minify()
|
||||
* @see minifyJS()
|
||||
*/
|
||||
protected static function minifyCSS($css) {
|
||||
// Compress whitespace.
|
||||
$css = preg_replace('/\s+/', ' ', $css);
|
||||
|
||||
// Remove comments.
|
||||
$css = preg_replace('/\/\*.*?\*\//', '', $css);
|
||||
|
||||
return trim($css);
|
||||
}
|
||||
|
||||
protected static function minifyHTML($html) {
|
||||
require_once dirname(__FILE__).'/lib/htmlmin.php';
|
||||
return HTMLMin::minify($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Minifies the specified JavaScript string and returns it.
|
||||
*
|
||||
* @param string $js JavaScript string
|
||||
* @return string minified string
|
||||
* @see minify()
|
||||
* @see minifyCSS()
|
||||
*/
|
||||
protected static function minifyJS($js) {
|
||||
require_once dirname(__FILE__).'/../../../min/lib/JSMin.php';
|
||||
return JSMin::minify($js);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites relative URLs in the specified CSS string to point to the correct
|
||||
* location. URLs are assumed to be relative to the absolute path specified in
|
||||
* the $path parameter.
|
||||
*
|
||||
* @param string $css CSS string
|
||||
* @param string $path absolute path to which URLs are relative (should be a
|
||||
* directory, not a file)
|
||||
* @return string CSS string with rewritten URLs
|
||||
*/
|
||||
protected static function rewriteCSSUrls($css, $path) {
|
||||
/*
|
||||
Parentheses, commas, whitespace chars, single quotes, and double quotes are
|
||||
escaped with a backslash as described in the CSS spec:
|
||||
http://www.w3.org/TR/REC-CSS1#url
|
||||
*/
|
||||
$relativePath = preg_replace('/([\(\),\s\'"])/', '\\\$1',
|
||||
str_replace(MINIFY_BASE_DIR, '', $path));
|
||||
|
||||
|
||||
return preg_replace('/url\(\s*[\'"]?\/?(.+?)[\'"]?\s*\)/i', 'url('.
|
||||
$relativePath.'/$1)', $css);
|
||||
}
|
||||
|
||||
// -- Public Instance Methods ------------------------------------------------
|
||||
|
||||
/**
|
||||
* Instantiates a new Minify object. A filename can be in the form of a
|
||||
* relative path or a URL that resolves to the same site that hosts Minify.
|
||||
*
|
||||
* @param string $type content type of the specified files (either
|
||||
* Minify::TYPE_CSS or Minify::TYPE_JS)
|
||||
* @param array|string $files filename or array of filenames to be minified
|
||||
*/
|
||||
public function __construct($type = self::TYPE_JS, $files = array()) {
|
||||
if ($type !== self::TYPE_JS && $type !== self::TYPE_CSS) {
|
||||
throw new MinifyInvalidArgumentException('Invalid argument ($type): '.
|
||||
$type);
|
||||
}
|
||||
|
||||
$this->type = $type;
|
||||
|
||||
if (count((array) $files)) {
|
||||
$this->addFile($files);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified filename or array of filenames to the list of files to
|
||||
* be minified. A filename can be in the form of a relative path or a URL
|
||||
* that resolves to the same site that hosts Minify.
|
||||
*
|
||||
* @param array|string $files filename or array of filenames
|
||||
* @see getFiles()
|
||||
* @see removeFile()
|
||||
*/
|
||||
public function addFile($files) {
|
||||
$files = @array_map(array($this, 'resolveFilePath'), (array) $files);
|
||||
$this->files = array_unique(array_merge($this->files, $files));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to serve the combined, minified files from the cache if possible.
|
||||
*
|
||||
* This method first checks the ETag value and If-Modified-Since timestamp
|
||||
* sent by the browser and exits with an HTTP "304 Not Modified" response if
|
||||
* the requested files haven't changed since they were last sent to the
|
||||
* client.
|
||||
*
|
||||
* If the browser hasn't cached the content, we check to see if it's been
|
||||
* cached on the server and, if so, we send the cached content and exit.
|
||||
*
|
||||
* If neither the client nor the server has the content in its cache, we don't
|
||||
* do anything.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function browserCache() {
|
||||
$hash = $this->getHash();
|
||||
$lastModified = $this->getLastModified();
|
||||
|
||||
$lastModifiedGMT = gmdate('D, d M Y H:i:s', $lastModified).' GMT';
|
||||
|
||||
// Check/set the ETag.
|
||||
$etag = $hash.'_'.$lastModified;
|
||||
|
||||
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
|
||||
if (strpos($_SERVER['HTTP_IF_NONE_MATCH'], $etag) !== false) {
|
||||
header("Last-Modified: $lastModifiedGMT", true, 304);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
header('ETag: "'.$etag.'"');
|
||||
|
||||
// Check If-Modified-Since.
|
||||
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
||||
if ($lastModified <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
||||
header("Last-Modified: $lastModifiedGMT", true, 304);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
header("Last-Modified: $lastModifiedGMT");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines and returns the contents of all files that have been added with
|
||||
* addFile() or via this class's constructor.
|
||||
*
|
||||
* If MINIFY_USE_CACHE is true, the content will be returned from the server's
|
||||
* cache if the cache is up to date; otherwise the new content will be saved
|
||||
* to the cache for future use.
|
||||
*
|
||||
* @param bool $minify minify the combined contents before returning them
|
||||
* @return string combined file contents
|
||||
*/
|
||||
public function combine($minify = true) {
|
||||
// Return contents from server cache if possible.
|
||||
if (MINIFY_USE_CACHE) {
|
||||
if ($cacheResult = $this->serverCache(true)) {
|
||||
return $cacheResult;
|
||||
}
|
||||
}
|
||||
|
||||
// Combine contents.
|
||||
$combined = array();
|
||||
|
||||
foreach($this->files as $file) {
|
||||
if ($this->type === self::TYPE_CSS && MINIFY_REWRITE_CSS_URLS) {
|
||||
// Rewrite relative CSS URLs.
|
||||
$combined[] = self::rewriteCSSUrls(file_get_contents($file),
|
||||
dirname($file));
|
||||
}
|
||||
else {
|
||||
$combined[] = file_get_contents($file);
|
||||
}
|
||||
}
|
||||
|
||||
$combined = $minify ? self::min(implode("\n", $combined), $this->type) :
|
||||
implode("\n", $combined);
|
||||
|
||||
// Save combined contents to the cache.
|
||||
if (MINIFY_USE_CACHE) {
|
||||
$cacheFile = MINIFY_CACHE_DIR.'/minify_'.$this->getHash();
|
||||
@file_put_contents($cacheFile, $combined, LOCK_EX);
|
||||
}
|
||||
|
||||
return $combined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of absolute pathnames of all files that have been added with
|
||||
* addFile() or via this class's constructor.
|
||||
*
|
||||
* @return array array of absolute pathnames
|
||||
* @see addFile()
|
||||
* @see removeFile()
|
||||
*/
|
||||
public function getFiles() {
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MD5 hash of the concatenated filenames from the list of files to
|
||||
* be minified.
|
||||
*/
|
||||
public function getHash() {
|
||||
return hash('md5', implode('', $this->files));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp of the most recently modified file.
|
||||
*
|
||||
* @return int timestamp
|
||||
*/
|
||||
public function getLastModified() {
|
||||
$lastModified = 0;
|
||||
|
||||
// Get the timestamp of the most recently modified file.
|
||||
foreach($this->files as $file) {
|
||||
$modified = filemtime($file);
|
||||
|
||||
if ($modified !== false && $modified > $lastModified) {
|
||||
$lastModified = $modified;
|
||||
}
|
||||
}
|
||||
|
||||
return $lastModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified filename or array of filenames from the list of files
|
||||
* to be minified.
|
||||
*
|
||||
* @param array|string $files filename or array of filenames
|
||||
* @see addFile()
|
||||
* @see getFiles()
|
||||
*/
|
||||
public function removeFile($files) {
|
||||
$files = @array_map(array($this, 'resolveFilePath'), (array) $files);
|
||||
$this->files = array_diff($this->files, $files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to serve the combined, minified files from the server's disk-based
|
||||
* cache if possible.
|
||||
*
|
||||
* @param bool $return return cached content as a string instead of outputting
|
||||
* it to the client
|
||||
* @return bool|string
|
||||
*/
|
||||
public function serverCache($return = false) {
|
||||
$cacheFile = MINIFY_CACHE_DIR.'/minify_'.$this->getHash();
|
||||
$lastModified = $this->getLastModified();
|
||||
|
||||
if (is_file($cacheFile) && $lastModified <= filemtime($cacheFile)) {
|
||||
if ($return) {
|
||||
return file_get_contents($cacheFile);
|
||||
}
|
||||
else {
|
||||
echo file_get_contents($cacheFile);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// -- Protected Instance Methods ---------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the canonicalized absolute pathname to the specified file or local
|
||||
* URL.
|
||||
*
|
||||
* @param string $file relative file path
|
||||
* @return string canonicalized absolute pathname
|
||||
*/
|
||||
protected function resolveFilePath($file) {
|
||||
// Is this a URL?
|
||||
if (preg_match('/^https?:\/\//i', $file)) {
|
||||
if (!$parsedUrl = parse_url($file)) {
|
||||
throw new MinifyInvalidUrlException("Invalid URL: $file");
|
||||
}
|
||||
|
||||
// Does the server name match the local server name?
|
||||
if (!isset($parsedUrl['host']) ||
|
||||
$parsedUrl['host'] != $_SERVER['SERVER_NAME']) {
|
||||
throw new MinifyInvalidUrlException('Non-local URL not supported: '.
|
||||
$file);
|
||||
}
|
||||
|
||||
// Get the file's absolute path.
|
||||
$filepath = realpath(MINIFY_BASE_DIR.$parsedUrl['path']);
|
||||
}
|
||||
else {
|
||||
// Get the file's absolute path.
|
||||
$filepath = realpath(MINIFY_BASE_DIR.'/'.$file);
|
||||
}
|
||||
|
||||
// Ensure that the file exists, that the path is under the base directory,
|
||||
// that the file's extension is either '.css' or '.js', and that the file is
|
||||
// actually readable.
|
||||
if (!$filepath ||
|
||||
!is_file($filepath) ||
|
||||
!is_readable($filepath) ||
|
||||
!preg_match('/^'.preg_quote(MINIFY_BASE_DIR, '/').'/', $filepath) ||
|
||||
!preg_match('/\.(?:css|js)$/iD', $filepath)) {
|
||||
|
||||
// Even when the file exists, we still throw a
|
||||
// MinifyFileNotFoundException in order to try to prevent an information
|
||||
// disclosure vulnerability.
|
||||
throw new MinifyFileNotFoundException("File not found: $file");
|
||||
}
|
||||
|
||||
return $filepath;
|
||||
}
|
||||
}
|
||||
|
||||
// -- Exception Classes --------------------------------------------------------
|
||||
class MinifyException extends Exception {}
|
||||
class MinifyFileNotFoundException extends MinifyException {}
|
||||
class MinifyInvalidArgumentException extends MinifyException {}
|
||||
class MinifyInvalidUrlException extends MinifyException {}
|
||||
|
||||
// -- Global Scope -------------------------------------------------------------
|
||||
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) {
|
||||
Minify::handleRequest();
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
// using same lib path and cache path specified in /min/config.php
|
||||
|
||||
require dirname(__FILE__) . '/../min/config.php';
|
||||
|
||||
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
$minifyCachePath = isset($min_cachePath)
|
||||
? $min_cachePath
|
||||
: '';
|
||||
|
||||
function min_autoload($name) {
|
||||
require str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php';
|
||||
}
|
||||
spl_autoload_register('min_autoload');
|
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
$base = realpath(dirname(__FILE__) . '/..');
|
||||
$groupsSources = array(
|
||||
'js' => array(
|
||||
"{$base}/lib.js"
|
||||
,"{$base}/test space.js"
|
||||
)
|
||||
,'css' => array("{$base}/test.css")
|
||||
);
|
||||
unset($base);
|
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
require '../../config.php';
|
||||
require '_groupsSources.php';
|
||||
|
||||
$jsBuild = new Minify_Build($groupsSources['js']);
|
||||
$cssBuild = new Minify_Build($groupsSources['css']);
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Minify Example 1</title>
|
||||
<link rel="stylesheet" type="text/css" href="<?php echo $cssBuild->uri('m.php/css'); ?>" />
|
||||
<style type="text/css">#cssFail {width:2.8em; overflow:hidden;}</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<?php if (! $minifyCachePath): ?>
|
||||
<p><strong>Note:</strong> You should <em>always</em> enable caching using
|
||||
<code>Minify::setCache()</code>. For the examples this can be set in
|
||||
<code>config.php</code>.</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<h1>Minify Example 1 : Groups controller + Far-off Expires header</h1>
|
||||
|
||||
<p>In this example, we use a single config file <code>_groupsSources.php</code>
|
||||
to specify files for minification. During HTML generation,
|
||||
<code>Minify_Build</code> is used
|
||||
to stamp the latest modification times onto the minify URLs. Our minify server,
|
||||
<code>m.php</code>, then sends the content with far-off Expires headers.</p>
|
||||
|
||||
<p>If one of our sources is modified, its URL (particularly the query string) is
|
||||
changed in the HTML document, causing the browser to request a new version.</p>
|
||||
|
||||
<h2>Minify tests</h2>
|
||||
<ul>
|
||||
<li id="cssFail"><span>FAIL</span>PASS</li>
|
||||
<li id="jsFail1">FAIL</li>
|
||||
</ul>
|
||||
|
||||
<h2>Test client cache</h2>
|
||||
<p>When you <a href="">click here</a> to reload the page, your browser should
|
||||
not have to re-download the minified files.</p>
|
||||
|
||||
<p style='text-align:right'><a href="../2/">example 2 »</a></p>
|
||||
|
||||
<script type="text/javascript" src="<?php echo $jsBuild->uri('m.php/js'); ?>"></script>
|
||||
</body>
|
||||
</html>
|
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
require '../../config.php';
|
||||
require '_groupsSources.php';
|
||||
|
||||
if ($minifyCachePath) {
|
||||
Minify::setCache($minifyCachePath);
|
||||
}
|
||||
|
||||
Minify::serve('Groups', array(
|
||||
'groups' => $groupsSources
|
||||
,'setExpires' => time() + 86400 * 365
|
||||
));
|
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
$base = realpath(dirname(__FILE__) . '/..');
|
||||
$groupsSources = array(
|
||||
'js' => array(
|
||||
"{$base}/lib.js"
|
||||
,"{$base}/test space.js"
|
||||
)
|
||||
,'css' => array("{$base}/test.css")
|
||||
);
|
||||
unset($base);
|
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
require '../../config.php';
|
||||
require '_groupsSources.php';
|
||||
|
||||
$jsBuild = new Minify_Build($groupsSources['js']);
|
||||
$cssBuild = new Minify_Build($groupsSources['css']);
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Minify Example 2</title>
|
||||
<link rel="stylesheet" type="text/css" href="<?php echo $cssBuild->uri('m.php/css'); ?>" />
|
||||
<style type="text/css">
|
||||
|
||||
#cssFail {
|
||||
width:2.8em;
|
||||
overflow:hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<?php if (! $minifyCachePath): ?>
|
||||
<p><strong>Note:</strong> You should <em>always</em> enable caching using
|
||||
<code>Minify::setCache()</code>. For the examples this can be set in
|
||||
<code>config.php</code>.</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<h1>Minify Example 2: Minifying <em>Everything</em></h1>
|
||||
|
||||
<p>In this example, external Javascript and CSS minification is identical to
|
||||
example 1, but here Minify is also used to minify and serve the HTML, including
|
||||
the contents of all <code><style></code> and <code><script></code>
|
||||
elements.</p>
|
||||
|
||||
<p>As the document is XHTML, Minify_HTML places the 2nd <code><script></code>
|
||||
element in a CDATA section because it contains "<". The output is valid XHTML.</p>
|
||||
|
||||
<h2><a href="http://validator.w3.org/check/referer"
|
||||
onclick="this.target='_blank'">Validate XHTML</a></h2>
|
||||
|
||||
<h2>Minify tests</h2>
|
||||
<ul>
|
||||
<li id="cssFail"><span>FAIL</span>PASS</li>
|
||||
<li id="jsFail1">FAIL</li>
|
||||
<li id="jsFail2">FAIL</li>
|
||||
</ul>
|
||||
|
||||
<h2>Test client cache</h2>
|
||||
<p>When you <a href="">click here</a> to reload the page, your browser should
|
||||
not have to re-download any files.</p>
|
||||
|
||||
<p style='text-align:right'><a href="../../">extras index »</a></p>
|
||||
|
||||
<script type="text/javascript" src="<?php echo $jsBuild->uri('m.php/js'); ?>"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var wo = window.onload;
|
||||
window.onload = function () {
|
||||
wo && wo();
|
||||
if ( 1 < 2 ) {
|
||||
html('jsFail2', 'PASS');
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
|
||||
if ($minifyCachePath) {
|
||||
Minify::useServerCache($minifyCachePath);
|
||||
}
|
||||
|
||||
$pageLastUpdate = max(
|
||||
filemtime(__FILE__)
|
||||
,$jsBuild->lastModified
|
||||
,$cssBuild->lastModified
|
||||
);
|
||||
|
||||
Minify::serve('Page', array(
|
||||
'content' => $content
|
||||
,'id' => __FILE__
|
||||
,'lastModifiedTime' => $pageLastUpdate
|
||||
// also minify the CSS/JS inside the HTML
|
||||
,'minifyAll' => true
|
||||
));
|
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
require '../../config.php';
|
||||
require '_groupsSources.php';
|
||||
|
||||
if ($minifyCachePath) {
|
||||
Minify::setCache($minifyCachePath);
|
||||
}
|
||||
|
||||
Minify::serve('Groups', array(
|
||||
'groups' => $groupsSources
|
||||
,'setExpires' => time() + 86400 * 365
|
||||
));
|
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
header('Location: 1/');
|
@@ -1,6 +0,0 @@
|
||||
|
||||
function html(id, html) {
|
||||
|
||||
document.getElementById(id).innerHTML = html;
|
||||
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
window.onload = function () {
|
||||
|
||||
html('jsFail1', 'PASS');
|
||||
|
||||
};
|
@@ -1,41 +0,0 @@
|
||||
/* Test file to minify */
|
||||
|
||||
/*! copyright notice here... */
|
||||
|
||||
html {
|
||||
margin:0;
|
||||
padding:0;
|
||||
background:#aaa;
|
||||
}
|
||||
body {
|
||||
margin:0 auto;
|
||||
padding:1em;
|
||||
width:550px;
|
||||
background:#fff;
|
||||
}
|
||||
body > *:first-child {margin-top:0;}
|
||||
|
||||
h1 {
|
||||
color: #00cc00;
|
||||
font-size: 20px;
|
||||
}
|
||||
h2 {
|
||||
color: #009900;
|
||||
font-size: 17px;
|
||||
}
|
||||
h1, h2 {margin:1.3em 0 .3em;}
|
||||
|
||||
p {
|
||||
margin:0 0 1em;
|
||||
}
|
||||
|
||||
ul, li {
|
||||
padding:0;
|
||||
margin:0;
|
||||
display:block;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#cssFail span {
|
||||
display: none;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 686 B |
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (isset($_FILES['subject']['name'])) {
|
||||
|
||||
require '../config.php';
|
||||
|
||||
$he = new HTTP_Encoder(array(
|
||||
'content' => file_get_contents($_FILES['subject']['tmp_name'])
|
||||
,'method' => $_POST['method']
|
||||
));
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header("Content-Disposition: attachment; filename=\"{$_FILES['subject']['name']}."
|
||||
. ($_POST['method'] == 'deflate'
|
||||
? 'zd'
|
||||
: ($_POST['method'] == 'gzip'
|
||||
? 'zg'
|
||||
: 'zc'
|
||||
)
|
||||
) . '"');
|
||||
$he->encode(9);
|
||||
echo $he->getContent();
|
||||
exit();
|
||||
}
|
||||
|
||||
?>
|
||||
<form enctype="multipart/form-data" action="" method="post">
|
||||
<p>Encode <input type="file" name="subject" /><br />
|
||||
as <input type="submit" name="method" value="deflate" />
|
||||
<input type="submit" name="method" value="gzip" />
|
||||
<input type="submit" name="method" value="compress" />
|
||||
</p>
|
||||
</form>
|
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (isset($_FILES['subject']['name'])
|
||||
&& preg_match('/\\.(js|css|x?html?)$/', $_FILES['subject']['name'], $m)
|
||||
) {
|
||||
require '../config.php';
|
||||
|
||||
$arg2 = null;
|
||||
switch ($m[1]) {
|
||||
case 'js':
|
||||
$type = 'Javascript';
|
||||
break;
|
||||
case 'css':
|
||||
$type = 'CSS';
|
||||
break;
|
||||
case 'html': // fallthrough
|
||||
case 'htm': // fallthrough
|
||||
case 'xhtml':
|
||||
$type = 'HTML';
|
||||
$arg2 = array(
|
||||
'cssMinifier' => array('Minify_CSS', 'minify')
|
||||
,'jsMinifier' => array('JSMin', 'minify')
|
||||
);
|
||||
}
|
||||
$func = array('Minify_' . $type, 'minify');
|
||||
|
||||
$out = call_user_func($func, file_get_contents($_FILES['subject']['tmp_name']), $arg2);
|
||||
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Content-Disposition: attachment; filename="'
|
||||
. preg_replace('/\\.(\w+)$/', '.min.$1', $_FILES['subject']['name'])
|
||||
. '"');
|
||||
|
||||
//@unlink($_FILES['subject']['tmp_name']);
|
||||
echo $out;
|
||||
exit();
|
||||
}
|
||||
|
||||
?>
|
||||
<form enctype="multipart/form-data" action="" method="post">
|
||||
<p>Minify <input type="file" name="subject" /><br />
|
||||
<input type="submit" name="method" value="Go!" />
|
||||
</p>
|
||||
</form>
|
@@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
function getPost($key) {
|
||||
return get_magic_quotes_gpc()
|
||||
? stripslashes($_POST[$key])
|
||||
: $_POST[$key];
|
||||
}
|
||||
|
||||
if (isset($_POST['textIn'])) {
|
||||
require '../config.php';
|
||||
$textIn = str_replace("\r\n", "\n", getPost('textIn'));
|
||||
}
|
||||
|
||||
if (isset($_POST['method']) && $_POST['method'] === 'Minify and serve') {
|
||||
|
||||
$base = trim(getPost('base'));
|
||||
if ($base) {
|
||||
$textIn = preg_replace(
|
||||
'@(<head\\b[^>]*>)@i'
|
||||
,'$1<base href="' . htmlentities($base) . '" />'
|
||||
,$textIn
|
||||
);
|
||||
}
|
||||
|
||||
$sourceSpec['content'] = $textIn;
|
||||
$sourceSpec['id'] = 'foo';
|
||||
if (isset($_POST['minJs'])) {
|
||||
$sourceSpec['minifyOptions']['jsMinifier'] = array('JSMin', 'minify');
|
||||
}
|
||||
if (isset($_POST['minCss'])) {
|
||||
$sourceSpec['minifyOptions']['cssMinifier'] = array('Minify_CSS', 'minify');
|
||||
}
|
||||
$source = new Minify_Source($sourceSpec);
|
||||
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
||||
Minify::serve('Files', array(
|
||||
'files' => $source
|
||||
,'contentType' => Minify::TYPE_HTML
|
||||
));
|
||||
exit();
|
||||
}
|
||||
|
||||
$classes = array('Minify_HTML', 'Minify_CSS', 'JSMin', 'JSMinPlus');
|
||||
|
||||
if (isset($_POST['method']) && in_array($_POST['method'], $classes)) {
|
||||
|
||||
$arg2 = null;
|
||||
if ($_POST['method'] === 'Minify_HTML') {
|
||||
$arg2 = array(
|
||||
'cssMinifier' => array('Minify_CSS', 'minify')
|
||||
,'jsMinifier' => array('JSMin', 'minify')
|
||||
);
|
||||
}
|
||||
$func = array($_POST['method'], 'minify');
|
||||
$inOutBytes[0] = strlen($textIn);
|
||||
$textOut = call_user_func($func, $textIn, $arg2);
|
||||
$inOutBytes[1] = strlen($textOut);
|
||||
}
|
||||
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
?>
|
||||
<!DOCTYPE html><head><title>minifyTextarea</title></head>
|
||||
<?php
|
||||
if (isset($inOutBytes)) {
|
||||
echo "
|
||||
<table>
|
||||
<tr><th>Bytes in</th><td>{$inOutBytes[0]} (after line endings normalized to <code>\\n</code>)</td></tr>
|
||||
<tr><th>Bytes out</th><td>{$inOutBytes[1]} (" . round(100 * $inOutBytes[1] / $inOutBytes[0]) . "%)</td></tr>
|
||||
</table>
|
||||
";
|
||||
}
|
||||
?>
|
||||
<form action="?2" method="post">
|
||||
<p><label>Content<br><textarea name="textIn" cols="80" rows="35" style="width:99%"><?php
|
||||
if (isset($textOut)) {
|
||||
echo htmlspecialchars($textOut);
|
||||
}
|
||||
?></textarea></label></p>
|
||||
<p>Minify with:
|
||||
<?php foreach ($classes as $minClass): ?>
|
||||
<input type="submit" name="method" value="<?php echo $minClass; ?>">
|
||||
<?php endForEach; ?>
|
||||
</p>
|
||||
<p>...or <input type="submit" name="method" value="Minify and serve"> this HTML to the browser. Also minify:
|
||||
<label>CSS <input type="checkbox" name="minCss" checked></label> :
|
||||
<label>JS <input type="checkbox" name="minJs" checked></label>.
|
||||
<label>Insert BASE element w/ href: <input type="text" name="base" size="20"></label>
|
||||
</p>
|
||||
</form>
|
@@ -1,159 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Fetch and minify a URL (auto-detect HTML/JS/CSS)
|
||||
*/
|
||||
|
||||
function getPost($key) {
|
||||
if (! isset($_POST[$key])) {
|
||||
return null;
|
||||
}
|
||||
return get_magic_quotes_gpc()
|
||||
? stripslashes($_POST[$key])
|
||||
: $_POST[$key];
|
||||
}
|
||||
|
||||
function sniffType($headers) {
|
||||
$charset = 'utf-8';
|
||||
$type = null;
|
||||
$headers = "\n\n" . implode("\n\n", $headers) . "\n\n";
|
||||
if (preg_match(
|
||||
'@\\n\\nContent-Type: *([\\w/\\+-]+)( *; *charset *= *([\\w-]+))? *\\n\\n@i'
|
||||
,$headers
|
||||
,$m)) {
|
||||
$sentType = $m[1];
|
||||
if (isset($m[3])) {
|
||||
$charset = $m[3];
|
||||
}
|
||||
if (preg_match('@^(?:text|application)/(?:x-)?(?:java|ecma)script$@i', $sentType)) {
|
||||
$type = 'application/x-javascript';
|
||||
} elseif (preg_match('@^(?:text|application)/(?:html|xml|xhtml+xml)$@i', $sentType, $m)) {
|
||||
$type = 'text/html';
|
||||
} elseif ($sentType === 'text/css') {
|
||||
$type = $sentType;
|
||||
}
|
||||
}
|
||||
return array(
|
||||
'minify' => $type
|
||||
,'sent' => $sentType
|
||||
,'charset' => $charset
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($_POST['url'])) {
|
||||
|
||||
require '../config.php';
|
||||
|
||||
$url = trim(getPost('url'));
|
||||
$ua = trim(getPost('ua'));
|
||||
$cook = trim(getPost('cook'));
|
||||
|
||||
if (! preg_match('@^https?://@', $url)) {
|
||||
die('HTTP(s) only.');
|
||||
}
|
||||
|
||||
$httpOpts = array(
|
||||
'max_redirects' => 0
|
||||
,'timeout' => 3
|
||||
);
|
||||
if ($ua !== '') {
|
||||
$httpOpts['user_agent'] = $ua;
|
||||
}
|
||||
if ($cook !== '') {
|
||||
$httpOpts['header'] = "Cookie: {$cook}\r\n";
|
||||
}
|
||||
$ctx = stream_context_create(array(
|
||||
'http' => $httpOpts
|
||||
));
|
||||
|
||||
// fetch
|
||||
if (! ($fp = @fopen($url, 'r', false, $ctx))) {
|
||||
die('Couldn\'t open URL.');
|
||||
}
|
||||
$meta = stream_get_meta_data($fp);
|
||||
$content = stream_get_contents($fp);
|
||||
fclose($fp);
|
||||
|
||||
// get type info
|
||||
$type = sniffType($meta['wrapper_data']);
|
||||
if (! $type['minify']) {
|
||||
die('Unrecognized Content-Type: ' . $type['sent']);
|
||||
}
|
||||
|
||||
if ($type['minify'] === 'text/html'
|
||||
&& isset($_POST['addBase'])
|
||||
&& ! preg_match('@<base\\b@i', $content)) {
|
||||
$content = preg_replace(
|
||||
'@(<head\\b[^>]*>)@i'
|
||||
,'$1<base href="' . htmlentities($url) . '" />'
|
||||
,$content
|
||||
);
|
||||
}
|
||||
|
||||
$sourceSpec['content'] = $content;
|
||||
$sourceSpec['id'] = 'foo';
|
||||
|
||||
if ($type['minify'] === 'text/html') {
|
||||
if (isset($_POST['minJs'])) {
|
||||
$sourceSpec['minifyOptions']['jsMinifier'] = array('JSMin', 'minify');
|
||||
}
|
||||
if (isset($_POST['minCss'])) {
|
||||
$sourceSpec['minifyOptions']['cssMinifier'] = array('Minify_CSS', 'minify');
|
||||
}
|
||||
}
|
||||
|
||||
$source = new Minify_Source($sourceSpec);
|
||||
|
||||
$sendType = 'text/plain';
|
||||
if ($type['minify'] === 'text/html' && ! isset($_POST['asText'])) {
|
||||
$sendType = $type['sent'];
|
||||
}
|
||||
if ($type['charset']) {
|
||||
$sendType .= ';charset=' . $type['charset'];
|
||||
}
|
||||
header('Content-Type: ' . $sendType);
|
||||
// using combine instead of serve because it allows us to specify a
|
||||
// Content-Type like application/xhtml+xml IF we need to
|
||||
echo Minify::combine(array($source), array(
|
||||
'contentType' => $type['minify']
|
||||
));
|
||||
exit();
|
||||
}
|
||||
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
|
||||
$ua = get_magic_quotes_gpc()
|
||||
? stripslashes($_SERVER['HTTP_USER_AGENT'])
|
||||
: $_SERVER['HTTP_USER_AGENT'];
|
||||
|
||||
?>
|
||||
<!DOCTYPE html><head><title>Minify URL</title></head>
|
||||
|
||||
<p><strong>Warning! Please do not place this application on a public site.</strong> This should be used
|
||||
only for testing.</p>
|
||||
|
||||
<h1>Fetch and Minify a URL</h1>
|
||||
<p>This tool will retrieve the contents of a URL and minify it.
|
||||
The fetched resource Content-Type will determine the minifier used.</p>
|
||||
|
||||
<form action="?2" method="post">
|
||||
<p><label>URL: <input type="text" name="url" size="60"></label></p>
|
||||
<p><input type="submit" value="Fetch and minify"></p>
|
||||
|
||||
<fieldset><legend>HTML options</legend>
|
||||
<p>If the resource above is sent with an (x)HTML Content-Type, the following options will apply:</p>
|
||||
<ul>
|
||||
<li><label><input type="checkbox" name="asText" checked> Return plain text (o/w send the original content type)</label>
|
||||
<li><label><input type="checkbox" name="minCss" checked> Minify CSS</label>
|
||||
<li><label><input type="checkbox" name="minJs" checked> Minify JS</label>
|
||||
<li><label><input type="checkbox" name="addBase" checked> Add BASE element (if not present)</label>
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
||||
<fieldset><legend>Retreival options</legend>
|
||||
<ul>
|
||||
<li><label>User-Agent: <input type="text" name="ua" size="60" value="<?php echo htmlspecialchars($ua); ?>"></label>
|
||||
<li><label>Cookie: <input type="text" name="cook" size="60"></label>
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
||||
</form>
|
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
header('Content-Type: text/html;charset=utf-8');
|
||||
|
||||
function h($str) { return htmlspecialchars($str, ENT_QUOTES); }
|
||||
|
||||
function getPost($name, $default = '') { return isset($_POST[$name]) ? $_POST[$name] : $default; }
|
||||
|
||||
function getInput($name, $default = '', $size = 50) {
|
||||
$val = h(isset($_POST[$name]) ? $_POST[$name] : $default);
|
||||
return "<input type='text' name='{$name}' value='{$val}' size='{$size}' />";
|
||||
}
|
||||
|
||||
// validate user POST (no arrays and fix slashes)
|
||||
if (! empty($_POST)) {
|
||||
foreach ($_POST as $name => $val) {
|
||||
if (! is_string($val)) {
|
||||
unset($_POST[$name]);
|
||||
continue;
|
||||
}
|
||||
if (get_magic_quotes_gpc()) {
|
||||
$_POST[$name] = stripslashes($val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$defaultCurrentDir = dirname(__FILE__);
|
||||
$defaultDocRoot = realpath($_SERVER['DOCUMENT_ROOT']);
|
||||
$defaultSymLink = '//symlinkPath';
|
||||
$defaultSymTarget = ($defaultCurrentDir[0] === '/') ? '/tmp' : 'C:\\WINDOWS\\Temp';
|
||||
$defaultCss = "url(hello.gif)\nurl(../hello.gif)\nurl(../../hello.gif)\nurl(up/hello.gif)";
|
||||
|
||||
$out = '';
|
||||
|
||||
if (isset($_POST['css'])) {
|
||||
require '../config.php';
|
||||
$symlinks = array();
|
||||
if ('' !== ($target = getPost('symTarget'))) {
|
||||
$symlinks[getPost('symLink')] = $target;
|
||||
}
|
||||
$css = Minify_CSS_UriRewriter::rewrite(
|
||||
getPost('css')
|
||||
, getPost('currentDir')
|
||||
, getPost('docRoot')
|
||||
, $symlinks
|
||||
);
|
||||
$out = "<hr /><pre><code>" . h($css) . '</code></pre>';
|
||||
}
|
||||
|
||||
?>
|
||||
<h1>Test <code>Minify_CSS_UriRewriter::rewrite()</code></h1>
|
||||
<form action="" method="post">
|
||||
<div><label>document root: <?php echo getInput('docRoot', $defaultDocRoot); ?></label></div>
|
||||
<div><label>symlink: <?php echo getInput('symLink', $defaultSymLink); ?> => <?php echo getInput('symTarget', $defaultSymTarget); ?></label></div>
|
||||
<div><label>current directory: <?php echo getInput('currentDir', $defaultCurrentDir); ?></label></div>
|
||||
<p><label>input CSS: <textarea name="css" cols="80" rows="5"><?php echo h(getPost('css', $defaultCss)); ?></textarea></label></p>
|
||||
<p><input type="submit" value="rewrite()" /></p>
|
||||
</form>
|
||||
<?php echo $out; ?>
|
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__) . '/../../min/lib'));
|
||||
require 'HTTP/ConditionalGet.php';
|
||||
|
||||
// emulate regularly updating document
|
||||
$every = 20;
|
||||
$lastModified = round(time()/$every)*$every - $every;
|
||||
|
||||
$cg = new HTTP_ConditionalGet(array(
|
||||
'lastModifiedTime' => $lastModified
|
||||
));
|
||||
if ($cg->cacheIsValid) {
|
||||
$cg->sendHeaders();
|
||||
// we're done
|
||||
exit();
|
||||
}
|
||||
|
||||
// generate content
|
||||
$title = 'Last-Modified is known : add Content-Length';
|
||||
$explain = '
|
||||
<p>Here, like <a href="./">the first example</a>, we know the Last-Modified time,
|
||||
but we also want to set the Content-Length to increase cacheability and allow
|
||||
HTTP persistent connections. Instead of sending headers immediately, we first
|
||||
generate our content, then use <code>setContentLength(strlen($content))</code>
|
||||
to add the header. Then finally call <code>sendHeaders()</code> and send the
|
||||
content.</p>
|
||||
<p><strong>Note:</strong> This is not required if your PHP config buffers all
|
||||
output and your script doesn\'t do any incremental flushing of the output
|
||||
buffer. PHP will generally set Content-Length for you if it can.</p>
|
||||
<p>This script emulates a document that changes every ' .$every. ' seconds.
|
||||
<br>This is version: ' . date('r', $lastModified) . '</p>
|
||||
';
|
||||
|
||||
require '_include.php';
|
||||
$content = get_content(array(
|
||||
'title' => $title
|
||||
,'explain' => $explain
|
||||
));
|
||||
|
||||
$cg->setContentLength(strlen($content));
|
||||
$cg->sendHeaders();
|
||||
send_slowly($content);
|
||||
|
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__) . '/../../min/lib'));
|
||||
require 'HTTP/ConditionalGet.php';
|
||||
|
||||
// generate content first (not ideal)
|
||||
// emulate regularly updating document
|
||||
$every = 20;
|
||||
$lastModified = round(time()/$every)*$every - $every;
|
||||
$title = 'Last-Modified is unknown : use hash of content for ETag';
|
||||
$explain = '
|
||||
<p>When Last-Modified is unknown, you can still use ETags, but you need a short
|
||||
string that is unique for that content. In the worst case, you have to generate
|
||||
all the content first, <em>then</em> instantiate HTTP_ConditionalGet, setting
|
||||
the array key <code>contentHash</code> to the output of a hash function of the
|
||||
content. Since we have the full content, we might as well also use
|
||||
<code>setContentLength(strlen($content))</code> in the case where we need to
|
||||
send it.</p>
|
||||
<p>This script emulates a document that changes every ' .$every. ' seconds.
|
||||
<br>This is version: ' . date('r', $lastModified) . '</p>
|
||||
';
|
||||
require '_include.php';
|
||||
$content = get_content(array(
|
||||
'title' => $title
|
||||
,'explain' => $explain
|
||||
));
|
||||
|
||||
$cg = new HTTP_ConditionalGet(array(
|
||||
'contentHash' => substr(md5($content), 7)
|
||||
));
|
||||
if ($cg->cacheIsValid) {
|
||||
$cg->sendHeaders();
|
||||
// we're done
|
||||
exit();
|
||||
}
|
||||
$cg->setContentLength(strlen($content));
|
||||
$cg->sendHeaders();
|
||||
|
||||
send_slowly($content);
|
||||
|
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__) . '/../../min/lib'));
|
||||
require 'HTTP/ConditionalGet.php';
|
||||
|
||||
// emulate regularly updating document
|
||||
$every = 20;
|
||||
$lastModified = round(time()/$every)*$every - $every;
|
||||
|
||||
require 'HTTP/Encoder.php';
|
||||
list($enc,) = HTTP_Encoder::getAcceptedEncoding();
|
||||
|
||||
$cg = new HTTP_ConditionalGet(array(
|
||||
'lastModifiedTime' => $lastModified
|
||||
,'encoding' => $enc
|
||||
));
|
||||
$cg->sendHeaders();
|
||||
if ($cg->cacheIsValid) {
|
||||
// we're done
|
||||
exit();
|
||||
}
|
||||
|
||||
// output encoded content
|
||||
|
||||
$title = 'ConditionalGet + Encoder';
|
||||
$explain = '
|
||||
<p>Using ConditionalGet and Encoder is straightforward. First impliment the
|
||||
ConditionalGet, then if the cache is not valid, encode and send the content</p>
|
||||
<p>This script emulates a document that changes every ' .$every. ' seconds.
|
||||
<br>This is version: ' . date('r', $lastModified) . '</p>
|
||||
';
|
||||
require '_include.php';
|
||||
$content = get_content(array(
|
||||
'title' => $title
|
||||
,'explain' => $explain
|
||||
));
|
||||
|
||||
$he = new HTTP_Encoder(array(
|
||||
'content' => get_content(array(
|
||||
'title' => $title
|
||||
,'explain' => $explain
|
||||
))
|
||||
));
|
||||
$he->encode();
|
||||
|
||||
// usually you would just $he->sendAll(), but here we want to emulate slow
|
||||
// connection
|
||||
$he->sendHeaders();
|
||||
send_slowly($he->getContent());
|
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__) . '/../../min/lib'));
|
||||
require 'HTTP/ConditionalGet.php';
|
||||
|
||||
// far expires
|
||||
$cg = new HTTP_ConditionalGet(array(
|
||||
'maxAge' => 20
|
||||
,'lastModifiedTime' => filemtime(__FILE__)
|
||||
));
|
||||
$cg->sendHeaders();
|
||||
|
||||
// generate, send content
|
||||
$title = 'Last-Modified + Expires';
|
||||
$explain = '
|
||||
<p>Here we set a static "lastModifiedTime" and "maxAge" to 20. The browser
|
||||
will consider this document fresh for 20 seconds, then revalidate its cache. After
|
||||
the 304 response, the cache will be good for another 20 seconds. Unless you force
|
||||
a reload, there will only be 304 responses for this page after the initial download.
|
||||
';
|
||||
|
||||
require '_include.php';
|
||||
echo get_content(array(
|
||||
'title' => $title
|
||||
,'explain' => $explain
|
||||
));
|
||||
|
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
function send_slowly($content)
|
||||
{
|
||||
$half = ceil(strlen($content) / 2);
|
||||
$content = str_split($content, $half);
|
||||
while ($chunk = array_shift($content)) {
|
||||
sleep(1);
|
||||
echo $chunk;
|
||||
ob_get_level() && ob_flush();
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
function get_content($data)
|
||||
{
|
||||
ob_start();
|
||||
?>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>HTTP_ConditionalGet : <?php echo $data['title']; ?></title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>HTTP_ConditionalGet</h1>
|
||||
<h2><?php echo $data['title']; ?></h2>
|
||||
<?php echo $data['explain']; ?>
|
||||
<ul>
|
||||
<li><a href="./">Last-Modified is known : simple usage</a></li>
|
||||
<li><a href="2.php">Last-Modified is known : add Content-Length</a></li>
|
||||
<li><a href="3.php">Last-Modified is unknown : use hash of content for ETag</a></li>
|
||||
<li><a href="4.php">ConditionalGet + Encoder</a></li>
|
||||
<li><a href="5.php">Last-Modified + Expires</a></li>
|
||||
</ul>
|
||||
<h2>Notes</h2>
|
||||
<h3>How to distinguish 200 and 304 responses</h3>
|
||||
<p>For these pages all 200 responses are sent in chunks a second apart, so you
|
||||
should notice that 304 responses are quicker. You can also use HTTP sniffers
|
||||
like <a href="http://www.fiddlertool.com/">Fiddler (win)</a> and
|
||||
<a href="http://livehttpheaders.mozdev.org/">LiveHTTPHeaders (Firefox add-on)</a>
|
||||
to verify headers and content being sent.</p>
|
||||
<h3>Browser notes</h3>
|
||||
<dl>
|
||||
<dt>Opera</dt>
|
||||
<dd>Opera has a couple behaviors against the HTTP spec: Manual refreshes (F5)
|
||||
prevents the ETag/If-Modified-Since headers from being sent; it only sends
|
||||
them when following a link or bookmark. Also, Opera will not honor the
|
||||
<code>must-revalidate</code> Cache-Control value unless <code>max-age</code>
|
||||
is set. To get Opera to follow the spec, ConditionalGet will send Opera max-age=0
|
||||
(if one is not already set).</dd>
|
||||
<dt>Safari</dt>
|
||||
<dd>ETag validation is unsupported, but Safari supports HTTP/1.0 validation via
|
||||
If-Modified-Since headers as long as the cache is explicitly marked
|
||||
"public" or "private" ("private" is default in ConditionalGet).</dd>
|
||||
</dl>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
return $content;
|
||||
}
|
||||
|
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__) . '/../../min/lib'));
|
||||
require 'HTTP/ConditionalGet.php';
|
||||
|
||||
// emulate regularly updating document
|
||||
$every = 20;
|
||||
$lastModified = round(time()/$every)*$every - $every;
|
||||
|
||||
$cg = new HTTP_ConditionalGet(array(
|
||||
'lastModifiedTime' => $lastModified
|
||||
));
|
||||
$cg->sendHeaders();
|
||||
if ($cg->cacheIsValid) {
|
||||
// we're done
|
||||
exit();
|
||||
}
|
||||
|
||||
$title = 'Last-Modified is known : simple usage';
|
||||
$explain = '
|
||||
<p>If your content has not changed since a certain timestamp, set this via the
|
||||
the <code>lastModifiedTime</code> array key when instantiating HTTP_ConditionalGet.
|
||||
You can immediately call the method <code>sendHeaders()</code> to set the
|
||||
Last-Modified, ETag, and Cache-Control headers. The, if <code>cacheIsValid</code>
|
||||
property is false, you echo the content.</p>
|
||||
<p>This script emulates a document that changes every ' .$every. ' seconds.
|
||||
<br>This is version: ' . date('r', $lastModified) . '</p>
|
||||
';
|
||||
|
||||
require '_include.php';
|
||||
|
||||
echo send_slowly(get_content(array(
|
||||
'title' => $title
|
||||
,'explain' => $explain
|
||||
)));
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 202 B |
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
ini_set('display_errors', 'on');
|
||||
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__) . '/../../min/lib'));
|
||||
require 'HTTP/Encoder.php';
|
||||
|
||||
if (!isset($_GET['test'])) {
|
||||
$type = 'text/html';
|
||||
ob_start();
|
||||
?>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>HTTP_Encoder Test</title>
|
||||
<style type="text/css">
|
||||
@import "?test=2";
|
||||
#img {background:url("?test=1");}
|
||||
.green {background:#0f0;}
|
||||
p span {padding:0 .5em;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>HTTP_Encoder test</h1>
|
||||
<p><span class="green"> HTML </span></p>
|
||||
<p><span id="css"> CSS </span></p>
|
||||
<p><span id="js"> Javascript </span></p>
|
||||
<p><span id="img"> image </span></p>
|
||||
<script src="?test=3" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
} elseif ($_GET['test'] == '1') {
|
||||
$content = file_get_contents(dirname(__FILE__) . '/green.png');
|
||||
$type = 'image/png';
|
||||
|
||||
} elseif ($_GET['test'] == '2') {
|
||||
$content = '#css {background:#0f0;}';
|
||||
$type = 'text/css';
|
||||
|
||||
} else {
|
||||
$content = '
|
||||
window.onload = function(){
|
||||
document.getElementById("js").className = "green";
|
||||
};
|
||||
';
|
||||
$type = 'application/x-javascript';
|
||||
}
|
||||
|
||||
$he = new HTTP_Encoder(array(
|
||||
'content' => $content
|
||||
,'type' => $type
|
||||
));
|
||||
$he->encode();
|
||||
$he->sendAll();
|
||||
|
||||
?>
|
@@ -1,4 +0,0 @@
|
||||
UNIT TESTING
|
||||
|
||||
Do not modify the "simpletest" directory as it's linked via svn:externals.
|
||||
|
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
require dirname(__FILE__) . '/../min/config.php';
|
||||
|
||||
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
||||
function min_autoload($name) {
|
||||
require str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php';
|
||||
}
|
||||
spl_autoload_register('min_autoload');
|
||||
|
||||
|
||||
// set cache path and doc root if configured
|
||||
$minifyCachePath = isset($min_cachePath)
|
||||
? $min_cachePath
|
||||
: '';
|
||||
if ($min_documentRoot) {
|
||||
$_SERVER['DOCUMENT_ROOT'] = $min_documentRoot;
|
||||
}
|
||||
|
||||
// default log to FirePHP
|
||||
if ($min_errorLogger && true !== $min_errorLogger) { // custom logger
|
||||
Minify_Logger::setLogger($min_errorLogger);
|
||||
} else {
|
||||
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
||||
}
|
||||
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
header('Content-Type: text/plain');
|
||||
|
||||
$thisDir = dirname(__FILE__);
|
||||
|
||||
/**
|
||||
* pTest - PHP Unit Tester
|
||||
* @param mixed $test Condition to test, evaluated as boolean
|
||||
* @param string $message Descriptive message to output upon test
|
||||
* @url http://www.sitepoint.com/blogs/2007/08/13/ptest-php-unit-tester-in-9-lines-of-code/
|
||||
*/
|
||||
function assertTrue($test, $message)
|
||||
{
|
||||
static $count;
|
||||
if (!isset($count)) $count = array('pass'=>0, 'fail'=>0, 'total'=>0);
|
||||
|
||||
$mode = $test ? 'pass' : 'fail';
|
||||
$outMode = $test ? 'PASS' : '!FAIL';
|
||||
printf("%s: %s (%d of %d tests run so far have %sed)\n",
|
||||
$outMode, $message, ++$count[$mode], ++$count['total'], $mode);
|
||||
|
||||
return (bool)$test;
|
||||
}
|
||||
|
||||
ob_start();
|
@@ -1,9 +0,0 @@
|
||||
|
||||
/* block comments get removed */
|
||||
|
||||
/*! YUI Compressor style comments are preserved */
|
||||
|
||||
/* but all other comments are removed */
|
||||
|
||||
/* comments that have any surrounding whitespace are replaced by a single space. */
|
||||
body{ background:#fff/*eef*/ url(/path/to/image.gif) repeat-y; }
|
@@ -1,3 +0,0 @@
|
||||
|
||||
/* YUI Compressor style comments are preserved */
|
||||
body{background:#fff url(/path/to/image.gif) repeat-y}
|
@@ -1,66 +0,0 @@
|
||||
/* hide from ie5/mac \*/ a{}
|
||||
.foo {color:red}
|
||||
/* necessary comment */
|
||||
|
||||
/* comment to attempt to confuse parser */
|
||||
|
||||
/* feed to ie5/mac \*//*/
|
||||
@import "ie5mac.css";
|
||||
/* necessary comment */
|
||||
|
||||
/* comment to attempt to confuse parser */
|
||||
|
||||
/*/ hide from nav4 */
|
||||
.foo {display:block;}
|
||||
/* necessary comment */
|
||||
|
||||
/* comment to attempt to confuse parser */
|
||||
|
||||
/*/ feed to nav *//*/
|
||||
.foo {display:crazy;}
|
||||
/* necessary comment */
|
||||
|
||||
/* hide props from various IE/win */
|
||||
div {
|
||||
width: 140px;
|
||||
width/* */:/**/100px;
|
||||
width: /**/100px;
|
||||
}
|
||||
|
||||
html>/**/body {}
|
||||
|
||||
/* Tantek's box model hack */
|
||||
div {
|
||||
width:400px;
|
||||
voice-family: "\"}\"";
|
||||
voice-family:inherit;
|
||||
width:300px;
|
||||
}
|
||||
|
||||
/* don't minimize hex colors in filters */
|
||||
div {
|
||||
filter:chroma(color=#aabbcc);
|
||||
filter:mask(color=#000000) shadow(color=#9BAD71, direction=135) chroma(color=#000000);
|
||||
}
|
||||
|
||||
@media screen {
|
||||
/* for IE 5.x-6, hidden from IE 5 Mac */ /*\*/
|
||||
* html div#page {
|
||||
height: 1%;
|
||||
}
|
||||
/**/ /* end hidden from IE 5 Mac */
|
||||
}
|
||||
|
||||
foo { /* filters for IE */
|
||||
_height : 20px;
|
||||
*height : 15px;
|
||||
}
|
||||
|
||||
/* http://tantek.com/CSS/Examples/midpass.html */
|
||||
@media tty {
|
||||
i{content:"\";/*" "*/}} @import 'midpassafter.css'; /*";}
|
||||
}/* */
|
||||
|
||||
/* leave at least 1 space between these pseudo elements and "{" for IE6: http://www.crankygeek.com/ie6pebug/ */
|
||||
p:first-letter {color:red;}
|
||||
p:first-line {color:red;}
|
4
min_unit_tests/_test_files/css/hacks.min.css
vendored
4
min_unit_tests/_test_files/css/hacks.min.css
vendored
@@ -1,4 +0,0 @@
|
||||
/*\*/a{}.foo{color:red}/**/ /*\*//*/@import "ie5mac.css";/**/ /*/*/.foo{display:block}/**/ /*/*//*/.foo{display:crazy}/**/ div{width:140px;width/**/:/**/100px;width:/**/100px}html>/**/body{}div{width:400px;voice-family:"\"}\"";voice-family:inherit;width:300px}div{filter:chroma(color=#aabbcc);filter:mask(color=#000000) shadow(color=#9BAD71, direction=135) chroma(color=#000000)}@media
|
||||
screen{/*\*/* html
|
||||
div#page{height:1%}/**/}foo{_height:20px;*height:15px}@media
|
||||
tty{i{content:"\";/*" "*/}}@import 'midpassafter.css';/*"}}/* */ p:first-letter {color:red}p:first-line {color:red}
|
@@ -1,890 +0,0 @@
|
||||
/*
|
||||
* DEFINITION DES STYLES DE TEXTE
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
h1 {
|
||||
color: #339933;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #339933;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5 {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.txt_10_noir {
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_10_noir:link,.txt_10_noir:visited,.txt_10_noir:active {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.txt_10_noir:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_11_noir {
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_11_noir:link,.txt_11_noir:visited,.txt_11_noir:active {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.txt_11_noir:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_12_noir {
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_12_noir:link,.txt_12_noir:visited,.txt_12_noir:active {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.txt_12_noir:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_14_noir {
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_14_noir:link,.txt_14_noir:visited,.txt_14_noir:active {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.txt_14_noir:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
.txt_10_gris {
|
||||
color: grey;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_10_gris:link,.txt_10_gris:visited,.txt_10_gris:active {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.txt_10_gris:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_11_gris {
|
||||
color: grey;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_11_gris:link,.txt_11_gris:visited,.txt_11_gris:active {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.txt_11_gris:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_12_gris {
|
||||
color: grey;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_12_gris:link,.txt_12_gris:visited,.txt_12_gris:active {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.txt_12_gris:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_14_gris {
|
||||
color: grey;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_14_gris:link,.txt_14_gris:visited,.txt_14_gris:active {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.txt_14_gris:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
.txt_10_blanc {
|
||||
color: #FFFFFF;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_10_blanc:link,.txt_10_blanc:visited,.txt_10_blanc:active {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.txt_10_blanc:hover {
|
||||
color: #FF8800; /*ORANGE*/
|
||||
}
|
||||
|
||||
.txt_11_blanc {
|
||||
color: #FFFFFF;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_11_blanc:link,.txt_11_blanc:visited,.txt_11_blanc:active {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.txt_11_blanc:hover {
|
||||
color: #FF8800;
|
||||
}
|
||||
|
||||
.txt_12_blanc {
|
||||
color: #FFFFFF;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_12_blanc:link,.txt_12_blanc:visited,.txt_12_blanc:active {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.txt_12_blanc:hover {
|
||||
color: #FFAA00;
|
||||
}
|
||||
|
||||
.txt_14_blanc {
|
||||
color: #FFFFFF;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_14_blanc:link,.txt_14_blanc:visited,.txt_14_blanc:active {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.txt_14_blanc:hover {
|
||||
color: #FF8800;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
.txt_10_orange {
|
||||
color: #FF8800;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_10_orange:link,.txt_10_orange:visited,.txt_10_orange:active {
|
||||
color: #FF8800;
|
||||
}
|
||||
|
||||
.txt_10_orange:hover {
|
||||
color: darkblue
|
||||
}
|
||||
|
||||
.txt_11_orange {
|
||||
color: #FF8800;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_11_orange:link,.txt_11_orange:visited,.txt_11_orange:active {
|
||||
color: #FF8800;
|
||||
}
|
||||
|
||||
.txt_11_orange:hover {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
.txt_12_orange {
|
||||
color: #FF8800;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_12_orange:link,.txt_12_orange:visited,.txt_12_orange:active {
|
||||
color: #FF8800;
|
||||
}
|
||||
|
||||
.txt_12_orange:hover {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
.txt_14_orange {
|
||||
color: #FF8800;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_14_orange:link,.txt_14_orange:visited,.txt_14_orange:active {
|
||||
color: #FF8800;
|
||||
}
|
||||
|
||||
.txt_14_orange:hover {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
.txt_10_rouge {
|
||||
color: red;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_10_rouge:link,.txt_10_rouge:visited,.txt_10_rouge:active {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_10_rouge:hover {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
.txt_11_rouge {
|
||||
color: red;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_11_rouge:link,.txt_11_rouge:visited,.txt_11_rouge:active {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_11_rouge:hover {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
.txt_12_rouge {
|
||||
color: red;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_12_rouge:link,.txt_12_rouge:visited,.txt_12_rouge:active {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_12_rouge:hover {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
.txt_14_rouge {
|
||||
color: red;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_14_rouge:link,.txt_14_rouge:visited,.txt_14_rouge:active {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_14_rouge:hover {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
.txt_10_bleu {
|
||||
color: blue;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_10_bleu:link,.txt_10_bleu:visited,.txt_10_bleu:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.txt_10_bleu:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_11_bleu {
|
||||
color: blue;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_11_bleu:link,.txt_11_bleu:visited,.txt_11_bleu:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.txt_11_bleu:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_12_bleu {
|
||||
color: blue;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_12_bleu:link,.txt_12_bleu:visited,.txt_12_bleu:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.txt_12_bleu:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_14_bleu {
|
||||
color: blue;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_14_bleu:link,.txt_14_bleu:visited,.txt_14_bleu:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.txt_14_bleu:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
.txt_10_bleu_f {
|
||||
color: darkblue;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_10_bleu_f:link,.txt_10_bleu_f:visited,.txt_10_bleu_f:active {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
.txt_10_bleu_f:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_11_bleu_f {
|
||||
color: darkblue;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_11_bleu_f:link,.txt_11_bleu_f:visited,.txt_11_bleu_f:active {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
.txt_11_bleu_f:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_12_bleu_f {
|
||||
color: darkblue;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_12_bleu_f:link,.txt_12_bleu_f:visited,.txt_12_bleu_f:active {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
.txt_12_bleu_f:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_14_bleu_f {
|
||||
color: darkblue;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_14_bleu_f:link,.txt_14_bleu_f:visited,.txt_14_bleu_f:active {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
.txt_14_bleu_f:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
.txt_10_vert_f {
|
||||
color: darkgreen;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_10_vert_f:link,.txt_10_vert_f:visited,.txt_10_vert_f:active {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
.txt_10_vert_f:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_11_vert_f {
|
||||
color: darkgreen;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_11_vert_f:link,.txt_11_vert_f:visited,.txt_11_vert_f:active {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
.txt_11_vert_f:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_12_vert_f {
|
||||
color: darkgreen;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_12_vert_f:link,.txt_12_vertf:visited,.txt_12_vert_f:active {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
.txt_12_vert_f:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_14_vert_f {
|
||||
color: darkgreen;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_14_vert_f:link,.txt_14_vert_f:visited,.txt_14_vert_f:active {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
.txt_14_vert_f:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
.txt_10_vert {
|
||||
color: green;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_10_vert:link,.txt_10_vert:visited,.txt_10_vert:active {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.txt_10_vert:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_11_vert {
|
||||
color: green;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_11_vert:link,.txt_11_vert:visited,.txt_11_vert:active {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.txt_11_vert:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_12_vert {
|
||||
color: green;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_12_vert:link,.txt_12_vert:visited,.txt_12_vert:active {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.txt_12_vert:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.txt_14_vert {
|
||||
color: green;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.txt_14_vert:link,.txt_14_vert:visited,.txt_14_vert:active {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.txt_14_vert:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
.fond_blanc {
|
||||
background-color: #FFFFFF;
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.fond_gris_c, .fond_gris_c tr {
|
||||
background-color: #FFFFFF;
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
background-image: url(../images/fond_4.bmp);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.fond_gris_c2, .fond_gris_c2 tr {
|
||||
background-color: #FBFBFB;
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.fond_bleu_c, .fond_bleu_c tr {
|
||||
background-color: #D9EEF9;
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
background-image: url(../images/fond_1.bmp);
|
||||
}
|
||||
|
||||
.fond_bleu_c2 {
|
||||
background-color: #ECF4FF;
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.fond_bleu_f {
|
||||
background-color: #003366;
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.fond_orange {
|
||||
background-color: #FEEFE7;
|
||||
color: darkgreen;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
background-image: url(../images/fond_3.jpg);
|
||||
}
|
||||
|
||||
.fond_orange_2 {
|
||||
background-color: #FFF8F4;
|
||||
color: darkgreen;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
border: 1px solid orange;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.vccDlgBody {
|
||||
border: 3px solid #336699;
|
||||
border-collapse: collapse;
|
||||
color: black;
|
||||
background-color: #EEFFEE;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* DEFINITION DES STYLES DE TABLEAUX */
|
||||
.bordure_0 {
|
||||
border: 0px solid;
|
||||
color: black;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.bordure_1_bleu {
|
||||
border: 1px solid green;
|
||||
border-collapse: collapse;
|
||||
color: black;
|
||||
background-color: #FFFFFF;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.bordure_3_bleu {
|
||||
border: 3px solid #336699;
|
||||
border-collapse: collapse;
|
||||
color: black;
|
||||
background-color: #FFFFFF;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.indent {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
/* DEFINITION DES STYLES D'OBJETS DE FORMULAIRE */
|
||||
.Btn {
|
||||
color: #003366;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
background-color: #FFFFFF;
|
||||
background-image: url(../images/ongletStyle1.jpg);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.Btn:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.menu1h {
|
||||
background-color: #003366;
|
||||
color: white;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
border-top: 1px solid #003366;
|
||||
border-bottom: 1px solid #003366;
|
||||
border-left: 1px solid #003366;
|
||||
border-right: 1px solid white;
|
||||
border-collapse: collapse;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu1h:hover {
|
||||
background-color: white;
|
||||
color: red;
|
||||
border: 1px solid darkgreen;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.menu1h_f {
|
||||
background-color: #003366;
|
||||
color: white;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
border: 1px solid #003366;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu1h_f:hover {
|
||||
background-color: white;
|
||||
color: red;
|
||||
border: 1px solid darkgreen;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.menu1v {
|
||||
background-color: #003366;
|
||||
color: white;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
border: 1px solid #003366;
|
||||
border-collapse: collapse;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu1v:hover {
|
||||
background-color: white;
|
||||
color: red;
|
||||
border: 1px solid darkgreen;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.menu2v {
|
||||
background-color: #5588BB;
|
||||
color: white;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
border: 1px solid #4277AB;
|
||||
border-collapse: collapse;
|
||||
float: left;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu2v:hover {
|
||||
background-color: white;
|
||||
color: red;
|
||||
border: 1px solid darkgreen;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.menuEDF {
|
||||
background-color: #003366;
|
||||
color: white;
|
||||
font-family: Verdana, Arial, Lucida, Tahoma;
|
||||
font-size: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.menuEDF:hover {
|
||||
color: #FF8800;
|
||||
}
|
||||
|
||||
/*bouton bleu sur blanc*/
|
||||
.Bouton {
|
||||
color: #003366;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
/* Ricardo cursor: hand; */
|
||||
cursor: pointer;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
input {
|
||||
border: 2px solid green;
|
||||
color: #003366;
|
||||
background-color: #FFFFFF;
|
||||
background-image: url(../images/fond_4.bmp);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.disabled_input {
|
||||
border: 1px solid gray;
|
||||
color: grey;
|
||||
background-color: #FFFFFF;
|
||||
background-image: url(../images/fond_4.bmp);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.input0 {
|
||||
border: 0px;
|
||||
color: #003366;
|
||||
background-color: #FFFFFF;
|
||||
background-image: url(../images/fond_4.bmp);
|
||||
}
|
||||
|
||||
.input2 {
|
||||
border: 1px solid green;
|
||||
color: #003366;
|
||||
background-color: #FFFFFF;
|
||||
background-image: url(../images/fond_4.bmp);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.input3 {
|
||||
border: 1px solid black;
|
||||
color: #003366;
|
||||
background-color: #EEEEEE;
|
||||
background-image: url();
|
||||
}
|
||||
|
||||
.input4 {
|
||||
border: 1px solid blue;
|
||||
color: #003366;
|
||||
background-color: #FFFFFF;
|
||||
background-image: url(../images/fond_4.bmp);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.input5 {
|
||||
border: 1px solid darkblue;
|
||||
color: #003366;
|
||||
background-color: #FFFFFF;
|
||||
background-image: url(../images/fond_4.bmp);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.input_btn {
|
||||
border: 0px;
|
||||
/* cursor: hand; */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
textarea {
|
||||
border: 2px solid green;
|
||||
color: #003366;
|
||||
background-color: #FFFFFF;
|
||||
background-image: url(../images/fond_5.bmp);
|
||||
}
|
||||
|
||||
.TEXTAREA3 {
|
||||
border: 1px solid green;
|
||||
color: #003366;
|
||||
background-color: #FFFFFF;
|
||||
background-image: url();
|
||||
}
|
||||
|
||||
.TEXTAREA4 {
|
||||
border: 1px solid green;
|
||||
color: #003366;
|
||||
background-color: #EEEEEE;
|
||||
background-image: url();
|
||||
}
|
||||
|
||||
.hand {
|
||||
cursor: hand;
|
||||
cursor: pointer;
|
||||
}
|
25
min_unit_tests/_test_files/css/issue62.min.css
vendored
25
min_unit_tests/_test_files/css/issue62.min.css
vendored
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user