Version Notes
reupload of 1.0.1
Download this release
Release Info
Developer | Magento Core Team |
Extension | Fooman_Speedster |
Version | 1.0.2 |
Comparing to | |
See all releases |
Code changes from version 1.0.1 to 1.0.2
- app/code/community/Fooman/Speedster/etc/config.xml +1 -1
- lib/minify/HISTORY.txt +12 -0
- lib/minify/README.txt +6 -0
- lib/minify/lib/HTTP/ConditionalGet.php +57 -11
- lib/minify/lib/HTTP/Encoder.php +29 -0
- lib/minify/lib/Minify.php +51 -3
- lib/minify/lib/Minify/CSS/Compressor.php +4 -1
- lib/minify/lib/Minify/CSS/UriRewriter.php +144 -65
- lib/minify/lib/Minify/Controller/Base.php +1 -0
- lib/minify/lib/Minify/HTML.php +100 -77
- lib/minify/lib/Minify/Lines.php +26 -3
- lib/minify/lib/MyMin.php +0 -289
- package.xml +6 -6
- var/minifycache/cache.txt +4 -0
app/code/community/Fooman/Speedster/etc/config.xml
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<config>
|
3 |
<modules>
|
4 |
<Fooman_Speedster>
|
5 |
-
<version>1.0.
|
6 |
<depends>
|
7 |
<Mage_Page />
|
8 |
<Mage_Adminhtml />
|
2 |
<config>
|
3 |
<modules>
|
4 |
<Fooman_Speedster>
|
5 |
+
<version>1.0.2</version>
|
6 |
<depends>
|
7 |
<Mage_Page />
|
8 |
<Mage_Adminhtml />
|
lib/minify/HISTORY.txt
CHANGED
@@ -1,5 +1,17 @@
|
|
1 |
Minify Release History
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
Version 2.1.1
|
4 |
* Bug fix release
|
5 |
* Detection and workarounds for zlib.output_compression and non-PHP encoding modules
|
1 |
Minify Release History
|
2 |
|
3 |
+
Version 2.1.2
|
4 |
+
* Javascript fixes
|
5 |
+
* Debug mode no longer confused by "*/*" in strings/RegExps (jQuery)
|
6 |
+
* quote characters inside RegExp literals no longer cause exception
|
7 |
+
* files ending in single-line comments no longer cause code loss
|
8 |
+
* CSS: data: URLs no longer mangled
|
9 |
+
* Optional error logging to Firefox's FirePHP extension
|
10 |
+
* Unit tests to check for common DOCUMENT_ROOT problems
|
11 |
+
* DOCUMENT_ROOT no longer overwritten on IIS servers
|
12 |
+
* Builder app doesn't fail on systems without gzdeflate()
|
13 |
+
* APC caching class included
|
14 |
+
|
15 |
Version 2.1.1
|
16 |
* Bug fix release
|
17 |
* Detection and workarounds for zlib.output_compression and non-PHP encoding modules
|
lib/minify/README.txt
CHANGED
@@ -7,6 +7,12 @@ GETs (serving content only when clients do not have a valid cache)
|
|
7 |
and tell clients to cache the file for a period of time.
|
8 |
More info: http://code.google.com/p/minify/
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
INSTALLATION AND USAGE:
|
11 |
|
12 |
1. Place the /min/ directory as a child of your DOCUMENT_ROOT
|
7 |
and tell clients to cache the file for a period of time.
|
8 |
More info: http://code.google.com/p/minify/
|
9 |
|
10 |
+
|
11 |
+
UPGRADING
|
12 |
+
|
13 |
+
See UPGRADING.txt for instructions.
|
14 |
+
|
15 |
+
|
16 |
INSTALLATION AND USAGE:
|
17 |
|
18 |
1. Place the /min/ directory as a child of your DOCUMENT_ROOT
|
lib/minify/lib/HTTP/ConditionalGet.php
CHANGED
@@ -13,6 +13,7 @@
|
|
13 |
* list($updateTime, $content) = getDbUpdateAndContent();
|
14 |
* $cg = new HTTP_ConditionalGet(array(
|
15 |
* 'lastModifiedTime' => $updateTime
|
|
|
16 |
* ));
|
17 |
* $cg->sendHeaders();
|
18 |
* if ($cg->cacheIsValid) {
|
@@ -20,6 +21,12 @@
|
|
20 |
* }
|
21 |
* echo $content;
|
22 |
* </code>
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
*
|
24 |
* E.g. Content from DB with no update time:
|
25 |
* <code>
|
@@ -69,8 +76,8 @@ class HTTP_ConditionalGet {
|
|
69 |
* @param array $spec options
|
70 |
*
|
71 |
* 'isPublic': (bool) if true, the Cache-Control header will contain
|
72 |
-
* "public", allowing
|
73 |
-
*
|
74 |
*
|
75 |
* 'lastModifiedTime': (int) if given, both ETag AND Last-Modified headers
|
76 |
* will be sent with content. This is recommended.
|
@@ -95,7 +102,8 @@ class HTTP_ConditionalGet {
|
|
95 |
*
|
96 |
* @return null
|
97 |
*/
|
98 |
-
public function __construct($spec)
|
|
|
99 |
$scope = (isset($spec['isPublic']) && $spec['isPublic'])
|
100 |
? 'public'
|
101 |
: 'private';
|
@@ -147,7 +155,8 @@ class HTTP_ConditionalGet {
|
|
147 |
*
|
148 |
* @return array
|
149 |
*/
|
150 |
-
public function getHeaders()
|
|
|
151 |
return $this->_headers;
|
152 |
}
|
153 |
|
@@ -162,7 +171,8 @@ class HTTP_ConditionalGet {
|
|
162 |
*
|
163 |
* @return int copy of input $bytes
|
164 |
*/
|
165 |
-
public function setContentLength($bytes)
|
|
|
166 |
return $this->_headers['Content-Length'] = $bytes;
|
167 |
}
|
168 |
|
@@ -177,7 +187,8 @@ class HTTP_ConditionalGet {
|
|
177 |
*
|
178 |
* @return null
|
179 |
*/
|
180 |
-
public function sendHeaders()
|
|
|
181 |
$headers = $this->_headers;
|
182 |
if (array_key_exists('_responseCode', $headers)) {
|
183 |
header($headers['_responseCode']);
|
@@ -188,6 +199,36 @@ class HTTP_ConditionalGet {
|
|
188 |
}
|
189 |
}
|
190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
/**
|
192 |
* Get a GMT formatted date for use in HTTP headers
|
193 |
*
|
@@ -199,7 +240,8 @@ class HTTP_ConditionalGet {
|
|
199 |
*
|
200 |
* @return string
|
201 |
*/
|
202 |
-
public static function gmtDate($time)
|
|
|
203 |
return gmdate('D, d M Y H:i:s \G\M\T', $time);
|
204 |
}
|
205 |
|
@@ -207,14 +249,16 @@ class HTTP_ConditionalGet {
|
|
207 |
protected $_lmTime = null;
|
208 |
protected $_etag = null;
|
209 |
|
210 |
-
protected function _setEtag($hash, $scope)
|
|
|
211 |
$this->_etag = '"' . $hash
|
212 |
. substr($scope, 0, 3)
|
213 |
. '"';
|
214 |
$this->_headers['ETag'] = $this->_etag;
|
215 |
}
|
216 |
|
217 |
-
protected function _setLastModified($time)
|
|
|
218 |
$this->_lmTime = (int)$time;
|
219 |
$this->_headers['Last-Modified'] = self::gmtDate($time);
|
220 |
}
|
@@ -237,7 +281,8 @@ class HTTP_ConditionalGet {
|
|
237 |
return $isValid;
|
238 |
}
|
239 |
|
240 |
-
protected function resourceMatchedEtag()
|
|
|
241 |
if (!isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
|
242 |
return false;
|
243 |
}
|
@@ -253,7 +298,8 @@ class HTTP_ConditionalGet {
|
|
253 |
return false;
|
254 |
}
|
255 |
|
256 |
-
protected function resourceNotModified()
|
|
|
257 |
if (!isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
258 |
return false;
|
259 |
}
|
13 |
* list($updateTime, $content) = getDbUpdateAndContent();
|
14 |
* $cg = new HTTP_ConditionalGet(array(
|
15 |
* 'lastModifiedTime' => $updateTime
|
16 |
+
* ,'isPublic' => true
|
17 |
* ));
|
18 |
* $cg->sendHeaders();
|
19 |
* if ($cg->cacheIsValid) {
|
21 |
* }
|
22 |
* echo $content;
|
23 |
* </code>
|
24 |
+
*
|
25 |
+
* E.g. Shortcut for the above
|
26 |
+
* <code>
|
27 |
+
* HTTP_ConditionalGet::check($updateTime, true); // exits if client has cache
|
28 |
+
* echo $content;
|
29 |
+
* </code>
|
30 |
*
|
31 |
* E.g. Content from DB with no update time:
|
32 |
* <code>
|
76 |
* @param array $spec options
|
77 |
*
|
78 |
* 'isPublic': (bool) if true, the Cache-Control header will contain
|
79 |
+
* "public", allowing proxies to cache the content. Otherwise "private" will
|
80 |
+
* be sent, allowing only browser caching. (default false)
|
81 |
*
|
82 |
* 'lastModifiedTime': (int) if given, both ETag AND Last-Modified headers
|
83 |
* will be sent with content. This is recommended.
|
102 |
*
|
103 |
* @return null
|
104 |
*/
|
105 |
+
public function __construct($spec)
|
106 |
+
{
|
107 |
$scope = (isset($spec['isPublic']) && $spec['isPublic'])
|
108 |
? 'public'
|
109 |
: 'private';
|
155 |
*
|
156 |
* @return array
|
157 |
*/
|
158 |
+
public function getHeaders()
|
159 |
+
{
|
160 |
return $this->_headers;
|
161 |
}
|
162 |
|
171 |
*
|
172 |
* @return int copy of input $bytes
|
173 |
*/
|
174 |
+
public function setContentLength($bytes)
|
175 |
+
{
|
176 |
return $this->_headers['Content-Length'] = $bytes;
|
177 |
}
|
178 |
|
187 |
*
|
188 |
* @return null
|
189 |
*/
|
190 |
+
public function sendHeaders()
|
191 |
+
{
|
192 |
$headers = $this->_headers;
|
193 |
if (array_key_exists('_responseCode', $headers)) {
|
194 |
header($headers['_responseCode']);
|
199 |
}
|
200 |
}
|
201 |
|
202 |
+
/**
|
203 |
+
* Exit if the client's cache is valid for this resource
|
204 |
+
*
|
205 |
+
* This is a convenience method for common use of the class
|
206 |
+
*
|
207 |
+
* @param int $lastModifiedTime if given, both ETag AND Last-Modified headers
|
208 |
+
* will be sent with content. This is recommended.
|
209 |
+
*
|
210 |
+
* @param bool $isPublic (default false) if true, the Cache-Control header
|
211 |
+
* will contain "public", allowing proxies to cache the content. Otherwise
|
212 |
+
* "private" will be sent, allowing only browser caching.
|
213 |
+
*
|
214 |
+
* @param array $options (default empty) additional options for constructor
|
215 |
+
*
|
216 |
+
* @return null
|
217 |
+
*/
|
218 |
+
public static function check($lastModifiedTime = null, $isPublic = false, $options = array())
|
219 |
+
{
|
220 |
+
if (null !== $lastModifiedTime) {
|
221 |
+
$options['lastModifiedTime'] = (int)$lastModifiedTime;
|
222 |
+
}
|
223 |
+
$options['isPublic'] = (bool)$isPublic;
|
224 |
+
$cg = new HTTP_ConditionalGet($options);
|
225 |
+
$cg->sendHeaders();
|
226 |
+
if ($cg->cacheIsValid) {
|
227 |
+
exit();
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
|
232 |
/**
|
233 |
* Get a GMT formatted date for use in HTTP headers
|
234 |
*
|
240 |
*
|
241 |
* @return string
|
242 |
*/
|
243 |
+
public static function gmtDate($time)
|
244 |
+
{
|
245 |
return gmdate('D, d M Y H:i:s \G\M\T', $time);
|
246 |
}
|
247 |
|
249 |
protected $_lmTime = null;
|
250 |
protected $_etag = null;
|
251 |
|
252 |
+
protected function _setEtag($hash, $scope)
|
253 |
+
{
|
254 |
$this->_etag = '"' . $hash
|
255 |
. substr($scope, 0, 3)
|
256 |
. '"';
|
257 |
$this->_headers['ETag'] = $this->_etag;
|
258 |
}
|
259 |
|
260 |
+
protected function _setLastModified($time)
|
261 |
+
{
|
262 |
$this->_lmTime = (int)$time;
|
263 |
$this->_headers['Last-Modified'] = self::gmtDate($time);
|
264 |
}
|
281 |
return $isValid;
|
282 |
}
|
283 |
|
284 |
+
protected function resourceMatchedEtag()
|
285 |
+
{
|
286 |
if (!isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
|
287 |
return false;
|
288 |
}
|
298 |
return false;
|
299 |
}
|
300 |
|
301 |
+
protected function resourceNotModified()
|
302 |
+
{
|
303 |
if (!isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
304 |
return false;
|
305 |
}
|
lib/minify/lib/HTTP/Encoder.php
CHANGED
@@ -19,6 +19,12 @@
|
|
19 |
* </code>
|
20 |
*
|
21 |
* <code>
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
* // Just sniff for the accepted encoding
|
23 |
* $encoding = HTTP_Encoder::getAcceptedEncoding();
|
24 |
* </code>
|
@@ -257,6 +263,29 @@ class HTTP_Encoder {
|
|
257 |
$this->_headers['Vary'] = 'Accept-Encoding';
|
258 |
$this->_content = $encoded;
|
259 |
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
260 |
}
|
261 |
|
262 |
protected $_content = '';
|
19 |
* </code>
|
20 |
*
|
21 |
* <code>
|
22 |
+
* // Shortcut to encoding output
|
23 |
+
* header('Content-Type: text/css'); // needed if not HTML
|
24 |
+
* HTTP_Encoder::output($css);
|
25 |
+
* </code>
|
26 |
+
*
|
27 |
+
* <code>
|
28 |
* // Just sniff for the accepted encoding
|
29 |
* $encoding = HTTP_Encoder::getAcceptedEncoding();
|
30 |
* </code>
|
263 |
$this->_headers['Vary'] = 'Accept-Encoding';
|
264 |
$this->_content = $encoded;
|
265 |
return true;
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Encode and send appropriate headers and content
|
270 |
+
*
|
271 |
+
* This is a convenience method for common use of the class
|
272 |
+
*
|
273 |
+
* @param string $content
|
274 |
+
*
|
275 |
+
* @param int $compressionLevel given to zlib functions. If not given, the
|
276 |
+
* class default will be used.
|
277 |
+
*
|
278 |
+
* @return bool success true if the content was actually compressed
|
279 |
+
*/
|
280 |
+
public static function output($content, $compressionLevel = null)
|
281 |
+
{
|
282 |
+
if (null === $compressionLevel) {
|
283 |
+
$compressionLevel = self::$compressionLevel;
|
284 |
+
}
|
285 |
+
$he = new HTTP_Encoder(array('content' => $content));
|
286 |
+
$ret = $he->encode($compressionLevel);
|
287 |
+
$he->sendAll();
|
288 |
+
return $ret;
|
289 |
}
|
290 |
|
291 |
protected $_content = '';
|
lib/minify/lib/Minify.php
CHANGED
@@ -48,6 +48,16 @@ class Minify {
|
|
48 |
*/
|
49 |
public static $uploaderHoursBehind = 0;
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
/**
|
52 |
* Specify a cache object (with identical interface as Minify_Cache_File) or
|
53 |
* a path to use with Minify_Cache_File.
|
@@ -103,6 +113,10 @@ class Minify {
|
|
103 |
* 'rewriteCssUris' : If true, serve() will automatically set the 'currentDir'
|
104 |
* minifier option to enable URI rewriting in CSS files (default true)
|
105 |
*
|
|
|
|
|
|
|
|
|
106 |
* 'debug' : set to true to minify all sources with the 'Lines' controller, which
|
107 |
* eases the debugging of combined files. This also prevents 304 responses.
|
108 |
* @see Minify_Lines::minify()
|
@@ -321,18 +335,22 @@ class Minify {
|
|
321 |
*
|
322 |
* @param array $sources array of filepaths and/or Minify_Source objects
|
323 |
*
|
|
|
|
|
|
|
324 |
* @return string
|
325 |
*/
|
326 |
-
public static function combine($sources)
|
327 |
{
|
328 |
$cache = self::$_cache;
|
329 |
self::$_cache = null;
|
330 |
-
$
|
331 |
'files' => (array)$sources
|
332 |
,'quiet' => true
|
333 |
,'encodeMethod' => ''
|
334 |
,'lastModifiedTime' => 0
|
335 |
-
));
|
|
|
336 |
self::$_cache = $cache;
|
337 |
return $out['content'];
|
338 |
}
|
@@ -453,6 +471,10 @@ class Minify {
|
|
453 |
$content = implode($implodeSeparator, $pieces);
|
454 |
}
|
455 |
|
|
|
|
|
|
|
|
|
456 |
// do any post-processing (esp. for editing build URIs)
|
457 |
if (self::$_options['postprocessorRequire']) {
|
458 |
require_once self::$_options['postprocessorRequire'];
|
@@ -476,6 +498,32 @@ class Minify {
|
|
476 |
,self::$_options['minifiers']
|
477 |
,self::$_options['minifierOptions']
|
478 |
,self::$_options['postprocessor']
|
|
|
479 |
)));
|
480 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
481 |
}
|
48 |
*/
|
49 |
public static $uploaderHoursBehind = 0;
|
50 |
|
51 |
+
/**
|
52 |
+
* If this string is not empty AND the serve() option 'bubbleCssImports' is
|
53 |
+
* NOT set, then serve() will check CSS files for @import declarations that
|
54 |
+
* appear too late in the combined stylesheet. If found, serve() will prepend
|
55 |
+
* the output with this warning.
|
56 |
+
*
|
57 |
+
* @var string $importWarning
|
58 |
+
*/
|
59 |
+
public static $importWarning = "/* See http://code.google.com/p/minify/wiki/CommonProblems#@imports_can_appear_in_invalid_locations_in_combined_CSS_files */\n";
|
60 |
+
|
61 |
/**
|
62 |
* Specify a cache object (with identical interface as Minify_Cache_File) or
|
63 |
* a path to use with Minify_Cache_File.
|
113 |
* 'rewriteCssUris' : If true, serve() will automatically set the 'currentDir'
|
114 |
* minifier option to enable URI rewriting in CSS files (default true)
|
115 |
*
|
116 |
+
* 'bubbleCssImports' : If true, all @import declarations in combined CSS
|
117 |
+
* files will be move to the top. Note this may alter effective CSS values
|
118 |
+
* due to a change in order. (default false)
|
119 |
+
*
|
120 |
* 'debug' : set to true to minify all sources with the 'Lines' controller, which
|
121 |
* eases the debugging of combined files. This also prevents 304 responses.
|
122 |
* @see Minify_Lines::minify()
|
335 |
*
|
336 |
* @param array $sources array of filepaths and/or Minify_Source objects
|
337 |
*
|
338 |
+
* @param array $options (optional) array of options for serve. By default
|
339 |
+
* these are already set: quiet = true, encodeMethod = '', lastModifiedTime = 0.
|
340 |
+
*
|
341 |
* @return string
|
342 |
*/
|
343 |
+
public static function combine($sources, $options = array())
|
344 |
{
|
345 |
$cache = self::$_cache;
|
346 |
self::$_cache = null;
|
347 |
+
$options = array_merge(array(
|
348 |
'files' => (array)$sources
|
349 |
,'quiet' => true
|
350 |
,'encodeMethod' => ''
|
351 |
,'lastModifiedTime' => 0
|
352 |
+
), $options);
|
353 |
+
$out = self::serve('Files', $options);
|
354 |
self::$_cache = $cache;
|
355 |
return $out['content'];
|
356 |
}
|
471 |
$content = implode($implodeSeparator, $pieces);
|
472 |
}
|
473 |
|
474 |
+
if ($type === self::TYPE_CSS && false !== strpos($content, '@import')) {
|
475 |
+
$content = self::_handleCssImports($content);
|
476 |
+
}
|
477 |
+
|
478 |
// do any post-processing (esp. for editing build URIs)
|
479 |
if (self::$_options['postprocessorRequire']) {
|
480 |
require_once self::$_options['postprocessorRequire'];
|
498 |
,self::$_options['minifiers']
|
499 |
,self::$_options['minifierOptions']
|
500 |
,self::$_options['postprocessor']
|
501 |
+
,self::$_options['bubbleCssImports']
|
502 |
)));
|
503 |
}
|
504 |
+
|
505 |
+
/**
|
506 |
+
* Bubble CSS @imports to the top or prepend a warning if an
|
507 |
+
* @import is detected not at the top.
|
508 |
+
*/
|
509 |
+
protected static function _handleCssImports($css) {
|
510 |
+
if (self::$_options['bubbleCssImports']) {
|
511 |
+
// bubble CSS imports
|
512 |
+
preg_match_all('/@import.*?;/', $css, $imports);
|
513 |
+
$css = implode('', $imports[0]) . preg_replace('/@import.*?;/', '', $css);
|
514 |
+
} else if ('' !== self::$importWarning) {
|
515 |
+
// remove comments so we don't mistake { in a comment as a block
|
516 |
+
$noCommentCss = preg_replace('@/\\*[\\s\\S]*?\\*/@', '', $css);
|
517 |
+
$lastImportPos = strrpos($noCommentCss, '@import');
|
518 |
+
$firstBlockPos = strpos($noCommentCss, '{');
|
519 |
+
if (false !== $lastImportPos
|
520 |
+
&& false !== $firstBlockPos
|
521 |
+
&& $firstBlockPos < $lastImportPos
|
522 |
+
) {
|
523 |
+
// { appears before @import : prepend warning
|
524 |
+
$css = self::$importWarning . $css;
|
525 |
+
}
|
526 |
+
}
|
527 |
+
return $css;
|
528 |
+
}
|
529 |
}
|
lib/minify/lib/Minify/CSS/Compressor.php
CHANGED
@@ -147,7 +147,10 @@ class Minify_CSS_Compressor {
|
|
147 |
\\s+
|
148 |
/x'
|
149 |
,"$1\n", $css);
|
150 |
-
|
|
|
|
|
|
|
151 |
return trim($css);
|
152 |
}
|
153 |
|
147 |
\\s+
|
148 |
/x'
|
149 |
,"$1\n", $css);
|
150 |
+
|
151 |
+
// prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
|
152 |
+
$css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css);
|
153 |
+
|
154 |
return trim($css);
|
155 |
}
|
156 |
|
lib/minify/lib/Minify/CSS/UriRewriter.php
CHANGED
@@ -19,6 +19,12 @@ class Minify_CSS_UriRewriter {
|
|
19 |
*/
|
20 |
protected static $className = 'Minify_CSS_UriRewriter';
|
21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
/**
|
23 |
* Rewrite file relative URIs as root relative in CSS files
|
24 |
*
|
@@ -43,30 +49,35 @@ class Minify_CSS_UriRewriter {
|
|
43 |
*/
|
44 |
public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = array())
|
45 |
{
|
46 |
-
self::$_docRoot =
|
47 |
-
? $docRoot
|
48 |
-
|
49 |
-
self::$
|
50 |
-
self::$_currentDir = realpath($currentDir);
|
51 |
self::$_symlinks = array();
|
52 |
-
|
53 |
-
//echo "doc".self::$_docRoot."<br>";
|
54 |
-
//echo "current".self::$_currentDir."<br>";exit;
|
55 |
|
56 |
// normalize symlinks
|
57 |
-
foreach ($symlinks as $link => $target) {
|
58 |
-
$link =
|
59 |
-
|
60 |
-
|
|
|
|
|
61 |
}
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
$css = self::_trimUrls($css);
|
64 |
|
65 |
// rewrite
|
66 |
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
67 |
-
,array(self::$className, '
|
68 |
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
69 |
-
,array(self::$className, '
|
70 |
|
71 |
return $css;
|
72 |
}
|
@@ -88,9 +99,9 @@ class Minify_CSS_UriRewriter {
|
|
88 |
|
89 |
// append
|
90 |
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
91 |
-
,array(self::$className, '
|
92 |
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
93 |
-
,array(self::$className, '
|
94 |
|
95 |
self::$_prependPath = null;
|
96 |
return $css;
|
@@ -107,9 +118,9 @@ class Minify_CSS_UriRewriter {
|
|
107 |
*/
|
108 |
private static $_docRoot = '';
|
109 |
|
110 |
-
/**
|
111 |
-
* @var array directory replacements to map symlink targets back to their
|
112 |
-
* source (within the document root) E.g. '/var/www/symlink' => '/var/realpath'
|
113 |
*/
|
114 |
private static $_symlinks = array();
|
115 |
|
@@ -118,27 +129,26 @@ class Minify_CSS_UriRewriter {
|
|
118 |
*/
|
119 |
private static $_prependPath = null;
|
120 |
|
121 |
-
|
122 |
private static function _trimUrls($css)
|
123 |
{
|
124 |
return preg_replace('/
|
125 |
url\\( # url(
|
126 |
\\s*
|
127 |
-
([^\\)]+?) # 1 = URI (
|
128 |
\\s*
|
129 |
\\) # )
|
130 |
/x', 'url($1)', $css);
|
131 |
}
|
132 |
|
133 |
-
|
134 |
-
private static function _uriCB($m)
|
135 |
{
|
|
|
136 |
$isImport = ($m[0][0] === '@');
|
|
|
137 |
if ($isImport) {
|
138 |
$quoteChar = $m[1];
|
139 |
$uri = $m[2];
|
140 |
} else {
|
141 |
-
// is url()
|
142 |
// $m[1] is either quoted or not
|
143 |
$quoteChar = ($m[1][0] === "'" || $m[1][0] === '"')
|
144 |
? $m[1][0]
|
@@ -147,47 +157,116 @@ class Minify_CSS_UriRewriter {
|
|
147 |
? $m[1]
|
148 |
: substr($m[1], 1, strlen($m[1]) - 2);
|
149 |
}
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
)
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
// prepend path
|
160 |
-
$uri = self::$_prependPath . $uri;
|
161 |
-
} else {
|
162 |
-
// rewrite path
|
163 |
-
// prepend path with current dir separator (OS-independent)
|
164 |
-
$path = strtr(self::$_currentDir, '/', DIRECTORY_SEPARATOR)
|
165 |
-
. DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR);//echo "1".$path."<br>";
|
166 |
-
// "unresolve" a symlink back to doc root
|
167 |
-
foreach (self::$_symlinks as $link => $target) {
|
168 |
-
if (0 === strpos($path, $target)) {
|
169 |
-
// replace $target with $link
|
170 |
-
$path = $link . substr($path, strlen($target));
|
171 |
-
break;
|
172 |
-
}
|
173 |
-
}
|
174 |
-
// strip doc root
|
175 |
-
$path = substr($path, strlen(self::$_docRoot));//echo "2".$path."<br>";
|
176 |
-
// fix to root-relative URI
|
177 |
-
$uri = strtr($path, DIRECTORY_SEPARATOR, '/');//echo "3".$uri."<br>";
|
178 |
-
// remove /./ and /../ where possible
|
179 |
-
$uri = str_replace('/./', '/', $uri);//echo "4".$uri."<br>";
|
180 |
-
// inspired by patch from Oleg Cherniy
|
181 |
-
do {
|
182 |
-
$uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, -1, $changed);
|
183 |
-
} while ($changed);
|
184 |
-
}
|
185 |
-
}
|
186 |
}
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
}
|
|
|
|
|
|
|
|
|
192 |
}
|
193 |
}
|
19 |
*/
|
20 |
protected static $className = 'Minify_CSS_UriRewriter';
|
21 |
|
22 |
+
/**
|
23 |
+
* rewrite() and rewriteRelative() append debugging information here
|
24 |
+
* @var string
|
25 |
+
*/
|
26 |
+
public static $debugText = '';
|
27 |
+
|
28 |
/**
|
29 |
* Rewrite file relative URIs as root relative in CSS files
|
30 |
*
|
49 |
*/
|
50 |
public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = array())
|
51 |
{
|
52 |
+
self::$_docRoot = self::_realpath(
|
53 |
+
$docRoot ? $docRoot : $_SERVER['DOCUMENT_ROOT']
|
54 |
+
);
|
55 |
+
self::$_currentDir = self::_realpath($currentDir);
|
|
|
56 |
self::$_symlinks = array();
|
|
|
|
|
|
|
57 |
|
58 |
// normalize symlinks
|
59 |
+
foreach ($symlinks as $link => $target) {
|
60 |
+
$link = ($link === '//')
|
61 |
+
? self::$_docRoot
|
62 |
+
: str_replace('//', self::$_docRoot . '/', $link);
|
63 |
+
$link = strtr($link, '/', DIRECTORY_SEPARATOR);
|
64 |
+
self::$_symlinks[$link] = self::_realpath($target);
|
65 |
}
|
66 |
+
|
67 |
+
self::$debugText .= "docRoot : " . self::$_docRoot . "\n"
|
68 |
+
. "currentDir : " . self::$_currentDir . "\n";
|
69 |
+
if (self::$_symlinks) {
|
70 |
+
self::$debugText .= "symlinks : " . var_export(self::$_symlinks, 1) . "\n";
|
71 |
+
}
|
72 |
+
self::$debugText .= "\n";
|
73 |
+
|
74 |
$css = self::_trimUrls($css);
|
75 |
|
76 |
// rewrite
|
77 |
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
78 |
+
,array(self::$className, '_processUriCB'), $css);
|
79 |
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
80 |
+
,array(self::$className, '_processUriCB'), $css);
|
81 |
|
82 |
return $css;
|
83 |
}
|
99 |
|
100 |
// append
|
101 |
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
102 |
+
,array(self::$className, '_processUriCB'), $css);
|
103 |
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
104 |
+
,array(self::$className, '_processUriCB'), $css);
|
105 |
|
106 |
self::$_prependPath = null;
|
107 |
return $css;
|
118 |
*/
|
119 |
private static $_docRoot = '';
|
120 |
|
121 |
+
/**
|
122 |
+
* @var array directory replacements to map symlink targets back to their
|
123 |
+
* source (within the document root) E.g. '/var/www/symlink' => '/var/realpath'
|
124 |
*/
|
125 |
private static $_symlinks = array();
|
126 |
|
129 |
*/
|
130 |
private static $_prependPath = null;
|
131 |
|
|
|
132 |
private static function _trimUrls($css)
|
133 |
{
|
134 |
return preg_replace('/
|
135 |
url\\( # url(
|
136 |
\\s*
|
137 |
+
([^\\)]+?) # 1 = URI (assuming does not contain ")")
|
138 |
\\s*
|
139 |
\\) # )
|
140 |
/x', 'url($1)', $css);
|
141 |
}
|
142 |
|
143 |
+
private static function _processUriCB($m)
|
|
|
144 |
{
|
145 |
+
// $m matched either '/@import\\s+([\'"])(.*?)[\'"]/' or '/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
146 |
$isImport = ($m[0][0] === '@');
|
147 |
+
// determine URI and the quote character (if any)
|
148 |
if ($isImport) {
|
149 |
$quoteChar = $m[1];
|
150 |
$uri = $m[2];
|
151 |
} else {
|
|
|
152 |
// $m[1] is either quoted or not
|
153 |
$quoteChar = ($m[1][0] === "'" || $m[1][0] === '"')
|
154 |
? $m[1][0]
|
157 |
? $m[1]
|
158 |
: substr($m[1], 1, strlen($m[1]) - 2);
|
159 |
}
|
160 |
+
// analyze URI
|
161 |
+
if ('/' !== $uri[0] // root-relative
|
162 |
+
&& false === strpos($uri, '//') // protocol (non-data)
|
163 |
+
&& 0 !== strpos($uri, 'data:') // data protocol
|
164 |
+
) {
|
165 |
+
// URI is file-relative: rewrite depending on options
|
166 |
+
$uri = (self::$_prependPath !== null)
|
167 |
+
? (self::$_prependPath . $uri)
|
168 |
+
: self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
}
|
170 |
+
return $isImport
|
171 |
+
? "@import {$quoteChar}{$uri}{$quoteChar}"
|
172 |
+
: "url({$quoteChar}{$uri}{$quoteChar})";
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Rewrite a file relative URI as root relative
|
177 |
+
*
|
178 |
+
* <code>
|
179 |
+
* Minify_CSS_UriRewriter::rewriteRelative(
|
180 |
+
* '../img/hello.gif'
|
181 |
+
* , '/home/user/www/css' // path of CSS file
|
182 |
+
* , '/home/user/www' // doc root
|
183 |
+
* );
|
184 |
+
* // returns '/img/hello.gif'
|
185 |
+
*
|
186 |
+
* // example where static files are stored in a symlinked directory
|
187 |
+
* Minify_CSS_UriRewriter::rewriteRelative(
|
188 |
+
* 'hello.gif'
|
189 |
+
* , '/var/staticFiles/theme'
|
190 |
+
* , '/home/user/www'
|
191 |
+
* , array('/home/user/www/static' => '/var/staticFiles')
|
192 |
+
* );
|
193 |
+
* // returns '/static/theme/hello.gif'
|
194 |
+
* </code>
|
195 |
+
*
|
196 |
+
* @param string $uri file relative URI
|
197 |
+
*
|
198 |
+
* @param string $realCurrentDir realpath of the current file's directory.
|
199 |
+
*
|
200 |
+
* @param string $realDocRoot realpath of the site document root.
|
201 |
+
*
|
202 |
+
* @param array $symlinks (default = array()) If the file is stored in
|
203 |
+
* a symlink-ed directory, provide an array of link paths to
|
204 |
+
* real target paths, where the link paths "appear" to be within the document
|
205 |
+
* root. E.g.:
|
206 |
+
* <code>
|
207 |
+
* array('/home/foo/www/not/real/path' => '/real/target/path') // unix
|
208 |
+
* array('C:\\htdocs\\not\\real' => 'D:\\real\\target\\path') // Windows
|
209 |
+
* </code>
|
210 |
+
*
|
211 |
+
* @return string
|
212 |
+
*/
|
213 |
+
public static function rewriteRelative($uri, $realCurrentDir, $realDocRoot, $symlinks = array())
|
214 |
+
{
|
215 |
+
// prepend path with current dir separator (OS-independent)
|
216 |
+
$path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR)
|
217 |
+
. DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR);
|
218 |
+
|
219 |
+
self::$debugText .= "file-relative URI : {$uri}\n"
|
220 |
+
. "path prepended : {$path}\n";
|
221 |
+
|
222 |
+
// "unresolve" a symlink back to doc root
|
223 |
+
foreach ($symlinks as $link => $target) {
|
224 |
+
if (0 === strpos($path, $target)) {
|
225 |
+
// replace $target with $link
|
226 |
+
$path = $link . substr($path, strlen($target));
|
227 |
+
|
228 |
+
self::$debugText .= "symlink unresolved : {$path}\n";
|
229 |
+
|
230 |
+
break;
|
231 |
+
}
|
232 |
+
}
|
233 |
+
// strip doc root
|
234 |
+
$path = substr($path, strlen($realDocRoot));
|
235 |
+
|
236 |
+
self::$debugText .= "docroot stripped : {$path}\n";
|
237 |
+
|
238 |
+
// fix to root-relative URI
|
239 |
+
$uri = strtr($path, DIRECTORY_SEPARATOR, '/');
|
240 |
+
// remove /./ and /../ where possible
|
241 |
+
$uri = str_replace('/./', '/', $uri);
|
242 |
+
// inspired by patch from Oleg Cherniy
|
243 |
+
do {
|
244 |
+
$uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, -1, $changed);
|
245 |
+
} while ($changed);
|
246 |
+
|
247 |
+
self::$debugText .= "traversals removed : {$uri}\n\n";
|
248 |
+
|
249 |
+
return $uri;
|
250 |
+
}
|
251 |
+
|
252 |
+
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Get realpath with any trailing slash removed
|
256 |
+
*
|
257 |
+
* @param string $path
|
258 |
+
*
|
259 |
+
* @return mixed real path or false on realpath() failure
|
260 |
+
*/
|
261 |
+
protected static function _realpath($path)
|
262 |
+
{
|
263 |
+
$path = realpath($path);
|
264 |
+
if (! $path) {
|
265 |
+
return false;
|
266 |
}
|
267 |
+
$last = $path[strlen($path) - 1];
|
268 |
+
return ($last === '/' || $last === '\\')
|
269 |
+
? substr($path, 0, strlen($path) - 1)
|
270 |
+
: $path;
|
271 |
}
|
272 |
}
|
lib/minify/lib/Minify/Controller/Base.php
CHANGED
@@ -48,6 +48,7 @@ abstract class Minify_Controller_Base {
|
|
48 |
,'contentTypeCharset' => 'UTF-8'
|
49 |
,'maxAge' => 1800 // 30 minutes
|
50 |
,'rewriteCssUris' => true
|
|
|
51 |
,'quiet' => false // serve() will send headers and output
|
52 |
,'debug' => false
|
53 |
|
48 |
,'contentTypeCharset' => 'UTF-8'
|
49 |
,'maxAge' => 1800 // 30 minutes
|
50 |
,'rewriteCssUris' => true
|
51 |
+
,'bubbleCssImports' => false
|
52 |
,'quiet' => false // serve() will send headers and output
|
53 |
,'debug' => false
|
54 |
|
lib/minify/lib/Minify/HTML.php
CHANGED
@@ -18,13 +18,6 @@
|
|
18 |
*/
|
19 |
class Minify_HTML {
|
20 |
|
21 |
-
/**
|
22 |
-
* Defines which class to call as part of callbacks, change this
|
23 |
-
* if you extend Minify_HTML
|
24 |
-
* @var string
|
25 |
-
*/
|
26 |
-
protected static $className = 'Minify_HTML';
|
27 |
-
|
28 |
/**
|
29 |
* "Minify" an HTML page
|
30 |
*
|
@@ -44,122 +37,152 @@ class Minify_HTML {
|
|
44 |
* @return string
|
45 |
*/
|
46 |
public static function minify($html, $options = array()) {
|
47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
if (isset($options['cssMinifier'])) {
|
49 |
-
|
50 |
}
|
51 |
if (isset($options['jsMinifier'])) {
|
52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
}
|
54 |
|
55 |
-
$
|
56 |
-
|
57 |
-
self::$_isXhtml = (
|
58 |
-
isset($options['xhtml'])
|
59 |
-
? (bool)$options['xhtml']
|
60 |
-
: (false !== strpos($html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'))
|
61 |
-
);
|
62 |
-
|
63 |
-
self::$_replacementHash = 'MINIFYHTML' . md5(time());
|
64 |
-
self::$_placeholders = array();
|
65 |
|
66 |
// replace SCRIPTs (and minify) with placeholders
|
67 |
-
$
|
68 |
'/(\\s*)(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
|
69 |
-
,array(
|
70 |
-
,$
|
71 |
|
72 |
// replace STYLEs (and minify) with placeholders
|
73 |
-
$
|
74 |
'/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i'
|
75 |
-
,array(
|
76 |
-
,$
|
77 |
|
78 |
// remove HTML comments (not containing IE conditional comments).
|
79 |
-
$
|
80 |
'/<!--([\\s\\S]*?)-->/'
|
81 |
-
,array(
|
82 |
-
,$
|
83 |
|
84 |
// replace PREs with placeholders
|
85 |
-
$
|
86 |
-
,array(
|
87 |
-
|
88 |
|
89 |
// replace TEXTAREAs with placeholders
|
90 |
-
$
|
91 |
'/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
92 |
-
,array(
|
93 |
-
|
94 |
|
95 |
// trim each line.
|
96 |
// @todo take into account attribute values that span multiple lines.
|
97 |
-
$
|
98 |
|
99 |
// remove ws around block/undisplayed elements
|
100 |
-
$
|
101 |
.'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
|
102 |
.'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
|
103 |
.'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
|
104 |
-
.'|ul)\\b[^>]*>)/i', '$1', $
|
105 |
|
106 |
// remove ws outside of all elements
|
107 |
-
$
|
108 |
'/>([^<]+)</'
|
109 |
-
,array(
|
110 |
-
,$
|
111 |
|
112 |
// use newlines before 1st attribute in open tags (to limit line lengths)
|
113 |
-
$
|
114 |
|
115 |
// fill placeholders
|
116 |
-
$
|
117 |
-
array_keys(
|
118 |
-
,array_values(
|
119 |
-
,$
|
120 |
);
|
121 |
-
|
122 |
-
|
123 |
-
self::$_cssMinifier = self::$_jsMinifier = null;
|
124 |
-
return $html;
|
125 |
}
|
126 |
|
127 |
-
protected
|
128 |
{
|
129 |
return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
|
130 |
? $m[0]
|
131 |
: '';
|
132 |
}
|
133 |
|
134 |
-
protected
|
135 |
{
|
136 |
-
$placeholder = '%' .
|
137 |
-
|
138 |
return $placeholder;
|
139 |
}
|
140 |
|
141 |
-
protected
|
142 |
-
protected
|
143 |
-
protected
|
144 |
-
protected
|
145 |
-
protected
|
146 |
|
147 |
-
protected
|
148 |
{
|
149 |
return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
|
150 |
}
|
151 |
|
152 |
-
protected
|
153 |
{
|
154 |
-
return
|
155 |
}
|
156 |
|
157 |
-
protected
|
158 |
{
|
159 |
-
return
|
160 |
}
|
161 |
|
162 |
-
protected
|
163 |
{
|
164 |
$openStyle = $m[1];
|
165 |
$css = $m[2];
|
@@ -167,21 +190,21 @@ class Minify_HTML {
|
|
167 |
$css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
|
168 |
|
169 |
// remove CDATA section markers
|
170 |
-
$css =
|
171 |
|
172 |
// minify
|
173 |
-
$minifier =
|
174 |
-
?
|
175 |
: 'trim';
|
176 |
$css = call_user_func($minifier, $css);
|
177 |
|
178 |
-
return
|
179 |
? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
|
180 |
: "{$openStyle}{$css}</style>"
|
181 |
);
|
182 |
}
|
183 |
|
184 |
-
protected
|
185 |
{
|
186 |
$openScript = $m[2];
|
187 |
$js = $m[3];
|
@@ -194,29 +217,29 @@ class Minify_HTML {
|
|
194 |
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
|
195 |
|
196 |
// remove CDATA section markers
|
197 |
-
$js =
|
198 |
|
199 |
// minify
|
200 |
-
$minifier =
|
201 |
-
?
|
202 |
: 'trim';
|
203 |
$js = call_user_func($minifier, $js);
|
204 |
|
205 |
-
return
|
206 |
? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
|
207 |
: "{$ws1}{$openScript}{$js}</script>{$ws2}"
|
208 |
);
|
209 |
}
|
210 |
|
211 |
-
protected
|
212 |
{
|
213 |
return (false !== strpos($str, '<![CDATA['))
|
214 |
? str_replace(array('<![CDATA[', ']]>'), '', $str)
|
215 |
: $str;
|
216 |
}
|
217 |
|
218 |
-
protected
|
219 |
{
|
220 |
-
return (
|
221 |
}
|
222 |
}
|
18 |
*/
|
19 |
class Minify_HTML {
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
/**
|
22 |
* "Minify" an HTML page
|
23 |
*
|
37 |
* @return string
|
38 |
*/
|
39 |
public static function minify($html, $options = array()) {
|
40 |
+
$min = new Minify_HTML($html, $options);
|
41 |
+
return $min->process();
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Create a minifier object
|
47 |
+
*
|
48 |
+
* @param string $html
|
49 |
+
*
|
50 |
+
* @param array $options
|
51 |
+
*
|
52 |
+
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
53 |
+
* elements.
|
54 |
+
*
|
55 |
+
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
56 |
+
* elements. Note: the type attribute is ignored.
|
57 |
+
*
|
58 |
+
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
59 |
+
* unset, minify will sniff for an XHTML doctype.
|
60 |
+
*
|
61 |
+
* @return null
|
62 |
+
*/
|
63 |
+
public function __construct($html, $options = array())
|
64 |
+
{
|
65 |
+
$this->_html = str_replace("\r\n", "\n", trim($html));
|
66 |
+
if (isset($options['xhtml'])) {
|
67 |
+
$this->_isXhtml = (bool)$options['xhtml'];
|
68 |
+
}
|
69 |
if (isset($options['cssMinifier'])) {
|
70 |
+
$this->_cssMinifier = $options['cssMinifier'];
|
71 |
}
|
72 |
if (isset($options['jsMinifier'])) {
|
73 |
+
$this->_jsMinifier = $options['jsMinifier'];
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Minify the markeup given in the constructor
|
80 |
+
*
|
81 |
+
* @return string
|
82 |
+
*/
|
83 |
+
public function process()
|
84 |
+
{
|
85 |
+
if ($this->_isXhtml === null) {
|
86 |
+
$this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
|
87 |
}
|
88 |
|
89 |
+
$this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
|
90 |
+
$this->_placeholders = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
// replace SCRIPTs (and minify) with placeholders
|
93 |
+
$this->_html = preg_replace_callback(
|
94 |
'/(\\s*)(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
|
95 |
+
,array($this, '_removeScriptCB')
|
96 |
+
,$this->_html);
|
97 |
|
98 |
// replace STYLEs (and minify) with placeholders
|
99 |
+
$this->_html = preg_replace_callback(
|
100 |
'/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i'
|
101 |
+
,array($this, '_removeStyleCB')
|
102 |
+
,$this->_html);
|
103 |
|
104 |
// remove HTML comments (not containing IE conditional comments).
|
105 |
+
$this->_html = preg_replace_callback(
|
106 |
'/<!--([\\s\\S]*?)-->/'
|
107 |
+
,array($this, '_commentCB')
|
108 |
+
,$this->_html);
|
109 |
|
110 |
// replace PREs with placeholders
|
111 |
+
$this->_html = preg_replace_callback('/\\s*(<pre\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
|
112 |
+
,array($this, '_removePreCB')
|
113 |
+
,$this->_html);
|
114 |
|
115 |
// replace TEXTAREAs with placeholders
|
116 |
+
$this->_html = preg_replace_callback(
|
117 |
'/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
118 |
+
,array($this, '_removeTextareaCB')
|
119 |
+
,$this->_html);
|
120 |
|
121 |
// trim each line.
|
122 |
// @todo take into account attribute values that span multiple lines.
|
123 |
+
$this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
|
124 |
|
125 |
// remove ws around block/undisplayed elements
|
126 |
+
$this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
|
127 |
.'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
|
128 |
.'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
|
129 |
.'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
|
130 |
+
.'|ul)\\b[^>]*>)/i', '$1', $this->_html);
|
131 |
|
132 |
// remove ws outside of all elements
|
133 |
+
$this->_html = preg_replace_callback(
|
134 |
'/>([^<]+)</'
|
135 |
+
,array($this, '_outsideTagCB')
|
136 |
+
,$this->_html);
|
137 |
|
138 |
// use newlines before 1st attribute in open tags (to limit line lengths)
|
139 |
+
$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
|
140 |
|
141 |
// fill placeholders
|
142 |
+
$this->_html = str_replace(
|
143 |
+
array_keys($this->_placeholders)
|
144 |
+
,array_values($this->_placeholders)
|
145 |
+
,$this->_html
|
146 |
);
|
147 |
+
return $this->_html;
|
|
|
|
|
|
|
148 |
}
|
149 |
|
150 |
+
protected function _commentCB($m)
|
151 |
{
|
152 |
return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
|
153 |
? $m[0]
|
154 |
: '';
|
155 |
}
|
156 |
|
157 |
+
protected function _reservePlace($content)
|
158 |
{
|
159 |
+
$placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
|
160 |
+
$this->_placeholders[$placeholder] = $content;
|
161 |
return $placeholder;
|
162 |
}
|
163 |
|
164 |
+
protected $_isXhtml = null;
|
165 |
+
protected $_replacementHash = null;
|
166 |
+
protected $_placeholders = array();
|
167 |
+
protected $_cssMinifier = null;
|
168 |
+
protected $_jsMinifier = null;
|
169 |
|
170 |
+
protected function _outsideTagCB($m)
|
171 |
{
|
172 |
return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
|
173 |
}
|
174 |
|
175 |
+
protected function _removePreCB($m)
|
176 |
{
|
177 |
+
return $this->_reservePlace($m[1]);
|
178 |
}
|
179 |
|
180 |
+
protected function _removeTextareaCB($m)
|
181 |
{
|
182 |
+
return $this->_reservePlace($m[1]);
|
183 |
}
|
184 |
|
185 |
+
protected function _removeStyleCB($m)
|
186 |
{
|
187 |
$openStyle = $m[1];
|
188 |
$css = $m[2];
|
190 |
$css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
|
191 |
|
192 |
// remove CDATA section markers
|
193 |
+
$css = $this->_removeCdata($css);
|
194 |
|
195 |
// minify
|
196 |
+
$minifier = $this->_cssMinifier
|
197 |
+
? $this->_cssMinifier
|
198 |
: 'trim';
|
199 |
$css = call_user_func($minifier, $css);
|
200 |
|
201 |
+
return $this->_reservePlace($this->_needsCdata($css)
|
202 |
? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
|
203 |
: "{$openStyle}{$css}</style>"
|
204 |
);
|
205 |
}
|
206 |
|
207 |
+
protected function _removeScriptCB($m)
|
208 |
{
|
209 |
$openScript = $m[2];
|
210 |
$js = $m[3];
|
217 |
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
|
218 |
|
219 |
// remove CDATA section markers
|
220 |
+
$js = $this->_removeCdata($js);
|
221 |
|
222 |
// minify
|
223 |
+
$minifier = $this->_jsMinifier
|
224 |
+
? $this->_jsMinifier
|
225 |
: 'trim';
|
226 |
$js = call_user_func($minifier, $js);
|
227 |
|
228 |
+
return $this->_reservePlace($this->_needsCdata($js)
|
229 |
? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
|
230 |
: "{$ws1}{$openScript}{$js}</script>{$ws2}"
|
231 |
);
|
232 |
}
|
233 |
|
234 |
+
protected function _removeCdata($str)
|
235 |
{
|
236 |
return (false !== strpos($str, '<![CDATA['))
|
237 |
? str_replace(array('<![CDATA[', ']]>'), '', $str)
|
238 |
: $str;
|
239 |
}
|
240 |
|
241 |
+
protected function _needsCdata($str)
|
242 |
{
|
243 |
+
return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
|
244 |
}
|
245 |
}
|
lib/minify/lib/Minify/Lines.php
CHANGED
@@ -18,13 +18,19 @@ class Minify_Lines {
|
|
18 |
*
|
19 |
* This uses a very basic parser easily fooled by comment tokens inside
|
20 |
* strings or regexes, but, otherwise, generally clean code will not be
|
21 |
-
* mangled.
|
22 |
-
*
|
23 |
* @param string $content
|
24 |
*
|
25 |
* @param array $options available options:
|
26 |
*
|
27 |
* 'id': (optional) string to identify file. E.g. file name/path
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
*
|
29 |
* @return string
|
30 |
*/
|
@@ -49,7 +55,24 @@ class Minify_Lines {
|
|
49 |
$newLines[] = self::_addNote($line, $i, $inComment, $padTo);
|
50 |
$inComment = self::_eolInComment($line, $inComment);
|
51 |
}
|
52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
}
|
54 |
|
55 |
/**
|
18 |
*
|
19 |
* This uses a very basic parser easily fooled by comment tokens inside
|
20 |
* strings or regexes, but, otherwise, generally clean code will not be
|
21 |
+
* mangled. URI rewriting can also be performed.
|
22 |
+
*
|
23 |
* @param string $content
|
24 |
*
|
25 |
* @param array $options available options:
|
26 |
*
|
27 |
* 'id': (optional) string to identify file. E.g. file name/path
|
28 |
+
*
|
29 |
+
* 'currentDir': (default null) if given, this is assumed to be the
|
30 |
+
* directory of the current CSS file. Using this, minify will rewrite
|
31 |
+
* all relative URIs in import/url declarations to correctly point to
|
32 |
+
* the desired files, and prepend a comment with debugging information about
|
33 |
+
* this process.
|
34 |
*
|
35 |
* @return string
|
36 |
*/
|
55 |
$newLines[] = self::_addNote($line, $i, $inComment, $padTo);
|
56 |
$inComment = self::_eolInComment($line, $inComment);
|
57 |
}
|
58 |
+
$content = implode("\n", $newLines) . "\n";
|
59 |
+
|
60 |
+
// check for desired URI rewriting
|
61 |
+
if (isset($options['currentDir'])) {
|
62 |
+
require_once 'Minify/CSS/UriRewriter.php';
|
63 |
+
Minify_CSS_UriRewriter::$debugText = '';
|
64 |
+
$content = Minify_CSS_UriRewriter::rewrite(
|
65 |
+
$content
|
66 |
+
,$options['currentDir']
|
67 |
+
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
68 |
+
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
69 |
+
);
|
70 |
+
$content = "/* Minify_CSS_UriRewriter::\$debugText\n\n"
|
71 |
+
. Minify_CSS_UriRewriter::$debugText . "*/\n"
|
72 |
+
. $content;
|
73 |
+
}
|
74 |
+
|
75 |
+
return $content;
|
76 |
}
|
77 |
|
78 |
/**
|
lib/minify/lib/MyMin.php
DELETED
@@ -1,289 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* MyMin - JSMin like alternative parser for JavaScript
|
4 |
-
*
|
5 |
-
* This class is a jsmin alternative, based on same parser logic but modified
|
6 |
-
* to mantain performances and to parse correctly JavaScript conditional comments too.
|
7 |
-
*
|
8 |
-
* SERVER SIDE
|
9 |
-
* PHP 5 or greater is required.
|
10 |
-
* This code is compatible with every error_reporting level (E_ALL | E_STRICT)
|
11 |
-
* The best practice to use this code is caching results without run-time
|
12 |
-
* evaluation (your server should be stressed too much with big files)
|
13 |
-
*
|
14 |
-
* Permission is hereby granted to use this version of the library under the
|
15 |
-
* same terms as jsmin.php, which has the following license:
|
16 |
-
*
|
17 |
-
* --
|
18 |
-
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
19 |
-
*
|
20 |
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
21 |
-
* this software and associated documentation files (the "Software"), to deal in
|
22 |
-
* the Software without restriction, including without limitation the rights to
|
23 |
-
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
24 |
-
* of the Software, and to permit persons to whom the Software is furnished to do
|
25 |
-
* so, subject to the following conditions:
|
26 |
-
*
|
27 |
-
* The above copyright notice and this permission notice shall be included in all
|
28 |
-
* copies or substantial portions of the Software.
|
29 |
-
*
|
30 |
-
* The Software shall be used for Good, not Evil.
|
31 |
-
*
|
32 |
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
33 |
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
34 |
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
35 |
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
36 |
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
37 |
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
38 |
-
* SOFTWARE.
|
39 |
-
* --
|
40 |
-
*
|
41 |
-
* @class MyMin
|
42 |
-
* @author Andrea Giammarchi <http://www.3site.eu>
|
43 |
-
* @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
|
44 |
-
* @copyright 2007 Ryan Grove <ryan@wonko.com> (PHP port)
|
45 |
-
* @copyright 2007 Andrea Giammarchi (improvements + MyMinCompressor + MyMinCSS)
|
46 |
-
* @license http://opensource.org/licenses/mit-license.php MIT License
|
47 |
-
* @version 1.0.1 (2007-10-05) - updated 2008-02-17
|
48 |
-
*/
|
49 |
-
|
50 |
-
// -- Class MyMin --------------------------------------------------------------
|
51 |
-
class MyMin {
|
52 |
-
|
53 |
-
const /* char */ LF = "\n",
|
54 |
-
SPACE = ' ',
|
55 |
-
EOS = "\x00";
|
56 |
-
|
57 |
-
protected /* boolean */ $cc_on;
|
58 |
-
|
59 |
-
protected /* char */ $a,
|
60 |
-
$ahead,
|
61 |
-
$b;
|
62 |
-
|
63 |
-
protected /* int */ $index = 0,
|
64 |
-
$length;
|
65 |
-
|
66 |
-
protected /* string */ $input,
|
67 |
-
$output = "";
|
68 |
-
|
69 |
-
// -- Public Static Methods ----------------------------------------------------
|
70 |
-
static public final function /* string */ parse(/* string */ $input, /* boolean */ $cc_on = true){
|
71 |
-
return "".(new MyMin($input, $cc_on));
|
72 |
-
}
|
73 |
-
|
74 |
-
// -- Public Instance Methods --------------------------------------------------
|
75 |
-
public final function /* object */ __construct(/* string */ $input, /* boolean */ $cc_on = true){
|
76 |
-
$this->input = preg_replace("/(\r\n|\n\r|\r|\n)+/", self::LF, trim($input));
|
77 |
-
$this->length = strlen($this->input);
|
78 |
-
$this->cc_on = $cc_on;
|
79 |
-
$this->b = $this->ahead = self::SPACE;
|
80 |
-
$this->a = self::LF;
|
81 |
-
$this->action(3);
|
82 |
-
while($this->a !== self::EOS){
|
83 |
-
switch($this->a){
|
84 |
-
case self::SPACE:
|
85 |
-
$this->action($this->isAlNum($this->b) ? 1 : 2);
|
86 |
-
break;
|
87 |
-
case self::LF:
|
88 |
-
switch($this->b){
|
89 |
-
case '{':
|
90 |
-
case '[':
|
91 |
-
case '(':
|
92 |
-
case '+':
|
93 |
-
case '-':
|
94 |
-
$this->action(1);
|
95 |
-
break;
|
96 |
-
case self::SPACE:
|
97 |
-
$this->action(3);
|
98 |
-
break;
|
99 |
-
default:
|
100 |
-
$this->action($this->isAlNum($this->b) ? 1 : 2);
|
101 |
-
break;
|
102 |
-
}
|
103 |
-
break;
|
104 |
-
default:
|
105 |
-
switch($this->b){
|
106 |
-
case self::SPACE:
|
107 |
-
$this->action($this->isAlNum($this->a) ? 1 : 3);
|
108 |
-
break;
|
109 |
-
case self::LF:
|
110 |
-
switch($this->a){
|
111 |
-
case '}':
|
112 |
-
case ']':
|
113 |
-
case ')':
|
114 |
-
case '+':
|
115 |
-
case '-':
|
116 |
-
case '"':
|
117 |
-
case '\'':
|
118 |
-
$this->action(1);
|
119 |
-
break;
|
120 |
-
default:
|
121 |
-
$this->action($this->isAlNum($this->a) ? 1 : 3);
|
122 |
-
break;
|
123 |
-
}
|
124 |
-
break;
|
125 |
-
default:
|
126 |
-
$this->action(1);
|
127 |
-
break;
|
128 |
-
}
|
129 |
-
break;
|
130 |
-
}
|
131 |
-
}
|
132 |
-
}
|
133 |
-
|
134 |
-
public final function /* string */ __toString(/* void */){
|
135 |
-
return str_replace("\n\n", "\n", ltrim($this->output));
|
136 |
-
}
|
137 |
-
|
138 |
-
// -- Protected Instance Methods -----------------------------------------------
|
139 |
-
protected function /* void */ action(/* int */ $i){
|
140 |
-
switch($i){
|
141 |
-
case 1:
|
142 |
-
$this->output .= $this->a;
|
143 |
-
case 2:
|
144 |
-
$this->a = $this->b;
|
145 |
-
if($this->a === '\'' || $this->a === '"'){
|
146 |
-
while(true){
|
147 |
-
$this->output .= $this->a;
|
148 |
-
if(!$this->nextCharNoSlash($this->b, "Unterminated string literal."))
|
149 |
-
break;
|
150 |
-
}
|
151 |
-
}
|
152 |
-
case 3:
|
153 |
-
$this->b = $this->next();
|
154 |
-
if($this->b === '/'){
|
155 |
-
switch($this->a){
|
156 |
-
case self::LF:
|
157 |
-
case self::SPACE:
|
158 |
-
if(!$this->spaceBeforeRegExp($this->output))
|
159 |
-
break;
|
160 |
-
|
161 |
-
case '{':
|
162 |
-
case ';':
|
163 |
-
|
164 |
-
case '(':
|
165 |
-
case ',':
|
166 |
-
case '=':
|
167 |
-
case ':':
|
168 |
-
case '[':
|
169 |
-
case '!':
|
170 |
-
case '&':
|
171 |
-
case '|':
|
172 |
-
case '?':
|
173 |
-
$this->output .= $this->a.$this->b;
|
174 |
-
while($this->nextCharNoSlash('/', "Unterminated regular expression literal."))
|
175 |
-
$this->output .= $this->a;
|
176 |
-
$this->b = $this->next();
|
177 |
-
break;
|
178 |
-
}
|
179 |
-
}
|
180 |
-
break;
|
181 |
-
}
|
182 |
-
}
|
183 |
-
|
184 |
-
protected function /* void */ appendComment(/* int */ $pos, /* string */ $open, /* string */ $close) {
|
185 |
-
$this->output .= $this->a.$open.(new MyMin(substr($this->input, $this->index, $pos - $this->index), $this->cc_on)).$close;
|
186 |
-
$this->index = $pos;
|
187 |
-
$this->a = self::LF;
|
188 |
-
}
|
189 |
-
|
190 |
-
protected function /* void */ conditionalComment(/* char */ $find) {
|
191 |
-
$single = $find === self::LF;
|
192 |
-
$pos = strpos($this->input, $find, $this->index);
|
193 |
-
if($pos === false){
|
194 |
-
if($single)
|
195 |
-
$pos = $this->length;
|
196 |
-
else
|
197 |
-
throw new MyMinException("Unterminated comment.");
|
198 |
-
}
|
199 |
-
$this->appendComment($pos, $single ? "//" : "/*", $find);
|
200 |
-
}
|
201 |
-
|
202 |
-
protected function /* char */ get(/* void */) {
|
203 |
-
$c = $this->ahead;
|
204 |
-
$this->ahead = self::EOS;
|
205 |
-
if($c === self::EOS && $this->index < $this->length)
|
206 |
-
$c = $this->input{$this->index++};
|
207 |
-
return ($c === self::EOS || $c === self::LF || $c >= self::SPACE) ? $c : self::SPACE;
|
208 |
-
}
|
209 |
-
|
210 |
-
protected function /* boolean */ isAlNum(/* char */ $c) {
|
211 |
-
return $c > 126 || $c === '\\' || preg_match('/^(\w|\$)$/', $c);
|
212 |
-
}
|
213 |
-
|
214 |
-
protected function /* char */ next(/* void */) {
|
215 |
-
$c = $this->get();
|
216 |
-
$loop = true;
|
217 |
-
if($c === '/'){
|
218 |
-
switch($this->ahead = $this->get()){
|
219 |
-
case '/':
|
220 |
-
if($this->cc_on && $this->input{$this->index} === '@')
|
221 |
-
$this->conditionalComment(self::LF);
|
222 |
-
while($loop){
|
223 |
-
$c = $this->get();
|
224 |
-
if($c <= self::LF)
|
225 |
-
$loop = false;
|
226 |
-
}
|
227 |
-
break;
|
228 |
-
case '*':
|
229 |
-
$this->get();
|
230 |
-
if($this->cc_on && $this->input{$this->index} === '@')
|
231 |
-
$this->conditionalComment("*/");
|
232 |
-
while($loop){
|
233 |
-
switch($this->get()){
|
234 |
-
case '*':
|
235 |
-
if(($this->ahead = $this->get()) === '/'){
|
236 |
-
$this->get();
|
237 |
-
$c = self::SPACE;
|
238 |
-
$loop = false;
|
239 |
-
}
|
240 |
-
break;
|
241 |
-
case self::EOS:
|
242 |
-
throw new MyMinException("Unterminated comment.");
|
243 |
-
}
|
244 |
-
}
|
245 |
-
break;
|
246 |
-
}
|
247 |
-
}
|
248 |
-
return $c;
|
249 |
-
}
|
250 |
-
|
251 |
-
protected function /* boolean */ nextCharNoSlash(/* char */ $c, /* string */ $message) {
|
252 |
-
$loop = true;
|
253 |
-
$this->a = $this->get();
|
254 |
-
if($this->a === $c)
|
255 |
-
$loop = false;
|
256 |
-
else{
|
257 |
-
if($this->a === '\\'){
|
258 |
-
$this->output .= $this->a;
|
259 |
-
$this->a = $this->get();
|
260 |
-
}
|
261 |
-
if($this->a <= self::LF)
|
262 |
-
throw new MyMinException($message);
|
263 |
-
}
|
264 |
-
return $loop;
|
265 |
-
}
|
266 |
-
|
267 |
-
protected function /* boolean */ spaceBeforeRegExp(/* string */ $output){
|
268 |
-
for(
|
269 |
-
$i = 0,
|
270 |
-
$length = strlen($output),
|
271 |
-
$reserved = array("case", "else", "in", "return", "typeof"),
|
272 |
-
$result = false,
|
273 |
-
$tmp = "";
|
274 |
-
$i < 5 && !$result;
|
275 |
-
$i++
|
276 |
-
){
|
277 |
-
if($length === strlen($reserved[$i]))
|
278 |
-
$result = $reserved[$i] === $output;
|
279 |
-
else if($length > strlen($reserved[$i])){
|
280 |
-
$tmp = substr($output, $length - strlen($reserved[$i]) - 1);
|
281 |
-
$result = substr($tmp, 1) === $reserved[$i] && !$this->isAlNum($tmp{0});
|
282 |
-
}
|
283 |
-
};
|
284 |
-
return $length < 2 ? true : $result;
|
285 |
-
}
|
286 |
-
}
|
287 |
-
|
288 |
-
// -- MyMin Exceptions ---------------------------------------------------------
|
289 |
-
class MyMinException extends Exception {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
package.xml
CHANGED
@@ -1,23 +1,23 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Fooman_Speedster</name>
|
4 |
-
<version>1.0.
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0 / BSD see files</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
<summary>Speed up your store by combining, compressing and caching JS and CSS.</summary>
|
10 |
-
<description><p>FOOMAN Speedster 1.0.
|
11 |
|
12 |
<p>Speed up your store by combining, compressing and caching JS and CSS.</p>
|
13 |
|
14 |
<p>Please read the installation instructions and latest changes <a href="http://www.magentocommerce.com/extension/457/fooman-speedster">here.</a>
|
15 |
</p></description>
|
16 |
-
<notes>
|
17 |
<authors><author><name>Kristof Ringleff</name><user>auto-converted</user><email>kristof@fooman.co.nz</email></author></authors>
|
18 |
-
<date>2009-03-
|
19 |
-
<time>
|
20 |
-
<contents><target name="mage"><dir name="app"><dir name="etc"><dir name="modules"><file name="Fooman_Speedster.xml" hash="94d303cd2552119381411068d2e7809b"/></dir></dir></dir><dir name="js"><dir name="prototype"><file name="validation-4min.js" hash="6772623b37ef0a68e845e27004d7e1cb"/></dir></dir><dir name="lib"><dir name="minify"><file name=".htaccess" hash="4d6b8833e4ccae2d2393dfeba369b894"/></dir></dir><dir name="var"><dir name="minifycache"><file name="cache.txt" hash="
|
21 |
<compatible/>
|
22 |
<dependencies/>
|
23 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Fooman_Speedster</name>
|
4 |
+
<version>1.0.2</version>
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0 / BSD see files</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
<summary>Speed up your store by combining, compressing and caching JS and CSS.</summary>
|
10 |
+
<description><p>FOOMAN Speedster 1.0.2</p>
|
11 |
|
12 |
<p>Speed up your store by combining, compressing and caching JS and CSS.</p>
|
13 |
|
14 |
<p>Please read the installation instructions and latest changes <a href="http://www.magentocommerce.com/extension/457/fooman-speedster">here.</a>
|
15 |
</p></description>
|
16 |
+
<notes>reupload of 1.0.1</notes>
|
17 |
<authors><author><name>Kristof Ringleff</name><user>auto-converted</user><email>kristof@fooman.co.nz</email></author></authors>
|
18 |
+
<date>2009-03-22</date>
|
19 |
+
<time>10:29:47</time>
|
20 |
+
<contents><target name="mage"><dir name="app"><dir name="etc"><dir name="modules"><file name="Fooman_Speedster.xml" hash="94d303cd2552119381411068d2e7809b"/></dir></dir></dir><dir name="js"><dir name="prototype"><file name="validation-4min.js" hash="6772623b37ef0a68e845e27004d7e1cb"/></dir></dir><dir name="lib"><dir name="minify"><file name=".htaccess" hash="4d6b8833e4ccae2d2393dfeba369b894"/></dir></dir><dir name="var"><dir name="minifycache"><file name="cache.txt" hash="5709c1d6a6f85fb7b7ea2eef23086b46"/></dir></dir></target><target name="magecommunity"><dir name="Fooman"><dir name="Speedster"><dir name="Block"><dir name="Adminhtml"><dir name="Page"><file name="Head.php" hash="d850197d05af7b972eda1ef6bf3da2ed"/></dir></dir><dir name="Page"><dir name="Html"><file name="Head.php" hash="d3cb5b9869689fd5535511ebbab9efee"/></dir></dir></dir><dir name="etc"><file name="config.xml" hash="a64a32de72467805e9d2e45afcb44bdb"/></dir></dir></dir></target><target name="magelib"><dir name="minify"><dir name="lib"><dir name="HTTP"><file name="ConditionalGet.php" hash="2617a41438dff20749abb9be1793b10f"/><file name="Encoder.php" hash="a2f4ae355c06fb6a98d6b4bd82c34e76"/></dir><dir name="Minify"><dir name="Cache"><file name="APC.php" hash="2766ccf5e1e4d6e38d3ec128dbc4bc6f"/><file name="File.php" hash="dd7545011e50c153a11dd100db35315a"/><file name="Memcache.php" hash="fa208d979196d0479e3aacec853502c8"/></dir><dir name="Controller"><file name="Base.php" hash="070ed4d5f471a88f2f45cf2e93ba720a"/><file name="Files.php" hash="f579a28cea39da5c595057e72fc65967"/><file name="Groups.php" hash="79bb7cbd0b598dc35a93b99adfdbfab6"/><file name="MinApp.php" hash="42803a069db0f5892012991af5ec5334"/><file name="Page.php" hash="113e99f1206cfb3c3a64aedef65554d1"/><file name="Version1.php" hash="4369c8793be1d5cf061a99651b16da26"/></dir><dir name="CSS"><file name="Compressor.php" hash="3a3a65aa92f74958f50d9d43f8827f8a"/><file name="UriRewriter.php" hash="da8f5cdad4726e0370bbe5f351ec9d98"/></dir><file name="Build.php" hash="6e329c2acc80b72cfde52be6918940bb"/><file name="BuildSpeedster.php" hash="29409f498535de615ea68679939afc27"/><file name="CommentPreserver.php" hash="86bab05265083b57935503bdd735ce74"/><file name="CSS.php" hash="cdeb49c0f35a6cef166c6cfee7f1dd95"/><file name="HTML.php" hash="e774a70491041048fef690d4b162e0ce"/><file name="ImportProcessor.php" hash="3d1726a5df7eb2edba8cd6da2cb75eec"/><file name="Javascript.php" hash="1baa1a43818fcecb89c2a08b40a544da"/><file name="Lines.php" hash="80b2932320c98d1e84aa7f48fceb35e8"/><file name="Logger.php" hash="b2844a8c35e028b9ee725be05adbcf7e"/><file name="Packer.php" hash="41878d87ec3b3e3bbd1538291edeb7cf"/><file name="Source.php" hash="a8d9fa9f0ab2ba9e9b37209148375924"/><file name="YUICompressor.php" hash="13840856d6340e70e7289035827b8b7d"/></dir><dir name="Solar"><file name="Dir.php" hash="6c88f363f6830ac4dc3917eac3c9d78c"/></dir><file name="FirePHP.php" hash="f619b5a77fee4b21e4397e98d858fbf4"/><file name="JSMin.php" hash="e9fe7911a2787240d3ed6dd2da9bc95b"/><file name="Minify.php" hash="9ee5b8bb23e3d856faec4358aa887e33"/></dir><file name="HISTORY.txt" hash="70c3e25e9331dc17e5d538bfc3dd8fe1"/><file name="LICENSE.txt" hash="911d374696c0a5e9e6e848e7f20d0ee1"/><file name="m.php" hash="49b12c34094a3ba1090f7b42719706e7"/><file name="README.txt" hash="6e961a626ae6814c72fab53bcad4a4a7"/></dir></target></contents>
|
21 |
<compatible/>
|
22 |
<dependencies/>
|
23 |
</package>
|
var/minifycache/cache.txt
CHANGED
@@ -1 +1,5 @@
|
|
|
|
|
|
|
|
1 |
this file can be deleted
|
|
1 |
+
FOOMAN Speedster
|
2 |
+
folder to cache minified output
|
3 |
+
|
4 |
this file can be deleted
|
5 |
+
|