mirror of
https://github.com/mrclay/minify.git
synced 2025-08-09 15:46:34 +02:00
proper fix for Issue 144: + ++a
This commit is contained in:
@@ -1,20 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* jsmin.php - extended PHP implementation of Douglas Crockford's JSMin.
|
* JSMin.php - modified PHP implementation of Douglas Crockford's JSMin.
|
||||||
*
|
*
|
||||||
* <code>
|
* <code>
|
||||||
* $minifiedJs = JSMin::minify($js);
|
* $minifiedJs = JSMin::minify($js);
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* This is a direct port of jsmin.c to PHP with a few PHP performance tweaks and
|
* This is a modified port of jsmin.c. Improvements:
|
||||||
* modifications to preserve some comments (see below). Also, rather than using
|
*
|
||||||
* stdin/stdout, JSMin::minify() accepts a string as input and returns another
|
* Does not choke on some regexp literals containing quote characters. E.g. /'/
|
||||||
* string as output.
|
*
|
||||||
*
|
* Spaces are preserved after some add/sub operators, so they are not mistakenly
|
||||||
* Comments containing IE conditional compilation are preserved, as are multi-line
|
* converted to post-inc/dec. E.g. a + ++b -> a+ ++b
|
||||||
* comments that begin with "/*!" (for documentation purposes). In the latter case
|
|
||||||
* newlines are inserted around the comment to enhance readability.
|
|
||||||
*
|
*
|
||||||
|
* 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
|
||||||
@@ -68,6 +68,7 @@ class JSMin {
|
|||||||
protected $inputLength = 0;
|
protected $inputLength = 0;
|
||||||
protected $lookAhead = null;
|
protected $lookAhead = null;
|
||||||
protected $output = '';
|
protected $output = '';
|
||||||
|
protected $lastByteOut = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minify Javascript.
|
* Minify Javascript.
|
||||||
@@ -87,13 +88,6 @@ class JSMin {
|
|||||||
public function __construct($input)
|
public function __construct($input)
|
||||||
{
|
{
|
||||||
$this->input = $input;
|
$this->input = $input;
|
||||||
// look out for syntax like "++ +" and "- ++"
|
|
||||||
$p = '\\+';
|
|
||||||
$m = '\\-';
|
|
||||||
if (preg_match("/([$p$m])(?:\\1 [$p$m]| (?:$p$p|$m$m))/", $input)) {
|
|
||||||
// likely pre-minified and would be broken by JSMin
|
|
||||||
$this->output = $input;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,7 +113,11 @@ 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->isAlphaNum($this->b)) {
|
if (($this->lastByteOut === '+' || $this->lastByteOut === '-')
|
||||||
|
&& ($this->b === $this->lastByteOut)) {
|
||||||
|
// Don't delete this space. If we do, the addition/subtraction
|
||||||
|
// could be parsed as a post-increment
|
||||||
|
} elseif (! $this->isAlphaNum($this->b)) {
|
||||||
$command = self::ACTION_DELETE_A;
|
$command = self::ACTION_DELETE_A;
|
||||||
}
|
}
|
||||||
} elseif ($this->a === "\n") {
|
} elseif ($this->a === "\n") {
|
||||||
@@ -134,7 +132,7 @@ class JSMin {
|
|||||||
}
|
}
|
||||||
} 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;
|
||||||
}
|
}
|
||||||
@@ -156,9 +154,21 @@ class JSMin {
|
|||||||
*/
|
*/
|
||||||
protected function action($command)
|
protected function action($command)
|
||||||
{
|
{
|
||||||
|
if ($command === self::ACTION_DELETE_A_B
|
||||||
|
&& $this->b === ' '
|
||||||
|
&& ($this->a === '+' || $this->a === '-')) {
|
||||||
|
// Note: we're at an addition/substraction operator; the inputIndex
|
||||||
|
// will certainly be a valid index
|
||||||
|
if ($this->input[$this->inputIndex] === $this->a) {
|
||||||
|
// This is "+ +" or "- -". Don't delete the space.
|
||||||
|
$command = self::ACTION_KEEP_A;
|
||||||
|
}
|
||||||
|
}
|
||||||
switch ($command) {
|
switch ($command) {
|
||||||
case self::ACTION_KEEP_A:
|
case self::ACTION_KEEP_A:
|
||||||
$this->output .= $this->a;
|
$this->output .= $this->a;
|
||||||
|
$this->lastByteOut = $this->a;
|
||||||
|
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case self::ACTION_DELETE_A:
|
case self::ACTION_DELETE_A:
|
||||||
$this->a = $this->b;
|
$this->a = $this->b;
|
||||||
@@ -166,6 +176,8 @@ class JSMin {
|
|||||||
$str = $this->a; // in case needed for exception
|
$str = $this->a; // in case needed for exception
|
||||||
while (true) {
|
while (true) {
|
||||||
$this->output .= $this->a;
|
$this->output .= $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;
|
||||||
@@ -178,6 +190,8 @@ class JSMin {
|
|||||||
$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->a = $this->get();
|
$this->a = $this->get();
|
||||||
$str .= $this->a;
|
$str .= $this->a;
|
||||||
}
|
}
|
||||||
@@ -204,6 +218,7 @@ class JSMin {
|
|||||||
. $this->inputIndex .": {$pattern}");
|
. $this->inputIndex .": {$pattern}");
|
||||||
}
|
}
|
||||||
$this->output .= $this->a;
|
$this->output .= $this->a;
|
||||||
|
$this->lastByteOut = $this->a;
|
||||||
}
|
}
|
||||||
$this->b = $this->next();
|
$this->b = $this->next();
|
||||||
}
|
}
|
||||||
|
@@ -1,2 +1,9 @@
|
|||||||
// JSMin should not alter this file
|
a / ++b;
|
||||||
if(!a.id)a.id="dp"+ ++this.uuid;
|
a * --b;
|
||||||
|
a++ - b;
|
||||||
|
a + --b;
|
||||||
|
a - ++b;
|
||||||
|
a + -b;
|
||||||
|
a + ++b;
|
||||||
|
a + --b;
|
||||||
|
a - --b;
|
@@ -1,2 +1 @@
|
|||||||
// JSMin should not alter this file
|
a/++b;a*--b;a++-b;a+--b;a-++b;a+-b;a+ ++b;a+--b;a- --b;
|
||||||
if(!a.id)a.id="dp"+ ++this.uuid;
|
|
@@ -6,7 +6,7 @@ require_once 'JSMin.php';
|
|||||||
function test_JSMin()
|
function test_JSMin()
|
||||||
{
|
{
|
||||||
global $thisDir;
|
global $thisDir;
|
||||||
|
|
||||||
$src = file_get_contents($thisDir . '/_test_files/js/before.js');
|
$src = file_get_contents($thisDir . '/_test_files/js/before.js');
|
||||||
$minExpected = file_get_contents($thisDir . '/_test_files/js/before.min.js');
|
$minExpected = file_get_contents($thisDir . '/_test_files/js/before.min.js');
|
||||||
$minOutput = JSMin::minify($src);
|
$minOutput = JSMin::minify($src);
|
||||||
@@ -16,11 +16,16 @@ function test_JSMin()
|
|||||||
echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n";
|
echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n";
|
||||||
echo "---Source: " .countBytes($src). " bytes\n\n{$src}\n\n\n";
|
echo "---Source: " .countBytes($src). " bytes\n\n{$src}\n\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
$src = file_get_contents($thisDir . '/_test_files/js/issue144.js');
|
$src = file_get_contents($thisDir . '/_test_files/js/issue144.js');
|
||||||
$minExpected = file_get_contents($thisDir . '/_test_files/js/issue144.min.js');
|
$minExpected = file_get_contents($thisDir . '/_test_files/js/issue144.min.js');
|
||||||
$minOutput = JSMin::minify($src);
|
$minOutput = JSMin::minify($src);
|
||||||
$passed = assertTrue($minExpected == $minOutput, 'JSMin : Don\'t minify files with + ++ (Issue 144)');
|
$passed = assertTrue($minExpected == $minOutput, 'JSMin : Handle "+ ++a" syntax (Issue 144)');
|
||||||
|
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
||||||
|
echo "\n---Output: " .countBytes($minOutput). " bytes\n\n{$minOutput}\n\n";
|
||||||
|
echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n";
|
||||||
|
echo "---Source: " .countBytes($src). " bytes\n\n{$src}\n\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
|
if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
|
||||||
$src = file_get_contents($thisDir . '/_test_files/js/issue132.js');
|
$src = file_get_contents($thisDir . '/_test_files/js/issue132.js');
|
||||||
|
Reference in New Issue
Block a user