Upgraded JSMinPlus to v1.4

Added CSS path rewriting options to config file, updated JS.php to take groups file into account for caching
This commit is contained in:
Timothy Warren 2011-09-09 17:23:38 -04:00
parent 2160f23235
commit a441e764ea
4 changed files with 404 additions and 168 deletions

View File

@ -1,7 +1,7 @@
<?php
/**
* JSMinPlus version 1.1
* JSMinPlus version 1.4
*
* Minifies a javascript file using a javascript parser
*
@ -15,6 +15,11 @@
* Usage: $minified = JSMinPlus::minify($script [, $filename])
*
* Versionlog (see also changelog.txt):
* 23-07-2011 - remove dynamic creation of OP_* and KEYWORD_* defines and declare them on top
* reduce memory footprint by minifying by block-scope
* some small byte-saving and performance improvements
* 12-05-2009 - fixed hook:colon precedence, fixed empty body in loop and if-constructs
* 18-04-2009 - fixed crashbug in PHP 5.2.9 and several other bugfixes
* 12-04-2009 - some small bugfixes and performance improvements
* 09-04-2009 - initial open sourced version 1.0
*
@ -39,11 +44,11 @@
*
* The Initial Developer of the Original Code is
* Brendan Eich <brendan@mozilla.org>.
* Portions created by the Initial Developer are Copyright (C) 2004
* Portions created by the Initial Developer are Copyright © 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Tino Zijdel <crisp@tweakers.net>
* PHP port, modifications and minifier routine are (C) 2009
* PHP port, modifications and minifier routine are © 2009-2011
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -65,7 +70,8 @@ define('TOKEN_IDENTIFIER', 3);
define('TOKEN_STRING', 4);
define('TOKEN_REGEXP', 5);
define('TOKEN_NEWLINE', 6);
define('TOKEN_CONDCOMMENT_MULTILINE', 7);
define('TOKEN_CONDCOMMENT_START', 7);
define('TOKEN_CONDCOMMENT_END', 8);
define('JS_SCRIPT', 100);
define('JS_BLOCK', 101);
@ -82,10 +88,89 @@ define('JS_SETTER', 111);
define('JS_GROUP', 112);
define('JS_LIST', 113);
define('JS_MINIFIED', 999);
define('DECLARED_FORM', 0);
define('EXPRESSED_FORM', 1);
define('STATEMENT_FORM', 2);
/* Operators */
define('OP_SEMICOLON', ';');
define('OP_COMMA', ',');
define('OP_HOOK', '?');
define('OP_COLON', ':');
define('OP_OR', '||');
define('OP_AND', '&&');
define('OP_BITWISE_OR', '|');
define('OP_BITWISE_XOR', '^');
define('OP_BITWISE_AND', '&');
define('OP_STRICT_EQ', '===');
define('OP_EQ', '==');
define('OP_ASSIGN', '=');
define('OP_STRICT_NE', '!==');
define('OP_NE', '!=');
define('OP_LSH', '<<');
define('OP_LE', '<=');
define('OP_LT', '<');
define('OP_URSH', '>>>');
define('OP_RSH', '>>');
define('OP_GE', '>=');
define('OP_GT', '>');
define('OP_INCREMENT', '++');
define('OP_DECREMENT', '--');
define('OP_PLUS', '+');
define('OP_MINUS', '-');
define('OP_MUL', '*');
define('OP_DIV', '/');
define('OP_MOD', '%');
define('OP_NOT', '!');
define('OP_BITWISE_NOT', '~');
define('OP_DOT', '.');
define('OP_LEFT_BRACKET', '[');
define('OP_RIGHT_BRACKET', ']');
define('OP_LEFT_CURLY', '{');
define('OP_RIGHT_CURLY', '}');
define('OP_LEFT_PAREN', '(');
define('OP_RIGHT_PAREN', ')');
define('OP_CONDCOMMENT_END', '@*/');
define('OP_UNARY_PLUS', 'U+');
define('OP_UNARY_MINUS', 'U-');
/* Keywords */
define('KEYWORD_BREAK', 'break');
define('KEYWORD_CASE', 'case');
define('KEYWORD_CATCH', 'catch');
define('KEYWORD_CONST', 'const');
define('KEYWORD_CONTINUE', 'continue');
define('KEYWORD_DEBUGGER', 'debugger');
define('KEYWORD_DEFAULT', 'default');
define('KEYWORD_DELETE', 'delete');
define('KEYWORD_DO', 'do');
define('KEYWORD_ELSE', 'else');
define('KEYWORD_ENUM', 'enum');
define('KEYWORD_FALSE', 'false');
define('KEYWORD_FINALLY', 'finally');
define('KEYWORD_FOR', 'for');
define('KEYWORD_FUNCTION', 'function');
define('KEYWORD_IF', 'if');
define('KEYWORD_IN', 'in');
define('KEYWORD_INSTANCEOF', 'instanceof');
define('KEYWORD_NEW', 'new');
define('KEYWORD_NULL', 'null');
define('KEYWORD_RETURN', 'return');
define('KEYWORD_SWITCH', 'switch');
define('KEYWORD_THIS', 'this');
define('KEYWORD_THROW', 'throw');
define('KEYWORD_TRUE', 'true');
define('KEYWORD_TRY', 'try');
define('KEYWORD_TYPEOF', 'typeof');
define('KEYWORD_VAR', 'var');
define('KEYWORD_VOID', 'void');
define('KEYWORD_WHILE', 'while');
define('KEYWORD_WITH', 'with');
class JSMinPlus
{
private $parser;
@ -107,7 +192,7 @@ class JSMinPlus
private function __construct()
{
$this->parser = new JSParser();
$this->parser = new JSParser($this);
}
public static function minify($js, $filename='')
@ -136,42 +221,55 @@ class JSMinPlus
return false;
}
private function parseTree($n, $noBlockGrouping = false)
public function parseTree($n, $noBlockGrouping = false)
{
$s = '';
switch ($n->type)
{
case KEYWORD_FUNCTION:
$s .= 'function' . ($n->name ? ' ' . $n->name : '') . '(';
$params = $n->params;
for ($i = 0, $j = count($params); $i < $j; $i++)
$s .= ($i ? ',' : '') . $params[$i];
$s .= '){' . $this->parseTree($n->body, true) . '}';
case JS_MINIFIED:
$s = $n->value;
break;
case JS_SCRIPT:
// we do nothing with funDecls or varDecls
// we do nothing yet with funDecls or varDecls
$noBlockGrouping = true;
// fall through
// FALL THROUGH
case JS_BLOCK:
$childs = $n->treeNodes;
$lastType = 0;
for ($c = 0, $i = 0, $j = count($childs); $i < $j; $i++)
{
$type = $childs[$i]->type;
$t = $this->parseTree($childs[$i]);
if (strlen($t))
{
if ($c)
{
if ($childs[$i]->type == KEYWORD_FUNCTION && $childs[$i]->functionForm == DECLARED_FORM)
$s .= "\n"; // put declared functions on a new line
$s = rtrim($s, ';');
if ($type == KEYWORD_FUNCTION && $childs[$i]->functionForm == DECLARED_FORM)
{
// put declared functions on a new line
$s .= "\n";
}
elseif ($type == KEYWORD_VAR && $type == $lastType)
{
// mutiple var-statements can go into one
$t = ',' . substr($t, 4);
}
else
{
// add terminator
$s .= ';';
}
}
$s .= $t;
$c++;
$lastType = $type;
}
}
@ -181,31 +279,41 @@ class JSMinPlus
}
break;
case KEYWORD_FUNCTION:
$s .= 'function' . ($n->name ? ' ' . $n->name : '') . '(';
$params = $n->params;
for ($i = 0, $j = count($params); $i < $j; $i++)
$s .= ($i ? ',' : '') . $params[$i];
$s .= '){' . $this->parseTree($n->body, true) . '}';
break;
case KEYWORD_IF:
$s = 'if(' . $this->parseTree($n->condition) . ')';
$thenPart = $this->parseTree($n->thenPart);
$elsePart = $n->elsePart ? $this->parseTree($n->elsePart) : null;
// quite a rancid hack to see if we should enclose the thenpart in brackets
if ($thenPart[0] != '{')
{
if (strpos($thenPart, 'if(') !== false)
$thenPart = '{' . $thenPart . '}';
elseif ($elsePart)
$thenPart .= ';';
}
$s .= $thenPart;
// empty if-statement
if ($thenPart == '')
$thenPart = ';';
if ($elsePart)
{
$s .= 'else';
// be carefull and always make a block out of the thenPart; could be more optimized but is a lot of trouble
if ($thenPart != ';' && $thenPart[0] != '{')
$thenPart = '{' . $thenPart . '}';
$s .= $thenPart . 'else';
// we could check for more, but that hardly ever applies so go for performance
if ($elsePart[0] != '{')
$s .= ' ';
$s .= $elsePart;
}
else
{
$s .= $thenPart;
}
break;
case KEYWORD_SWITCH:
@ -219,26 +327,48 @@ class JSMinPlus
else
$s .= 'default:';
$statement = $this->parseTree($case->statements);
$statement = $this->parseTree($case->statements, true);
if ($statement)
$s .= $statement . ';';
{
$s .= $statement;
// no terminator for last statement
if ($i + 1 < $j)
$s .= ';';
}
}
$s = rtrim($s, ';') . '}';
$s .= '}';
break;
case KEYWORD_FOR:
$s = 'for(' . ($n->setup ? $this->parseTree($n->setup) : '')
. ';' . ($n->condition ? $this->parseTree($n->condition) : '')
. ';' . ($n->update ? $this->parseTree($n->update) : '') . ')'
. $this->parseTree($n->body);
. ';' . ($n->update ? $this->parseTree($n->update) : '') . ')';
$body = $this->parseTree($n->body);
if ($body == '')
$body = ';';
$s .= $body;
break;
case KEYWORD_WHILE:
$s = 'while(' . $this->parseTree($n->condition) . ')' . $this->parseTree($n->body);
$s = 'while(' . $this->parseTree($n->condition) . ')';
$body = $this->parseTree($n->body);
if ($body == '')
$body = ';';
$s .= $body;
break;
case JS_FOR_IN:
$s = 'for(' . ($n->varDecl ? $this->parseTree($n->varDecl) : $this->parseTree($n->iterator)) . ' in ' . $this->parseTree($n->object) . ')' . $this->parseTree($n->body);
$s = 'for(' . ($n->varDecl ? $this->parseTree($n->varDecl) : $this->parseTree($n->iterator)) . ' in ' . $this->parseTree($n->object) . ')';
$body = $this->parseTree($n->body);
if ($body == '')
$body = ';';
$s .= $body;
break;
case KEYWORD_DO:
@ -263,11 +393,19 @@ class JSMinPlus
break;
case KEYWORD_THROW:
$s = 'throw ' . $this->parseTree($n->exception);
break;
case KEYWORD_RETURN:
$s = 'return' . ($n->value ? ' ' . $this->parseTree($n->value) : '');
$s = $n->type;
if ($n->value)
{
$t = $this->parseTree($n->value);
if (strlen($t))
{
if ($this->isWordChar($t[0]) || $t[0] == '\\')
$s .= ' ';
$s .= $t;
}
}
break;
case KEYWORD_WITH:
@ -288,12 +426,47 @@ class JSMinPlus
}
break;
case KEYWORD_IN:
case KEYWORD_INSTANCEOF:
$left = $this->parseTree($n->treeNodes[0]);
$right = $this->parseTree($n->treeNodes[1]);
$s = $left;
if ($this->isWordChar(substr($left, -1)))
$s .= ' ';
$s .= $n->type;
if ($this->isWordChar($right[0]) || $right[0] == '\\')
$s .= ' ';
$s .= $right;
break;
case KEYWORD_DELETE:
case KEYWORD_TYPEOF:
$right = $this->parseTree($n->treeNodes[0]);
$s = $n->type;
if ($this->isWordChar($right[0]) || $right[0] == '\\')
$s .= ' ';
$s .= $right;
break;
case KEYWORD_VOID:
$s = 'void(' . $this->parseTree($n->treeNodes[0]) . ')';
break;
case KEYWORD_DEBUGGER:
throw new Exception('NOT IMPLEMENTED: DEBUGGER');
break;
case TOKEN_CONDCOMMENT_MULTILINE:
$s = $n->value . ' ';
case TOKEN_CONDCOMMENT_START:
case TOKEN_CONDCOMMENT_END:
$s = $n->value . ($n->type == TOKEN_CONDCOMMENT_START ? ' ' : '');
$childs = $n->treeNodes;
for ($i = 0, $j = count($childs); $i < $j; $i++)
$s .= $this->parseTree($childs[$i]);
@ -333,34 +506,32 @@ class JSMinPlus
case OP_PLUS:
case OP_MINUS:
$s = $this->parseTree($n->treeNodes[0]) . $n->type;
$nextTokenType = $n->treeNodes[1]->type;
if ( $nextTokenType == OP_PLUS || $nextTokenType == OP_MINUS ||
$nextTokenType == OP_INCREMENT || $nextTokenType == OP_DECREMENT ||
$nextTokenType == OP_UNARY_PLUS || $nextTokenType == OP_UNARY_MINUS
)
$s .= ' ';
$s .= $this->parseTree($n->treeNodes[1]);
break;
$left = $this->parseTree($n->treeNodes[0]);
$right = $this->parseTree($n->treeNodes[1]);
case KEYWORD_IN:
$s = $this->parseTree($n->treeNodes[0]) . ' in ' . $this->parseTree($n->treeNodes[1]);
break;
switch ($n->treeNodes[1]->type)
{
case OP_PLUS:
case OP_MINUS:
case OP_INCREMENT:
case OP_DECREMENT:
case OP_UNARY_PLUS:
case OP_UNARY_MINUS:
$s = $left . $n->type . ' ' . $right;
break;
case KEYWORD_INSTANCEOF:
$s = $this->parseTree($n->treeNodes[0]) . ' instanceof ' . $this->parseTree($n->treeNodes[1]);
break;
case TOKEN_STRING:
//combine concatted strings with same quotestyle
if ($n->type == OP_PLUS && substr($left, -1) == $right[0])
{
$s = substr($left, 0, -1) . substr($right, 1);
break;
}
// FALL THROUGH
case KEYWORD_DELETE:
$s = 'delete ' . $this->parseTree($n->treeNodes[0]);
break;
case KEYWORD_VOID:
$s = 'void(' . $this->parseTree($n->treeNodes[0]) . ')';
break;
case KEYWORD_TYPEOF:
$s = 'typeof ' . $this->parseTree($n->treeNodes[0]);
default:
$s = $left . $n->type . $right;
}
break;
case OP_NOT:
@ -452,13 +623,33 @@ class JSMinPlus
$s .= '}';
break;
case TOKEN_NUMBER:
$s = $n->value;
if (preg_match('/^([1-9]+)(0{3,})$/', $s, $m))
$s = $m[1] . 'e' . strlen($m[2]);
break;
case KEYWORD_NULL: case KEYWORD_THIS: case KEYWORD_TRUE: case KEYWORD_FALSE:
case TOKEN_IDENTIFIER: case TOKEN_NUMBER: case TOKEN_STRING: case TOKEN_REGEXP:
case TOKEN_IDENTIFIER: case TOKEN_STRING: case TOKEN_REGEXP:
$s = $n->value;
break;
case JS_GROUP:
$s = '(' . $this->parseTree($n->treeNodes[0]) . ')';
if (in_array(
$n->treeNodes[0]->type,
array(
JS_ARRAY_INIT, JS_OBJECT_INIT, JS_GROUP,
TOKEN_NUMBER, TOKEN_STRING, TOKEN_REGEXP, TOKEN_IDENTIFIER,
KEYWORD_NULL, KEYWORD_THIS, KEYWORD_TRUE, KEYWORD_FALSE
)
))
{
$s = $this->parseTree($n->treeNodes[0]);
}
else
{
$s = '(' . $this->parseTree($n->treeNodes[0]) . ')';
}
break;
default:
@ -472,17 +663,23 @@ class JSMinPlus
{
return preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $string) && !in_array($string, $this->reserved);
}
private function isWordChar($char)
{
return $char == '_' || $char == '$' || ctype_alnum($char);
}
}
class JSParser
{
private $t;
private $minifier;
private $opPrecedence = array(
';' => 0,
',' => 1,
'=' => 2, '?' => 2, ':' => 2,
// The above all have to have the same precedence, see bug 330975.
// The above all have to have the same precedence, see bug 330975
'||' => 4,
'&&' => 5,
'|' => 6,
@ -523,11 +720,12 @@ class JSParser
'.' => 2,
JS_NEW_WITH_ARGS => 2, JS_INDEX => 2, JS_CALL => 2,
JS_ARRAY_INIT => 1, JS_OBJECT_INIT => 1, JS_GROUP => 1,
TOKEN_CONDCOMMENT_MULTILINE => 1
TOKEN_CONDCOMMENT_START => 1, TOKEN_CONDCOMMENT_END => 1
);
public function __construct()
public function __construct($minifier=null)
{
$this->minifier = $minifier;
$this->t = new JSTokenizer();
}
@ -551,6 +749,19 @@ class JSParser
$n->funDecls = $x->funDecls;
$n->varDecls = $x->varDecls;
// minify by scope
if ($this->minifier)
{
$n->value = $this->minifier->parseTree($n);
// clear tree from node to save memory
$n->treeNodes = null;
$n->funDecls = null;
$n->varDecls = null;
$n->type = JS_MINIFIED;
}
return $n;
}
@ -809,7 +1020,7 @@ class JSParser
case KEYWORD_THROW:
$n = new JSNode($this->t);
$n->exception = $this->Expression($x);
$n->value = $this->Expression($x);
break;
case KEYWORD_RETURN:
@ -835,7 +1046,8 @@ class JSParser
$n = $this->Variables($x);
break;
case TOKEN_CONDCOMMENT_MULTILINE:
case TOKEN_CONDCOMMENT_START:
case TOKEN_CONDCOMMENT_END:
$n = new JSNode($this->t);
return $n;
@ -994,37 +1206,47 @@ class JSParser
// NB: cannot be empty, Statement handled that.
break 2;
case OP_ASSIGN:
case OP_HOOK:
case OP_COLON:
if ($this->t->scanOperand)
break 2;
// Use >, not >=, for right-associative ASSIGN and HOOK/COLON.
while ( !empty($operators) &&
( $this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt] ||
($tt == OP_COLON && end($operators)->type == OP_ASSIGN)
)
$this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt]
)
$this->reduce($operators, $operands);
if ($tt == OP_COLON)
{
$n = end($operators);
if ($n->type != OP_HOOK)
throw $this->t->newSyntaxError('Invalid label');
array_push($operators, new JSNode($this->t));
--$x->hookLevel;
}
else
{
array_push($operators, new JSNode($this->t));
if ($tt == OP_ASSIGN)
end($operands)->assignOp = $this->t->currentToken()->assignOp;
else
++$x->hookLevel;
}
++$x->hookLevel;
$this->t->scanOperand = true;
$n = $this->Expression($x);
if (!$this->t->match(OP_COLON))
break 2;
--$x->hookLevel;
array_push($operands, $n);
break;
case OP_COLON:
if ($x->hookLevel)
break 2;
throw $this->t->newSyntaxError('Invalid label');
break;
case OP_ASSIGN:
if ($this->t->scanOperand)
break 2;
// Use >, not >=, for right-associative ASSIGN
while ( !empty($operators) &&
$this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt]
)
$this->reduce($operators, $operands);
array_push($operators, new JSNode($this->t));
end($operands)->assignOp = $this->t->currentToken()->assignOp;
$this->t->scanOperand = true;
break;
@ -1036,14 +1258,19 @@ class JSParser
!$x->bracketLevel && !$x->curlyLevel &&
!$x->parenLevel
)
{
break 2;
}
// FALL THROUGH
case OP_COMMA:
// Treat comma as left-associative so reduce can fold left-heavy
// COMMA trees into a single array.
// FALL THROUGH
// A comma operator should not be parsed if we're parsing the then part
// of a conditional expression unless it's parenthesized somehow.
if ($tt == OP_COMMA && $x->hookLevel &&
!$x->bracketLevel && !$x->curlyLevel &&
!$x->parenLevel
)
break 2;
// Treat comma as left-associative so reduce can fold left-heavy
// COMMA trees into a single array.
// FALL THROUGH
case OP_OR:
case OP_AND:
case OP_BITWISE_OR:
@ -1127,7 +1354,8 @@ class JSParser
$this->t->scanOperand = false;
break;
case TOKEN_CONDCOMMENT_MULTILINE:
case TOKEN_CONDCOMMENT_START:
case TOKEN_CONDCOMMENT_END:
if ($this->t->scanOperand)
array_push($operators, new JSNode($this->t));
else
@ -1312,7 +1540,7 @@ class JSParser
}
if ($x->hookLevel != $hl)
throw $this->t->newSyntaxError('Missing : after ?');
throw $this->t->newSyntaxError('Missing : in conditional expression');
if ($x->parenLevel != $pl)
throw $this->t->newSyntaxError('Missing ) in parenthetical');
@ -1443,7 +1671,7 @@ class JSNode
if (($numargs = func_num_args()) > 2)
{
$args = func_get_args();;
$args = func_get_args();
for ($i = 2; $i < $numargs; $i++)
$this->addNode($args[$i]);
}
@ -1465,6 +1693,14 @@ class JSNode
public function addNode($node)
{
if ($node !== null)
{
if ($node->start < $this->start)
$this->start = $node->start;
if ($this->end < $node->end)
$this->end = $node->end;
}
$this->treeNodes[] = $node;
}
}
@ -1499,44 +1735,11 @@ class JSTokenizer
);
private $opTypeNames = array(
';' => 'SEMICOLON',
',' => 'COMMA',
'?' => 'HOOK',
':' => 'COLON',
'||' => 'OR',
'&&' => 'AND',
'|' => 'BITWISE_OR',
'^' => 'BITWISE_XOR',
'&' => 'BITWISE_AND',
'===' => 'STRICT_EQ',
'==' => 'EQ',
'=' => 'ASSIGN',
'!==' => 'STRICT_NE',
'!=' => 'NE',
'<<' => 'LSH',
'<=' => 'LE',
'<' => 'LT',
'>>>' => 'URSH',
'>>' => 'RSH',
'>=' => 'GE',
'>' => 'GT',
'++' => 'INCREMENT',
'--' => 'DECREMENT',
'+' => 'PLUS',
'-' => 'MINUS',
'*' => 'MUL',
'/' => 'DIV',
'%' => 'MOD',
'!' => 'NOT',
'~' => 'BITWISE_NOT',
'.' => 'DOT',
'[' => 'LEFT_BRACKET',
']' => 'RIGHT_BRACKET',
'{' => 'LEFT_CURLY',
'}' => 'RIGHT_CURLY',
'(' => 'LEFT_PAREN',
')' => 'RIGHT_PAREN',
'@*/' => 'CONDCOMMENT_END'
';', ',', '?', ':', '||', '&&', '|', '^',
'&', '===', '==', '=', '!==', '!=', '<<', '<=',
'<', '>>>', '>>', '>=', '>', '++', '--', '+',
'-', '*', '/', '%', '!', '~', '.', '[',
']', '{', '}', '(', ')', '@*/'
);
private $assignOps = array('|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%');
@ -1544,17 +1747,7 @@ class JSTokenizer
public function __construct()
{
$this->opRegExp = '#^(' . implode('|', array_map('preg_quote', array_keys($this->opTypeNames))) . ')#';
// this is quite a hidden yet convenient place to create the defines for operators and keywords
foreach ($this->opTypeNames as $operand => $name)
define('OP_' . $name, $operand);
define('OP_UNARY_PLUS', 'U+');
define('OP_UNARY_MINUS', 'U-');
foreach ($this->keywords as $keyword)
define('KEYWORD_' . strtoupper($keyword), $keyword);
$this->opRegExp = '#^(' . implode('|', array_map('preg_quote', $this->opTypeNames)) . ')#';
}
public function init($source, $filename = '', $lineno = 1)
@ -1668,7 +1861,7 @@ class JSTokenizer
}
// Comments
if (!preg_match('/^\/(?:\*(@(?:cc_on|if|elif|else|end))?(?:.|\n)*?\*\/|\/.*)/', $input, $match))
if (!preg_match('/^\/(?:\*(@(?:cc_on|if|elif|else|end))?.*?\*\/|\/[^\n]*)/s', $input, $match))
{
if (!$chunksize)
break;
@ -1681,7 +1874,7 @@ class JSTokenizer
// check if this is a conditional (JScript) comment
if (!empty($match[1]))
{
//$match[0] = '/*' . $match[1];
$match[0] = '/*' . $match[1];
$conditional_comment = true;
break;
}
@ -1699,28 +1892,44 @@ class JSTokenizer
}
elseif ($conditional_comment)
{
$tt = TOKEN_CONDCOMMENT_MULTILINE;
$tt = TOKEN_CONDCOMMENT_START;
}
else
{
switch ($input[0])
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (preg_match('/^\d+\.\d*(?:[eE][-+]?\d+)?|^\d+(?:\.\d*)?[eE][-+]?\d+/', $input, $match))
case '0':
// hexadecimal
if (($input[1] == 'x' || $input[1] == 'X') && preg_match('/^0x[0-9a-f]+/i', $input, $match))
{
$tt = TOKEN_NUMBER;
break;
}
elseif (preg_match('/^0[xX][\da-fA-F]+|^0[0-7]*|^\d+/', $input, $match))
// FALL THROUGH
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
// should always match
preg_match('/^\d+(?:\.\d*)?(?:[eE][-+]?\d+)?/', $input, $match);
$tt = TOKEN_NUMBER;
break;
case "'":
if (preg_match('/^\'(?:[^\\\\\'\r\n]++|\\\\(?:.|\r?\n))*\'/', $input, $match))
{
// this should always match because of \d+
$tt = TOKEN_NUMBER;
$tt = TOKEN_STRING;
}
else
{
if ($chunksize)
return $this->get(null); // retry with a full chunk fetch
throw $this->newSyntaxError('Unterminated string literal');
}
break;
case '"':
case "'":
if (preg_match('/^"(?:\\\\(?:.|\r?\n)|[^\\\\"\r\n])*"|^\'(?:\\\\(?:.|\r?\n)|[^\\\\\'\r\n])*\'/', $input, $match))
if (preg_match('/^"(?:[^\\\\"\r\n]++|\\\\(?:.|\r?\n))*"/', $input, $match))
{
$tt = TOKEN_STRING;
}
@ -1739,7 +1948,7 @@ class JSTokenizer
$tt = TOKEN_REGEXP;
break;
}
// fall through
// FALL THROUGH
case '|':
case '^':
@ -1780,7 +1989,7 @@ class JSTokenizer
$tt = TOKEN_NUMBER;
break;
}
// fall through
// FALL THROUGH
case ';':
case ',':
@ -1799,7 +2008,14 @@ class JSTokenizer
break;
case '@':
throw $this->newSyntaxError('Illegal token');
// check end of conditional comment
if (substr($input, 0, 3) == '@*/')
{
$match = array('@*/');
$tt = TOKEN_CONDCOMMENT_END;
}
else
throw $this->newSyntaxError('Illegal token');
break;
case "\n":
@ -1868,5 +2084,3 @@ class JSToken
public $lineno;
public $assignOp;
}
?>

View File

@ -25,6 +25,26 @@ $document_root = $_SERVER['DOCUMENT_ROOT'];
*/
$css_root = $document_root. '/css/';
/*
|--------------------------------------------------------------------------
| Path from
|--------------------------------------------------------------------------
|
| Path fragment to rewrite in css files
|
*/
$path_from = '';
/*
|--------------------------------------------------------------------------
| Path to
|--------------------------------------------------------------------------
|
| The path fragment replacement for the css files
|
*/
$path_to = '';
/*
|--------------------------------------------------------------------------
| JS Folder

View File

@ -6,7 +6,7 @@ require('./config/config.php');
$groups = require("./config/css_groups.php");
//The name of this file
$this_file = $css_root.'css.php';
$this_file = 'css.php';
//Function for compressing the CSS as tightly as possible
@ -61,6 +61,8 @@ if(!isset($_GET['debug']))
$css = compress($css);
}
$css = strtr($css, $path_from, $path_to);
$requested_time=(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])
: time();

2
js.php
View File

@ -7,7 +7,7 @@ require('./config/JSMinPlus.php');
$groups = require("./config/js_groups.php");
//The name of this file
$this_file = $js_root.'js.php';
$this_file = 'js.php';
// --------------------------------------------------------------------------