Browse Source

Updated minify, jQuery, MixItUp and Tooltipster

pull/40/head
Jano Slota 10 years ago
committed by czaks
parent
commit
c25b8f01c5
  1. 226
      inc/lib/minify/JSMin.php
  2. 29
      inc/lib/minify/Minify.php
  3. 2
      inc/lib/minify/Minify/Build.php
  4. 22
      inc/lib/minify/Minify/CSS.php
  5. 11
      inc/lib/minify/Minify/CSS/UriRewriter.php
  6. 4
      inc/lib/minify/Minify/Cache/File.php
  7. 28
      inc/lib/minify/Minify/Controller/Base.php
  8. 2
      inc/lib/minify/Minify/Controller/Files.php
  9. 2
      inc/lib/minify/Minify/Controller/Groups.php
  10. 19
      inc/lib/minify/Minify/Controller/MinApp.php
  11. 19
      inc/lib/minify/Minify/Controller/Page.php
  12. 11
      inc/lib/minify/Minify/Controller/Version1.php
  13. 53
      inc/lib/minify/Minify/HTML.php
  14. 54
      inc/lib/minify/Minify/HTML/Helper.php
  15. 179
      inc/lib/minify/Minify/JS/ClosureCompiler.php
  16. 10
      inc/lib/minify/Minify/Lines.php
  17. 20
      inc/lib/minify/Minify/YUICompressor.php
  18. 33
      inc/lib/minify/MrClay/Cli.php
  19. 6
      inc/lib/minify/MrClay/Cli/Arg.php
  20. 8
      js/jquery.min.js
  21. 57
      js/jquery.mixitup.min.js
  22. 2
      js/jquery.tooltipster.min.js

226
inc/lib/minify/JSMin.php

@ -7,14 +7,14 @@
* </code> * </code>
* *
* This is a modified port of jsmin.c. Improvements: * This is a modified port of jsmin.c. Improvements:
* *
* Does not choke on some regexp literals containing quote characters. E.g. /'/ * Does not choke on some regexp literals containing quote characters. E.g. /'/
* *
* Spaces are preserved after some add/sub operators, so they are not mistakenly * Spaces are preserved after some add/sub operators, so they are not mistakenly
* converted to post-inc/dec. E.g. a + ++b -> a+ ++b * converted to post-inc/dec. E.g. a + ++b -> a+ ++b
* *
* Preserves multi-line comments that begin with /*! * Preserves multi-line comments that begin with /*!
* *
* PHP 5 or higher is required. * PHP 5 or higher is required.
* *
* Permission is hereby granted to use this version of the library under the * Permission is hereby granted to use this version of the library under the
@ -69,6 +69,7 @@ class JSMin {
protected $lookAhead = null; protected $lookAhead = null;
protected $output = ''; protected $output = '';
protected $lastByteOut = ''; protected $lastByteOut = '';
protected $keptComment = '';
/** /**
* Minify Javascript. * Minify Javascript.
@ -116,8 +117,8 @@ class JSMin {
// determine next command // determine next command
$command = self::ACTION_KEEP_A; // default $command = self::ACTION_KEEP_A; // default
if ($this->a === ' ') { if ($this->a === ' ') {
if (($this->lastByteOut === '+' || $this->lastByteOut === '-') if (($this->lastByteOut === '+' || $this->lastByteOut === '-')
&& ($this->b === $this->lastByteOut)) { && ($this->b === $this->lastByteOut)) {
// Don't delete this space. If we do, the addition/subtraction // Don't delete this space. If we do, the addition/subtraction
// could be parsed as a post-increment // could be parsed as a post-increment
} elseif (! $this->isAlphaNum($this->b)) { } elseif (! $this->isAlphaNum($this->b)) {
@ -126,16 +127,17 @@ class JSMin {
} elseif ($this->a === "\n") { } elseif ($this->a === "\n") {
if ($this->b === ' ') { if ($this->b === ' ') {
$command = self::ACTION_DELETE_A_B; $command = self::ACTION_DELETE_A_B;
// in case of mbstring.func_overload & 2, must check for null b,
// otherwise mb_strpos will give WARNING // in case of mbstring.func_overload & 2, must check for null b,
// otherwise mb_strpos will give WARNING
} elseif ($this->b === null } elseif ($this->b === null
|| (false === strpos('{[(+-', $this->b) || (false === strpos('{[(+-!~', $this->b)
&& ! $this->isAlphaNum($this->b))) { && ! $this->isAlphaNum($this->b))) {
$command = self::ACTION_DELETE_A; $command = self::ACTION_DELETE_A;
} }
} elseif (! $this->isAlphaNum($this->a)) { } elseif (! $this->isAlphaNum($this->a)) {
if ($this->b === ' ' if ($this->b === ' '
|| ($this->b === "\n" || ($this->b === "\n"
&& (false === strpos('}])+-"\'', $this->a)))) { && (false === strpos('}])+-"\'', $this->a)))) {
$command = self::ACTION_DELETE_A_B; $command = self::ACTION_DELETE_A_B;
} }
@ -160,7 +162,8 @@ class JSMin {
*/ */
protected function action($command) protected function action($command)
{ {
if ($command === self::ACTION_DELETE_A_B // make sure we don't compress "a + ++b" to "a+++b", etc.
if ($command === self::ACTION_DELETE_A_B
&& $this->b === ' ' && $this->b === ' '
&& ($this->a === '+' || $this->a === '-')) { && ($this->a === '+' || $this->a === '-')) {
// Note: we're at an addition/substraction operator; the inputIndex // Note: we're at an addition/substraction operator; the inputIndex
@ -170,58 +173,88 @@ class JSMin {
$command = self::ACTION_KEEP_A; $command = self::ACTION_KEEP_A;
} }
} }
switch ($command) { switch ($command) {
case self::ACTION_KEEP_A: case self::ACTION_KEEP_A: // 1
$this->output .= $this->a; $this->output .= $this->a;
if ($this->keptComment) {
$this->output = rtrim($this->output, "\n");
$this->output .= $this->keptComment;
$this->keptComment = '';
}
$this->lastByteOut = $this->a; $this->lastByteOut = $this->a;
// fallthrough // fallthrough intentional
case self::ACTION_DELETE_A: case self::ACTION_DELETE_A: // 2
$this->a = $this->b; $this->a = $this->b;
if ($this->a === "'" || $this->a === '"') { // string literal if ($this->a === "'" || $this->a === '"') { // string literal
$str = $this->a; // in case needed for exception $str = $this->a; // in case needed for exception
while (true) { for(;;) {
$this->output .= $this->a; $this->output .= $this->a;
$this->lastByteOut = $this->a; $this->lastByteOut = $this->a;
$this->a = $this->get(); $this->a = $this->get();
if ($this->a === $this->b) { // end quote if ($this->a === $this->b) { // end quote
break; break;
} }
if (ord($this->a) <= self::ORD_LF) { if ($this->isEOF($this->a)) {
$byte = $this->inputIndex - 1;
throw new JSMin_UnterminatedStringException( throw new JSMin_UnterminatedStringException(
"JSMin: Unterminated String at byte " "JSMin: Unterminated String at byte {$byte}: {$str}");
. $this->inputIndex . ": {$str}");
} }
$str .= $this->a; $str .= $this->a;
if ($this->a === '\\') { if ($this->a === '\\') {
$this->output .= $this->a; $this->output .= $this->a;
$this->lastByteOut = $this->a; $this->lastByteOut = $this->a;
$this->a = $this->get(); $this->a = $this->get();
$str .= $this->a; $str .= $this->a;
} }
} }
} }
// fallthrough
case self::ACTION_DELETE_A_B: // fallthrough intentional
case self::ACTION_DELETE_A_B: // 3
$this->b = $this->next(); $this->b = $this->next();
if ($this->b === '/' && $this->isRegexpLiteral()) { // RegExp literal if ($this->b === '/' && $this->isRegexpLiteral()) {
$this->output .= $this->a . $this->b; $this->output .= $this->a . $this->b;
$pattern = '/'; // in case needed for exception $pattern = '/'; // keep entire pattern in case we need to report it in the exception
while (true) { for(;;) {
$this->a = $this->get(); $this->a = $this->get();
$pattern .= $this->a; $pattern .= $this->a;
if ($this->a === '[') {
for(;;) {
$this->output .= $this->a;
$this->a = $this->get();
$pattern .= $this->a;
if ($this->a === ']') {
break;
}
if ($this->a === '\\') {
$this->output .= $this->a;
$this->a = $this->get();
$pattern .= $this->a;
}
if ($this->isEOF($this->a)) {
throw new JSMin_UnterminatedRegExpException(
"JSMin: Unterminated set in RegExp at byte "
. $this->inputIndex .": {$pattern}");
}
}
}
if ($this->a === '/') { // end pattern if ($this->a === '/') { // end pattern
break; // while (true) break; // while (true)
} elseif ($this->a === '\\') { } elseif ($this->a === '\\') {
$this->output .= $this->a; $this->output .= $this->a;
$this->a = $this->get(); $this->a = $this->get();
$pattern .= $this->a; $pattern .= $this->a;
} elseif (ord($this->a) <= self::ORD_LF) { } elseif ($this->isEOF($this->a)) {
$byte = $this->inputIndex - 1;
throw new JSMin_UnterminatedRegExpException( throw new JSMin_UnterminatedRegExpException(
"JSMin: Unterminated RegExp at byte " "JSMin: Unterminated RegExp at byte {$byte}: {$pattern}");
. $this->inputIndex .": {$pattern}");
} }
$this->output .= $this->a; $this->output .= $this->a;
$this->lastByteOut = $this->a; $this->lastByteOut = $this->a;
@ -237,31 +270,43 @@ class JSMin {
*/ */
protected function isRegexpLiteral() protected function isRegexpLiteral()
{ {
if (false !== strpos("\n{;(,=:[!&|?", $this->a)) { // we aren't dividing if (false !== strpos("(,=:[!&|?+-~*{;", $this->a)) {
// we obviously aren't dividing
return true; return true;
} }
if (' ' === $this->a) {
$length = strlen($this->output); // we have to check for a preceding keyword, and we don't need to pattern
if ($length < 2) { // weird edge case // match over the whole output.
return true; $recentOutput = substr($this->output, -10);
// check if return/typeof directly precede a pattern without a space
foreach (array('return', 'typeof') as $keyword) {
if ($this->a !== substr($keyword, -1)) {
// certainly wasn't keyword
continue;
} }
// you can't divide a keyword if (preg_match("~(^|[\\s\\S])" . substr($keyword, 0, -1) . "$~", $recentOutput, $m)) {
if (preg_match('/(?:case|else|in|return|typeof)$/', $this->output, $m)) { if ($m[1] === '' || !$this->isAlphaNum($m[1])) {
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 true;
} }
} }
} }
// check all keywords
if ($this->a === ' ' || $this->a === "\n") {
if (preg_match('~(^|[\\s\\S])(?:case|else|in|return|typeof)$~', $recentOutput, $m)) {
if ($m[1] === '' || !$this->isAlphaNum($m[1])) {
return true;
}
}
}
return false; return false;
} }
/** /**
* Get next char. Convert ctrl char to space. * Return the next character from stdin. Watch out for lookahead. If the character is a control character,
* translate it to a space or linefeed.
* *
* @return string * @return string
*/ */
@ -270,24 +315,36 @@ class JSMin {
$c = $this->lookAhead; $c = $this->lookAhead;
$this->lookAhead = null; $this->lookAhead = null;
if ($c === null) { if ($c === null) {
// getc(stdin)
if ($this->inputIndex < $this->inputLength) { if ($this->inputIndex < $this->inputLength) {
$c = $this->input[$this->inputIndex]; $c = $this->input[$this->inputIndex];
$this->inputIndex += 1; $this->inputIndex += 1;
} else { } else {
return null; $c = null;
} }
} }
if ($c === "\r" || $c === "\n") { if (ord($c) >= self::ORD_SPACE || $c === "\n" || $c === null) {
return "\n"; return $c;
} }
if (ord($c) < self::ORD_SPACE) { // control char if ($c === "\r") {
return ' '; return "\n";
} }
return $c; return ' ';
}
/**
* Does $a indicate end of input?
*
* @param string $a
* @return bool
*/
protected function isEOF($a)
{
return ord($a) <= self::ORD_LF;
} }
/** /**
* Get next char. If is ctrl character, translate to a space or newline. * Get next char (without getting it). If is ctrl character, translate to a space or newline.
* *
* @return string * @return string
*/ */
@ -298,7 +355,7 @@ class JSMin {
} }
/** /**
* Is $c a letter, digit, underscore, dollar sign, escape, or non-ASCII? * Return true if the character is a letter, digit, underscore, dollar sign, or non-ASCII character.
* *
* @param string $c * @param string $c
* *
@ -306,77 +363,84 @@ class JSMin {
*/ */
protected function isAlphaNum($c) protected function isAlphaNum($c)
{ {
return (preg_match('/^[0-9a-zA-Z_\\$\\\\]$/', $c) || ord($c) > 126); return (preg_match('/^[a-z0-9A-Z_\\$\\\\]$/', $c) || ord($c) > 126);
} }
/** /**
* @return string * Consume a single line comment from input (possibly retaining it)
*/ */
protected function singleLineComment() protected function consumeSingleLineComment()
{ {
$comment = ''; $comment = '';
while (true) { while (true) {
$get = $this->get(); $get = $this->get();
$comment .= $get; $comment .= $get;
if (ord($get) <= self::ORD_LF) { // EOL reached if (ord($get) <= self::ORD_LF) { // end of line reached
// if IE conditional comment // if IE conditional comment
if (preg_match('/^\\/@(?:cc_on|if|elif|else|end)\\b/', $comment)) { if (preg_match('/^\\/@(?:cc_on|if|elif|else|end)\\b/', $comment)) {
return "/{$comment}"; $this->keptComment .= "/{$comment}";
} }
return $get; return;
} }
} }
} }
/** /**
* @return string * Consume a multiple line comment from input (possibly retaining it)
*
* @throws JSMin_UnterminatedCommentException * @throws JSMin_UnterminatedCommentException
*/ */
protected function multipleLineComment() protected function consumeMultipleLineComment()
{ {
$this->get(); $this->get();
$comment = ''; $comment = '';
while (true) { for(;;) {
$get = $this->get(); $get = $this->get();
if ($get === '*') { if ($get === '*') {
if ($this->peek() === '/') { // end of comment reached if ($this->peek() === '/') { // end of comment reached
$this->get(); $this->get();
// if comment preserved by YUI Compressor
if (0 === strpos($comment, '!')) { if (0 === strpos($comment, '!')) {
return "\n/*!" . substr($comment, 1) . "*/\n"; // preserved by YUI Compressor
} if (!$this->keptComment) {
// if IE conditional comment // don't prepend a newline if two comments right after one another
if (preg_match('/^@(?:cc_on|if|elif|else|end)\\b/', $comment)) { $this->keptComment = "\n";
return "/*{$comment}*/"; }
$this->keptComment .= "/*!" . substr($comment, 1) . "*/\n";
} else if (preg_match('/^@(?:cc_on|if|elif|else|end)\\b/', $comment)) {
// IE conditional
$this->keptComment .= "/*{$comment}*/";
} }
return ' '; return;
} }
} elseif ($get === null) { } elseif ($get === null) {
throw new JSMin_UnterminatedCommentException( throw new JSMin_UnterminatedCommentException(
"JSMin: Unterminated comment at byte " "JSMin: Unterminated comment at byte {$this->inputIndex}: /*{$comment}");
. $this->inputIndex . ": /*{$comment}");
} }
$comment .= $get; $comment .= $get;
} }
} }
/** /**
* Get the next character, skipping over comments. * Get the next character, skipping over comments. Some comments may be preserved.
* Some comments may be preserved.
* *
* @return string * @return string
*/ */
protected function next() protected function next()
{ {
$get = $this->get(); $get = $this->get();
if ($get !== '/') { if ($get === '/') {
return $get; switch ($this->peek()) {
} case '/':
switch ($this->peek()) { $this->consumeSingleLineComment();
case '/': return $this->singleLineComment(); $get = "\n";
case '*': return $this->multipleLineComment(); break;
default: return $get; case '*':
$this->consumeMultipleLineComment();
$get = ' ';
break;
}
} }
return $get;
} }
} }

29
inc/lib/minify/Minify.php

@ -3,11 +3,6 @@
* Class Minify * Class Minify
* @package Minify * @package Minify
*/ */
/**
* Minify_Source
*/
require_once 'Minify/Source.php';
/** /**
* Minify - Combines, minifies, and caches JavaScript and CSS files on demand. * Minify - Combines, minifies, and caches JavaScript and CSS files on demand.
@ -29,7 +24,7 @@ require_once 'Minify/Source.php';
*/ */
class Minify { class Minify {
const VERSION = '2.1.5'; const VERSION = '2.2.0';
const TYPE_CSS = 'text/css'; const TYPE_CSS = 'text/css';
const TYPE_HTML = 'text/html'; const TYPE_HTML = 'text/html';
// there is some debate over the ideal JS Content-Type, but this is the // there is some debate over the ideal JS Content-Type, but this is the
@ -85,7 +80,6 @@ class Minify {
public static function setCache($cache = '', $fileLocking = true) public static function setCache($cache = '', $fileLocking = true)
{ {
if (is_string($cache)) { if (is_string($cache)) {
require_once 'Minify/Cache/File.php';
self::$_cache = new Minify_Cache_File($cache, $fileLocking); self::$_cache = new Minify_Cache_File($cache, $fileLocking);
} else { } else {
self::$_cache = $cache; self::$_cache = $cache;
@ -161,9 +155,11 @@ class Minify {
* *
* @param array $options controller/serve options * @param array $options controller/serve options
* *
* @return mixed null, or, if the 'quiet' option is set to true, an array * @return null|array if the 'quiet' option is set to true, an array
* with keys "success" (bool), "statusCode" (int), "content" (string), and * with keys "success" (bool), "statusCode" (int), "content" (string), and
* "headers" (array). * "headers" (array).
*
* @throws Exception
*/ */
public static function serve($controller, $options = array()) public static function serve($controller, $options = array())
{ {
@ -174,10 +170,6 @@ class Minify {
if (is_string($controller)) { if (is_string($controller)) {
// make $controller into object // make $controller into object
$class = 'Minify_Controller_' . $controller; $class = 'Minify_Controller_' . $controller;
if (! class_exists($class, false)) {
require_once "Minify/Controller/"
. str_replace('_', '/', $controller) . ".php";
}
$controller = new $class(); $controller = new $class();
/* @var Minify_Controller_Base $controller */ /* @var Minify_Controller_Base $controller */
} }
@ -219,8 +211,7 @@ class Minify {
$contentEncoding = self::$_options['encodeMethod']; $contentEncoding = self::$_options['encodeMethod'];
} else { } else {
// sniff request header // sniff request header
require_once 'HTTP/Encoder.php'; // depending on what the client accepts, $contentEncoding may be
// depending on what the client accepts, $contentEncoding may be
// 'x-gzip' while our internal encodeMethod is 'gzip'. Calling // 'x-gzip' while our internal encodeMethod is 'gzip'. Calling
// getAcceptedEncoding(false, false) leaves out compress and deflate as options. // getAcceptedEncoding(false, false) leaves out compress and deflate as options.
list(self::$_options['encodeMethod'], $contentEncoding) = HTTP_Encoder::getAcceptedEncoding(false, false); list(self::$_options['encodeMethod'], $contentEncoding) = HTTP_Encoder::getAcceptedEncoding(false, false);
@ -231,7 +222,6 @@ class Minify {
} }
// check client cache // check client cache
require_once 'HTTP/ConditionalGet.php';
$cgOptions = array( $cgOptions = array(
'lastModifiedTime' => self::$_options['lastModifiedTime'] 'lastModifiedTime' => self::$_options['lastModifiedTime']
,'isPublic' => self::$_options['isPublic'] ,'isPublic' => self::$_options['isPublic']
@ -300,7 +290,7 @@ class Minify {
throw $e; throw $e;
} }
self::$_cache->store($cacheId, $content); self::$_cache->store($cacheId, $content);
if (function_exists('gzencode')) { if (function_exists('gzencode') && self::$_options['encodeMethod']) {
self::$_cache->store($cacheId . '.gz', gzencode($content, self::$_options['encodeLevel'])); self::$_cache->store($cacheId . '.gz', gzencode($content, self::$_options['encodeLevel']));
} }
} }
@ -451,7 +441,7 @@ class Minify {
/** /**
* Set up sources to use Minify_Lines * Set up sources to use Minify_Lines
* *
* @param array $sources Minify_Source instances * @param Minify_Source[] $sources Minify_Source instances
*/ */
protected static function _setupDebug($sources) protected static function _setupDebug($sources)
{ {
@ -468,6 +458,8 @@ class Minify {
* Combines sources and minifies the result. * Combines sources and minifies the result.
* *
* @return string * @return string
*
* @throws Exception
*/ */
protected static function _combineMinify() protected static function _combineMinify()
{ {
@ -526,7 +518,6 @@ class Minify {
$imploded = implode($implodeSeparator, $groupToProcessTogether); $imploded = implode($implodeSeparator, $groupToProcessTogether);
$groupToProcessTogether = array(); $groupToProcessTogether = array();
if ($lastMinifier) { if ($lastMinifier) {
self::$_controller->loadMinifier($lastMinifier);
try { try {
$content[] = call_user_func($lastMinifier, $imploded, $lastOptions); $content[] = call_user_func($lastMinifier, $imploded, $lastOptions);
} catch (Exception $e) { } catch (Exception $e) {
@ -574,7 +565,7 @@ class Minify {
{ {
$name = preg_replace('/[^a-zA-Z0-9\\.=_,]/', '', self::$_controller->selectionId); $name = preg_replace('/[^a-zA-Z0-9\\.=_,]/', '', self::$_controller->selectionId);
$name = preg_replace('/\\.+/', '.', $name); $name = preg_replace('/\\.+/', '.', $name);
$name = substr($name, 0, 200 - 34 - strlen($prefix)); $name = substr($name, 0, 100 - 34 - strlen($prefix));
$md5 = md5(serialize(array( $md5 = md5(serialize(array(
Minify_Source::getDigest(self::$_controller->sources) Minify_Source::getDigest(self::$_controller->sources)
,self::$_options['minifiers'] ,self::$_options['minifiers']

2
inc/lib/minify/Minify/Build.php

@ -4,8 +4,6 @@
* @package Minify * @package Minify
*/ */
require_once 'Minify/Source.php';
/** /**
* Maintain a single last modification time for a group of Minify sources to * Maintain a single last modification time for a group of Minify sources to
* allow use of far off Expires headers in Minify. * allow use of far off Expires headers in Minify.

22
inc/lib/minify/Minify/CSS.php

@ -56,6 +56,7 @@ class Minify_CSS {
public static function minify($css, $options = array()) public static function minify($css, $options = array())
{ {
$options = array_merge(array( $options = array_merge(array(
'compress' => true,
'removeCharsets' => true, 'removeCharsets' => true,
'preserveComments' => true, 'preserveComments' => true,
'currentDir' => null, 'currentDir' => null,
@ -67,21 +68,20 @@ class Minify_CSS {
if ($options['removeCharsets']) { if ($options['removeCharsets']) {
$css = preg_replace('/@charset[^;]+;\\s*/', '', $css); $css = preg_replace('/@charset[^;]+;\\s*/', '', $css);
} }
require_once 'Minify/CSS/Compressor.php'; if ($options['compress']) {
if (! $options['preserveComments']) { if (! $options['preserveComments']) {
$css = Minify_CSS_Compressor::process($css, $options); $css = Minify_CSS_Compressor::process($css, $options);
} else { } else {
require_once 'Minify/CommentPreserver.php'; $css = Minify_CommentPreserver::process(
$css = Minify_CommentPreserver::process( $css
$css ,array('Minify_CSS_Compressor', 'process')
,array('Minify_CSS_Compressor', 'process') ,array($options)
,array($options) );
); }
} }
if (! $options['currentDir'] && ! $options['prependRelativePath']) { if (! $options['currentDir'] && ! $options['prependRelativePath']) {
return $css; return $css;
} }
require_once 'Minify/CSS/UriRewriter.php';
if ($options['currentDir']) { if ($options['currentDir']) {
return Minify_CSS_UriRewriter::rewrite( return Minify_CSS_UriRewriter::rewrite(
$css $css

11
inc/lib/minify/Minify/CSS/UriRewriter.php

@ -70,7 +70,7 @@ class Minify_CSS_UriRewriter {
// rewrite // rewrite
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
,array(self::$className, '_processUriCB'), $css); ,array(self::$className, '_processUriCB'), $css);
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/' $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/'
,array(self::$className, '_processUriCB'), $css); ,array(self::$className, '_processUriCB'), $css);
return $css; return $css;
@ -94,7 +94,7 @@ class Minify_CSS_UriRewriter {
// append // append
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
,array(self::$className, '_processUriCB'), $css); ,array(self::$className, '_processUriCB'), $css);
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/' $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/'
,array(self::$className, '_processUriCB'), $css); ,array(self::$className, '_processUriCB'), $css);
self::$_prependPath = null; self::$_prependPath = null;
@ -282,11 +282,8 @@ class Minify_CSS_UriRewriter {
? $m[1] ? $m[1]
: substr($m[1], 1, strlen($m[1]) - 2); : substr($m[1], 1, strlen($m[1]) - 2);
} }
// analyze URI // if not root/scheme relative and not starts with scheme
if ('/' !== $uri[0] // root-relative if (!preg_match('~^(/|[a-z]+\:)~', $uri)) {
&& false === strpos($uri, '//') // protocol (non-data)
&& 0 !== strpos($uri, 'data:') // data protocol
) {
// URI is file-relative: rewrite depending on options // URI is file-relative: rewrite depending on options
if (self::$_prependPath === null) { if (self::$_prependPath === null) {
$uri = self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks); $uri = self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks);

4
inc/lib/minify/Minify/Cache/File.php

@ -98,6 +98,9 @@ class Minify_Cache_File {
{ {
if ($this->_locking) { if ($this->_locking) {
$fp = fopen($this->_path . '/' . $id, 'rb'); $fp = fopen($this->_path . '/' . $id, 'rb');
if (!$fp) {
return false;
}
flock($fp, LOCK_SH); flock($fp, LOCK_SH);
$ret = stream_get_contents($fp); $ret = stream_get_contents($fp);
flock($fp, LOCK_UN); flock($fp, LOCK_UN);
@ -186,7 +189,6 @@ class Minify_Cache_File {
*/ */
protected function _log($msg) protected function _log($msg)
{ {
require_once 'Minify/Logger.php';
Minify_Logger::log($msg); Minify_Logger::log($msg);
} }

28
inc/lib/minify/Minify/Controller/Base.php

@ -78,33 +78,6 @@ abstract class Minify_Controller_Base {
return $ret; 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)
{
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, * Is a user-given file within an allowable directory, existing,
* and having an extension js/css/html/txt ? * and having an extension js/css/html/txt ?
@ -244,7 +217,6 @@ abstract class Minify_Controller_Base {
* @return null * @return null
*/ */
public function log($msg) { public function log($msg) {
require_once 'Minify/Logger.php';
Minify_Logger::log($msg); Minify_Logger::log($msg);
} }
} }

2
inc/lib/minify/Minify/Controller/Files.php

@ -4,8 +4,6 @@
* @package Minify * @package Minify
*/ */
require_once 'Minify/Controller/Base.php';
/** /**
* Controller class for minifying a set of files * Controller class for minifying a set of files
* *

2
inc/lib/minify/Minify/Controller/Groups.php

@ -4,8 +4,6 @@
* @package Minify * @package Minify
*/ */
require_once 'Minify/Controller/Base.php';
/** /**
* Controller class for serving predetermined groups of minimized sets, selected * Controller class for serving predetermined groups of minimized sets, selected
* by PATH_INFO * by PATH_INFO

19
inc/lib/minify/Minify/Controller/MinApp.php

@ -4,8 +4,6 @@
* @package Minify * @package Minify
*/ */
require_once 'Minify/Controller/Base.php';
/** /**
* Controller class for requests to /min/index.php * Controller class for requests to /min/index.php
* *
@ -22,6 +20,13 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
* @return array Minify options * @return array Minify options
*/ */
public function setupSources($options) { public function setupSources($options) {
// PHP insecure by default: realpath() and other FS functions can't handle null bytes.
foreach (array('g', 'b', 'f') as $key) {
if (isset($_GET[$key])) {
$_GET[$key] = str_replace("\x00", '', (string)$_GET[$key]);
}
}
// filter controller options // filter controller options
$cOptions = array_merge( $cOptions = array_merge(
array( array(
@ -36,7 +41,6 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
$sources = array(); $sources = array();
$this->selectionId = ''; $this->selectionId = '';
$firstMissingResource = null; $firstMissingResource = null;
if (isset($_GET['g'])) { if (isset($_GET['g'])) {
// add group(s) // add group(s)
$this->selectionId .= 'g=' . $_GET['g']; $this->selectionId .= 'g=' . $_GET['g'];
@ -195,9 +199,12 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
protected function _getFileSource($file, $cOptions) protected function _getFileSource($file, $cOptions)
{ {
$spec['filepath'] = $file; $spec['filepath'] = $file;
if ($cOptions['noMinPattern'] if ($cOptions['noMinPattern'] && preg_match($cOptions['noMinPattern'], basename($file))) {
&& preg_match($cOptions['noMinPattern'], basename($file))) { if (preg_match('~\.css$~i', $file)) {
$spec['minifier'] = ''; $spec['minifyOptions']['compress'] = false;
} else {
$spec['minifier'] = '';
}
} }
return new Minify_Source($spec); return new Minify_Source($spec);
} }

19
inc/lib/minify/Minify/Controller/Page.php

@ -4,8 +4,6 @@
* @package Minify * @package Minify
*/ */
require_once 'Minify/Controller/Base.php';
/** /**
* Controller class for serving a single HTML page * Controller class for serving a single HTML page
* *
@ -59,7 +57,6 @@ class Minify_Controller_Page extends Minify_Controller_Base {
'cssMinifier' => array('Minify_CSS', 'minify') 'cssMinifier' => array('Minify_CSS', 'minify')
,'jsMinifier' => array('JSMin', 'minify') ,'jsMinifier' => array('JSMin', 'minify')
); );
$this->_loadCssJsMinifiers = true;
unset($options['minifyAll']); unset($options['minifyAll']);
} }
$this->sources[] = new Minify_Source($sourceSpec); $this->sources[] = new Minify_Source($sourceSpec);
@ -67,21 +64,5 @@ class Minify_Controller_Page extends Minify_Controller_Base {
$options['contentType'] = Minify::TYPE_HTML; $options['contentType'] = Minify::TYPE_HTML;
return $options; 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.
require_once 'Minify/CSS.php';
require_once 'JSMin.php';
}
parent::loadMinifier($minifierCallback); // load Minify/HTML.php
}
} }

11
inc/lib/minify/Minify/Controller/Version1.php

@ -4,8 +4,6 @@
* @package Minify * @package Minify
*/ */
require_once 'Minify/Controller/Base.php';
/** /**
* Controller class for emulating version 1 of minify.php (mostly a proof-of-concept) * Controller class for emulating version 1 of minify.php (mostly a proof-of-concept)
* *
@ -26,6 +24,11 @@ class Minify_Controller_Version1 extends Minify_Controller_Base {
* *
*/ */
public function setupSources($options) { public function setupSources($options) {
// PHP insecure by default: realpath() and other FS functions can't handle null bytes.
if (isset($_GET['files'])) {
$_GET['files'] = str_replace("\x00", '', (string)$_GET['files']);
}
self::_setupDefines(); self::_setupDefines();
if (MINIFY_USE_CACHE) { if (MINIFY_USE_CACHE) {
$cacheDir = defined('MINIFY_CACHE_DIR') $cacheDir = defined('MINIFY_CACHE_DIR')
@ -51,8 +54,7 @@ class Minify_Controller_Version1 extends Minify_Controller_Base {
) { ) {
return $options; return $options;
} }
$extension = $m[1];
$files = explode(',', $_GET['files']); $files = explode(',', $_GET['files']);
if (count($files) > MINIFY_MAX_FILES) { if (count($files) > MINIFY_MAX_FILES) {
return $options; return $options;
@ -63,7 +65,6 @@ class Minify_Controller_Version1 extends Minify_Controller_Base {
. DIRECTORY_SEPARATOR; . DIRECTORY_SEPARATOR;
$prependAbsPaths = $_SERVER['DOCUMENT_ROOT']; $prependAbsPaths = $_SERVER['DOCUMENT_ROOT'];
$sources = array();
$goodFiles = array(); $goodFiles = array();
$hasBadSource = false; $hasBadSource = false;

53
inc/lib/minify/Minify/HTML.php

@ -1,22 +1,26 @@
<?php <?php
/** /**
* Class Minify_HTML * Class Minify_HTML
* @package Minify * @package Minify
*/ */
/** /**
* Compress HTML * Compress HTML
* *
* This is a heavy regex-based removal of whitespace, unnecessary comments and * This is a heavy regex-based removal of whitespace, unnecessary comments and
* tokens. IE conditional comments are preserved. There are also options to have * tokens. IE conditional comments are preserved. There are also options to have
* STYLE and SCRIPT blocks compressed by callback functions. * STYLE and SCRIPT blocks compressed by callback functions.
* *
* A test suite is available. * A test suite is available.
* *
* @package Minify * @package Minify
* @author Stephen Clay <steve@mrclay.org> * @author Stephen Clay <steve@mrclay.org>
*/ */
class Minify_HTML { class Minify_HTML {
/**
* @var boolean
*/
protected $_jsCleanComments = true;
/** /**
* "Minify" an HTML page * "Minify" an HTML page
@ -27,21 +31,21 @@ class Minify_HTML {
* *
* 'cssMinifier' : (optional) callback function to process content of STYLE * 'cssMinifier' : (optional) callback function to process content of STYLE
* elements. * elements.
* *
* 'jsMinifier' : (optional) callback function to process content of SCRIPT * 'jsMinifier' : (optional) callback function to process content of SCRIPT
* elements. Note: the type attribute is ignored. * elements. Note: the type attribute is ignored.
* *
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
* unset, minify will sniff for an XHTML doctype. * unset, minify will sniff for an XHTML doctype.
* *
* @return string * @return string
*/ */
public static function minify($html, $options = array()) { public static function minify($html, $options = array()) {
$min = new Minify_HTML($html, $options); $min = new self($html, $options);
return $min->process(); return $min->process();
} }
/** /**
* Create a minifier object * Create a minifier object
* *
@ -51,14 +55,14 @@ class Minify_HTML {
* *
* 'cssMinifier' : (optional) callback function to process content of STYLE * 'cssMinifier' : (optional) callback function to process content of STYLE
* elements. * elements.
* *
* 'jsMinifier' : (optional) callback function to process content of SCRIPT * 'jsMinifier' : (optional) callback function to process content of SCRIPT
* elements. Note: the type attribute is ignored. * elements. Note: the type attribute is ignored.
* *
* 'jsCleanComments' : (optional) whether to remove HTML comments beginning and end of script block
*
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
* unset, minify will sniff for an XHTML doctype. * unset, minify will sniff for an XHTML doctype.
*
* @return null
*/ */
public function __construct($html, $options = array()) public function __construct($html, $options = array())
{ {
@ -72,9 +76,12 @@ class Minify_HTML {
if (isset($options['jsMinifier'])) { if (isset($options['jsMinifier'])) {
$this->_jsMinifier = $options['jsMinifier']; $this->_jsMinifier = $options['jsMinifier'];
} }
if (isset($options['jsCleanComments'])) {
$this->_jsCleanComments = (bool)$options['jsCleanComments'];
}
} }
/** /**
* Minify the markeup given in the constructor * Minify the markeup given in the constructor
* *
@ -124,7 +131,7 @@ class Minify_HTML {
// remove ws around block/undisplayed elements // remove ws around block/undisplayed elements
$this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body' $this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
.'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form' .'|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
.'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta' .'|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)' .'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
.'|ul)\\b[^>]*>)/i', '$1', $this->_html); .'|ul)\\b[^>]*>)/i', '$1', $this->_html);
@ -213,17 +220,19 @@ class Minify_HTML {
// whitespace surrounding? preserve at least one space // whitespace surrounding? preserve at least one space
$ws1 = ($m[1] === '') ? '' : ' '; $ws1 = ($m[1] === '') ? '' : ' ';
$ws2 = ($m[4] === '') ? '' : ' '; $ws2 = ($m[4] === '') ? '' : ' ';
// remove HTML comments (and ending "//" if present) // remove HTML comments (and ending "//" if present)
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js); if ($this->_jsCleanComments) {
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
}
// remove CDATA section markers // remove CDATA section markers
$js = $this->_removeCdata($js); $js = $this->_removeCdata($js);
// minify // minify
$minifier = $this->_jsMinifier $minifier = $this->_jsMinifier
? $this->_jsMinifier ? $this->_jsMinifier
: 'trim'; : 'trim';
$js = call_user_func($minifier, $js); $js = call_user_func($minifier, $js);
return $this->_reservePlace($this->_needsCdata($js) return $this->_reservePlace($this->_needsCdata($js)

54
inc/lib/minify/Minify/HTML/Helper.php

@ -15,10 +15,10 @@ class Minify_HTML_Helper {
public $minAppUri = '/min'; public $minAppUri = '/min';
public $groupsConfigFile = ''; public $groupsConfigFile = '';
/* /**
* Get an HTML-escaped Minify URI for a group or set of files * Get an HTML-escaped Minify URI for a group or set of files
* *
* @param mixed $keyOrFiles a group key or array of filepaths/URIs * @param string|array $keyOrFiles a group key or array of filepaths/URIs
* @param array $opts options: * @param array $opts options:
* 'farExpires' : (default true) append a modified timestamp for cache revving * 'farExpires' : (default true) append a modified timestamp for cache revving
* 'debug' : (default false) append debug flag * 'debug' : (default false) append debug flag
@ -51,8 +51,12 @@ class Minify_HTML_Helper {
return htmlspecialchars($uri, ENT_QUOTES, $opts['charset']); return htmlspecialchars($uri, ENT_QUOTES, $opts['charset']);
} }
/* /**
* Get non-HTML-escaped URI to minify the specified files * Get non-HTML-escaped URI to minify the specified files
*
* @param bool $farExpires
* @param bool $debug
* @return string
*/ */
public function getRawUri($farExpires = true, $debug = false) public function getRawUri($farExpires = true, $debug = false)
{ {
@ -74,6 +78,12 @@ class Minify_HTML_Helper {
return $path; return $path;
} }
/**
* Set the files that will comprise the URI we're building
*
* @param array $files
* @param bool $checkLastModified
*/
public function setFiles($files, $checkLastModified = true) public function setFiles($files, $checkLastModified = true)
{ {
$this->_groupKey = null; $this->_groupKey = null;
@ -94,6 +104,12 @@ class Minify_HTML_Helper {
$this->_filePaths = $files; $this->_filePaths = $files;
} }
/**
* Set the group of files that will comprise the URI we're building
*
* @param string $key
* @param bool $checkLastModified
*/
public function setGroup($key, $checkLastModified = true) public function setGroup($key, $checkLastModified = true)
{ {
$this->_groupKey = $key; $this->_groupKey = $key;
@ -103,13 +119,23 @@ class Minify_HTML_Helper {
} }
if (is_file($this->groupsConfigFile)) { if (is_file($this->groupsConfigFile)) {
$gc = (require $this->groupsConfigFile); $gc = (require $this->groupsConfigFile);
if (isset($gc[$key])) { $keys = explode(',', $key);
$this->_lastModified = self::getLastModified($gc[$key]); foreach ($keys as $key) {
if (isset($gc[$key])) {
$this->_lastModified = self::getLastModified($gc[$key], $this->_lastModified);
}
} }
} }
} }
} }
/**
* Get the max(lastModified) of all files
*
* @param array|string $sources
* @param int $lastModified
* @return int
*/
public static function getLastModified($sources, $lastModified = 0) public static function getLastModified($sources, $lastModified = 0)
{ {
$max = $lastModified; $max = $lastModified;
@ -142,13 +168,19 @@ class Minify_HTML_Helper {
* @return mixed a common char or '' if any do not match * @return mixed a common char or '' if any do not match
*/ */
protected static function _getCommonCharAtPos($arr, $pos) { protected static function _getCommonCharAtPos($arr, $pos) {
$l = count($arr); if (!isset($arr[0][$pos])) {
return '';
}
$c = $arr[0][$pos]; $c = $arr[0][$pos];
if ($c === '' || $l === 1) $l = count($arr);
if ($l === 1) {
return $c; return $c;
for ($i = 1; $i < $l; ++$i) }
if ($arr[$i][$pos] !== $c) for ($i = 1; $i < $l; ++$i) {
if ($arr[$i][$pos] !== $c) {
return ''; return '';
}
}
return $c; return $c;
} }
@ -157,11 +189,11 @@ class Minify_HTML_Helper {
* *
* @param array $paths root-relative URIs of files * @param array $paths root-relative URIs of files
* @param string $minRoot root-relative URI of the "min" application * @param string $minRoot root-relative URI of the "min" application
* @return string
*/ */
protected static function _getShortestUri($paths, $minRoot = '/min/') { protected static function _getShortestUri($paths, $minRoot = '/min/') {
$pos = 0; $pos = 0;
$base = ''; $base = '';
$c;
while (true) { while (true) {
$c = self::_getCommonCharAtPos($paths, $pos); $c = self::_getCommonCharAtPos($paths, $pos);
if ($c === '') { if ($c === '') {

179
inc/lib/minify/Minify/JS/ClosureCompiler.php

@ -14,13 +14,68 @@
* @todo can use a stream wrapper to unit test this? * @todo can use a stream wrapper to unit test this?
*/ */
class Minify_JS_ClosureCompiler { class Minify_JS_ClosureCompiler {
const URL = 'http://closure-compiler.appspot.com/compile';
/** /**
* Minify Javascript code via HTTP request to the Closure Compiler API * @var string The option key for the maximum POST byte size
*/
const OPTION_MAX_BYTES = 'maxBytes';
/**
* @var string The option key for additional params. @see __construct
*/
const OPTION_ADDITIONAL_OPTIONS = 'additionalParams';
/**
* @var string The option key for the fallback Minifier
*/
const OPTION_FALLBACK_FUNCTION = 'fallbackFunc';
/**
* @var string The option key for the service URL
*/
const OPTION_COMPILER_URL = 'compilerUrl';
/**
* @var int The default maximum POST byte size according to https://developers.google.com/closure/compiler/docs/api-ref
*/
const DEFAULT_MAX_BYTES = 200000;
/**
* @var string[] $DEFAULT_OPTIONS The default options to pass to the compiler service
*
* @note This would be a constant if PHP allowed it
*/
private static $DEFAULT_OPTIONS = array(
'output_format' => 'text',
'compilation_level' => 'SIMPLE_OPTIMIZATIONS'
);
/**
* @var string $url URL of compiler server. defaults to Google's
*/
protected $serviceUrl = 'http://closure-compiler.appspot.com/compile';
/**
* @var int $maxBytes The maximum JS size that can be sent to the compiler server in bytes
*/
protected $maxBytes = self::DEFAULT_MAX_BYTES;
/**
* @var string[] $additionalOptions Additional options to pass to the compiler service
*/
protected $additionalOptions = array();
/**
* @var callable Function to minify JS if service fails. Default is JSMin
*/
protected $fallbackMinifier = array('JSMin', 'minify');
/**
* Minify JavaScript code via HTTP request to a Closure Compiler API
* *
* @param string $js input code * @param string $js input code
* @param array $options unused at this point * @param array $options Options passed to __construct(). @see __construct
*
* @return string * @return string
*/ */
public static function minify($js, array $options = array()) public static function minify($js, array $options = array())
@ -30,63 +85,101 @@ class Minify_JS_ClosureCompiler {
} }
/** /**
* @param array $options Options with keys available below:
*
* fallbackFunc : (callable) function to minify if service unavailable. Default is JSMin.
* *
* @param array $options * compilerUrl : (string) URL to closure compiler server
* *
* fallbackFunc : default array($this, 'fallback'); * maxBytes : (int) The maximum amount of bytes to be sent as js_code in the POST request.
* Defaults to 200000.
*
* additionalParams : (string[]) Additional parameters to pass to the compiler server. Can be anything named
* in https://developers.google.com/closure/compiler/docs/api-ref except for js_code and
* output_info
*/ */
public function __construct(array $options = array()) public function __construct(array $options = array())
{ {
$this->_fallbackFunc = isset($options['fallbackMinifier']) if (isset($options[self::OPTION_FALLBACK_FUNCTION])) {
? $options['fallbackMinifier'] $this->fallbackMinifier = $options[self::OPTION_FALLBACK_FUNCTION];
: array($this, '_fallback'); }
if (isset($options[self::OPTION_COMPILER_URL])) {
$this->serviceUrl = $options[self::OPTION_COMPILER_URL];
}
if (isset($options[self::OPTION_ADDITIONAL_OPTIONS]) && is_array($options[self::OPTION_ADDITIONAL_OPTIONS])) {
$this->additionalOptions = $options[self::OPTION_ADDITIONAL_OPTIONS];
}
if (isset($options[self::OPTION_MAX_BYTES])) {
$this->maxBytes = (int) $options[self::OPTION_MAX_BYTES];
}
} }
/**
* Call the service to perform the minification
*
* @param string $js JavaScript code
* @return string
* @throws Minify_JS_ClosureCompiler_Exception
*/
public function min($js) public function min($js)
{ {
$postBody = $this->_buildPostBody($js); $postBody = $this->buildPostBody($js);
$bytes = (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2))
? mb_strlen($postBody, '8bit') if ($this->maxBytes > 0) {
: strlen($postBody); $bytes = (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2))
if ($bytes > 200000) { ? mb_strlen($postBody, '8bit')
throw new Minify_JS_ClosureCompiler_Exception( : strlen($postBody);
'POST content larger than 200000 bytes' if ($bytes > $this->maxBytes) {
); throw new Minify_JS_ClosureCompiler_Exception(
'POST content larger than ' . $this->maxBytes . ' bytes'
);
}
} }
$response = $this->_getResponse($postBody);
$response = $this->getResponse($postBody);
if (preg_match('/^Error\(\d\d?\):/', $response)) { if (preg_match('/^Error\(\d\d?\):/', $response)) {
if (is_callable($this->_fallbackFunc)) { if (is_callable($this->fallbackMinifier)) {
// use fallback
$response = "/* Received errors from Closure Compiler API:\n$response" $response = "/* Received errors from Closure Compiler API:\n$response"
. "\n(Using fallback minifier)\n*/\n"; . "\n(Using fallback minifier)\n*/\n";
$response .= call_user_func($this->_fallbackFunc, $js); $response .= call_user_func($this->fallbackMinifier, $js);
} else { } else {
throw new Minify_JS_ClosureCompiler_Exception($response); throw new Minify_JS_ClosureCompiler_Exception($response);
} }
} }
if ($response === '') { if ($response === '') {
$errors = $this->_getResponse($this->_buildPostBody($js, true)); $errors = $this->getResponse($this->buildPostBody($js, true));
throw new Minify_JS_ClosureCompiler_Exception($errors); throw new Minify_JS_ClosureCompiler_Exception($errors);
} }
return $response; return $response;
} }
protected $_fallbackFunc = null;
protected function _getResponse($postBody) /**
* Get the response for a given POST body
*
* @param string $postBody
* @return string
* @throws Minify_JS_ClosureCompiler_Exception
*/
protected function getResponse($postBody)
{ {
$allowUrlFopen = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen')); $allowUrlFopen = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
if ($allowUrlFopen) { if ($allowUrlFopen) {
$contents = file_get_contents(self::URL, false, stream_context_create(array( $contents = file_get_contents($this->serviceUrl, false, stream_context_create(array(
'http' => array( 'http' => array(
'method' => 'POST', 'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded', 'header' => "Content-type: application/x-www-form-urlencoded\r\nConnection: close\r\n",
'content' => $postBody, 'content' => $postBody,
'max_redirects' => 0, 'max_redirects' => 0,
'timeout' => 15, 'timeout' => 15,
) )
))); )));
} elseif (defined('CURLOPT_POST')) { } elseif (defined('CURLOPT_POST')) {
$ch = curl_init(self::URL); $ch = curl_init($this->serviceUrl);
curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded')); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
@ -100,33 +193,37 @@ class Minify_JS_ClosureCompiler {
"Could not make HTTP request: allow_url_open is false and cURL not available" "Could not make HTTP request: allow_url_open is false and cURL not available"
); );
} }
if (false === $contents) { if (false === $contents) {
throw new Minify_JS_ClosureCompiler_Exception( throw new Minify_JS_ClosureCompiler_Exception(
"No HTTP response from server" "No HTTP response from server"
); );
} }
return trim($contents);
}
protected function _buildPostBody($js, $returnErrors = false) return trim($contents);
{
return http_build_query(array(
'js_code' => $js,
'output_info' => ($returnErrors ? 'errors' : 'compiled_code'),
'output_format' => 'text',
'compilation_level' => 'SIMPLE_OPTIMIZATIONS'
), null, '&');
} }
/** /**
* Default fallback function if CC API fails * Build a POST request body
* @param string $js *
* @param string $js JavaScript code
* @param bool $returnErrors
* @return string * @return string
*/ */
protected function _fallback($js) protected function buildPostBody($js, $returnErrors = false)
{ {
require_once 'JSMin.php'; return http_build_query(
return JSMin::minify($js); array_merge(
self::$DEFAULT_OPTIONS,
$this->additionalOptions,
array(
'js_code' => $js,
'output_info' => ($returnErrors ? 'errors' : 'compiled_code')
)
),
null,
'&'
);
} }
} }

10
inc/lib/minify/Minify/Lines.php

@ -55,7 +55,11 @@ class Minify_Lines {
$newLines = array(); $newLines = array();
while (null !== ($line = array_shift($lines))) { while (null !== ($line = array_shift($lines))) {
if (('' !== $id) && (0 == $i % 50)) { if (('' !== $id) && (0 == $i % 50)) {
array_push($newLines, '', "/* {$id} */", ''); if ($inComment) {
array_push($newLines, '', "/* {$id} *|", '');
} else {
array_push($newLines, '', "/* {$id} */", '');
}
} }
++$i; ++$i;
$newLines[] = self::_addNote($line, $i, $inComment, $padTo); $newLines[] = self::_addNote($line, $i, $inComment, $padTo);
@ -65,7 +69,6 @@ class Minify_Lines {
// check for desired URI rewriting // check for desired URI rewriting
if (isset($options['currentDir'])) { if (isset($options['currentDir'])) {
require_once 'Minify/CSS/UriRewriter.php';
Minify_CSS_UriRewriter::$debugText = ''; Minify_CSS_UriRewriter::$debugText = '';
$content = Minify_CSS_UriRewriter::rewrite( $content = Minify_CSS_UriRewriter::rewrite(
$content $content
@ -93,6 +96,9 @@ class Minify_Lines {
*/ */
private static function _eolInComment($line, $inComment) private static function _eolInComment($line, $inComment)
{ {
// crude way to avoid things like // */
$line = preg_replace('~//.*?(\\*/|/\\*).*~', '', $line);
while (strlen($line)) { while (strlen($line)) {
$search = $inComment $search = $inComment
? '*/' ? '*/'

20
inc/lib/minify/Minify/YUICompressor.php

@ -13,14 +13,17 @@
* Java environment. * Java environment.
* *
* <code> * <code>
* Minify_YUICompressor::$jarFile = '/path/to/yuicompressor-2.3.5.jar'; * Minify_YUICompressor::$jarFile = '/path/to/yuicompressor-2.4.6.jar';
* Minify_YUICompressor::$tempDir = '/tmp'; * Minify_YUICompressor::$tempDir = '/tmp';
* $code = Minify_YUICompressor::minifyJs( * $code = Minify_YUICompressor::minifyJs(
* $code * $code
* ,array('nomunge' => true, 'line-break' => 1000) * ,array('nomunge' => true, 'line-break' => 1000)
* ); * );
* </code> * </code>
* *
* Note: In case you run out stack (default is 512k), you may increase stack size in $options:
* array('stack-size' => '2048k')
*
* @todo unit tests, $options docs * @todo unit tests, $options docs
* *
* @package Minify * @package Minify
@ -87,7 +90,7 @@ class Minify_YUICompressor {
{ {
self::_prepare(); self::_prepare();
if (! ($tmpFile = tempnam(self::$tempDir, 'yuic_'))) { if (! ($tmpFile = tempnam(self::$tempDir, 'yuic_'))) {
throw new Exception('Minify_YUICompressor : could not create temp file.'); throw new Exception('Minify_YUICompressor : could not create temp file in "'.self::$tempDir.'".');
} }
file_put_contents($tmpFile, $content); file_put_contents($tmpFile, $content);
exec(self::_getCmd($options, $type, $tmpFile), $output, $result_code); exec(self::_getCmd($options, $type, $tmpFile), $output, $result_code);
@ -108,10 +111,15 @@ class Minify_YUICompressor {
,'nomunge' => false ,'nomunge' => false
,'preserve-semi' => false ,'preserve-semi' => false
,'disable-optimizations' => false ,'disable-optimizations' => false
,'stack-size' => ''
) )
,$userOptions ,$userOptions
); );
$cmd = self::$javaExecutable . ' -jar ' . escapeshellarg(self::$jarFile) $cmd = self::$javaExecutable
. (!empty($o['stack-size'])
? ' -Xss' . $o['stack-size']
: '')
. ' -jar ' . escapeshellarg(self::$jarFile)
. " --type {$type}" . " --type {$type}"
. (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset']) . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset'])
? " --charset {$o['charset']}" ? " --charset {$o['charset']}"
@ -134,8 +142,8 @@ class Minify_YUICompressor {
if (! is_file(self::$jarFile)) { if (! is_file(self::$jarFile)) {
throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not a valid file.'); throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not a valid file.');
} }
if (! is_executable(self::$jarFile)) { if (! is_readable(self::$jarFile)) {
throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not executable.'); throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not readable.');
} }
if (! is_dir(self::$tempDir)) { if (! is_dir(self::$tempDir)) {
throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not a valid direcotry.'); throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not a valid direcotry.');

33
inc/lib/minify/MrClay/Cli.php

@ -2,6 +2,9 @@
namespace MrClay; namespace MrClay;
use MrClay\Cli\Arg;
use InvalidArgumentException;
/** /**
* Forms a front controller for a console app, handling and validating arguments (options) * Forms a front controller for a console app, handling and validating arguments (options)
* *
@ -51,7 +54,7 @@ class Cli {
public $isHelpRequest = false; public $isHelpRequest = false;
/** /**
* @var array of Cli\Arg * @var Arg[]
*/ */
protected $_args = array(); protected $_args = array();
@ -80,8 +83,8 @@ class Cli {
} }
/** /**
* @param Cli\Arg|string $letter * @param Arg|string $letter
* @return Cli\Arg * @return Arg
*/ */
public function addOptionalArg($letter) public function addOptionalArg($letter)
{ {
@ -89,8 +92,8 @@ class Cli {
} }
/** /**
* @param Cli\Arg|string $letter * @param Arg|string $letter
* @return Cli\Arg * @return Arg
*/ */
public function addRequiredArg($letter) public function addRequiredArg($letter)
{ {
@ -100,17 +103,17 @@ class Cli {
/** /**
* @param string $letter * @param string $letter
* @param bool $required * @param bool $required
* @param Cli\Arg|null $arg * @param Arg|null $arg
* @return Cli\Arg * @return Arg
* @throws \InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function addArgument($letter, $required, Cli\Arg $arg = null) public function addArgument($letter, $required, Arg $arg = null)
{ {
if (! preg_match('/^[a-zA-Z]$/', $letter)) { if (! preg_match('/^[a-zA-Z]$/', $letter)) {
throw new \InvalidArgumentException('$letter must be in [a-zA-z]'); throw new InvalidArgumentException('$letter must be in [a-zA-Z]');
} }
if (! $arg) { if (! $arg) {
$arg = new Cli\Arg($required); $arg = new Arg($required);
} }
$this->_args[$letter] = $arg; $this->_args[$letter] = $arg;
return $arg; return $arg;
@ -118,7 +121,7 @@ class Cli {
/** /**
* @param string $letter * @param string $letter
* @return Cli\Arg|null * @return Arg|null
*/ */
public function getArgument($letter) public function getArgument($letter)
{ {
@ -143,7 +146,7 @@ class Cli {
$lettersUsed = ''; $lettersUsed = '';
foreach ($this->_args as $letter => $arg) { foreach ($this->_args as $letter => $arg) {
/* @var Cli\Arg $arg */ /* @var Arg $arg */
$options .= $letter; $options .= $letter;
$lettersUsed .= $letter; $lettersUsed .= $letter;
@ -159,7 +162,7 @@ class Cli {
$this->debug['getopt_return'] = $o; $this->debug['getopt_return'] = $o;
foreach ($this->_args as $letter => $arg) { foreach ($this->_args as $letter => $arg) {
/* @var Cli\Arg $arg */ /* @var Arg $arg */
$this->values[$letter] = false; $this->values[$letter] = false;
if (isset($o[$letter])) { if (isset($o[$letter])) {
if (is_bool($o[$letter])) { if (is_bool($o[$letter])) {
@ -295,7 +298,7 @@ class Cli {
{ {
$r = "\n"; $r = "\n";
foreach ($this->_args as $letter => $arg) { foreach ($this->_args as $letter => $arg) {
/* @var Cli\Arg $arg */ /* @var Arg $arg */
$desc = $arg->getDescription(); $desc = $arg->getDescription();
$flag = " -$letter "; $flag = " -$letter ";
if ($arg->mayHaveValue) { if ($arg->mayHaveValue) {

6
inc/lib/minify/MrClay/Cli/Arg.php

@ -2,6 +2,8 @@
namespace MrClay\Cli; namespace MrClay\Cli;
use BadMethodCallException;
/** /**
* An argument for a CLI app. This specifies the argument, what values it expects and * An argument for a CLI app. This specifies the argument, what values it expects and
* how it's treated during validation. * how it's treated during validation.
@ -150,7 +152,7 @@ class Arg {
* @param string $name * @param string $name
* @param array $args * @param array $args
* @return Arg * @return Arg
* @throws \BadMethodCallException * @throws BadMethodCallException
*/ */
public function __call($name, array $args = array()) public function __call($name, array $args = array())
{ {
@ -160,7 +162,7 @@ class Arg {
$this->spec['mustHaveValue'] = true; $this->spec['mustHaveValue'] = true;
} }
} else { } else {
throw new \BadMethodCallException('Method does not exist'); throw new BadMethodCallException('Method does not exist');
} }
return $this; return $this;
} }

8
js/jquery.min.js

File diff suppressed because one or more lines are too long

57
js/jquery.mixitup.min.js

File diff suppressed because one or more lines are too long

2
js/jquery.tooltipster.min.js

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save