mirror of
https://github.com/mrclay/minify.git
synced 2025-08-09 23:56:43 +02:00
proper fix for Issue 144: + ++a
This commit is contained in:
@@ -1,19 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* jsmin.php - extended PHP implementation of Douglas Crockford's JSMin.
|
||||
* JSMin.php - modified PHP implementation of Douglas Crockford's JSMin.
|
||||
*
|
||||
* <code>
|
||||
* $minifiedJs = JSMin::minify($js);
|
||||
* </code>
|
||||
*
|
||||
* This is a direct port of jsmin.c to PHP with a few PHP performance tweaks and
|
||||
* modifications to preserve some comments (see below). Also, rather than using
|
||||
* stdin/stdout, JSMin::minify() accepts a string as input and returns another
|
||||
* string as output.
|
||||
* This is a modified port of jsmin.c. Improvements:
|
||||
*
|
||||
* Comments containing IE conditional compilation are preserved, as are multi-line
|
||||
* comments that begin with "/*!" (for documentation purposes). In the latter case
|
||||
* newlines are inserted around the comment to enhance readability.
|
||||
* 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
|
||||
* converted to post-inc/dec. E.g. a + ++b -> a+ ++b
|
||||
*
|
||||
* Preserves multi-line comments that begin with /*!
|
||||
*
|
||||
* PHP 5 or higher is required.
|
||||
*
|
||||
@@ -68,6 +68,7 @@ class JSMin {
|
||||
protected $inputLength = 0;
|
||||
protected $lookAhead = null;
|
||||
protected $output = '';
|
||||
protected $lastByteOut = '';
|
||||
|
||||
/**
|
||||
* Minify Javascript.
|
||||
@@ -87,13 +88,6 @@ class JSMin {
|
||||
public function __construct($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
|
||||
$command = self::ACTION_KEEP_A; // default
|
||||
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;
|
||||
}
|
||||
} elseif ($this->a === "\n") {
|
||||
@@ -156,9 +154,21 @@ class JSMin {
|
||||
*/
|
||||
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) {
|
||||
case self::ACTION_KEEP_A:
|
||||
$this->output .= $this->a;
|
||||
$this->lastByteOut = $this->a;
|
||||
|
||||
// fallthrough
|
||||
case self::ACTION_DELETE_A:
|
||||
$this->a = $this->b;
|
||||
@@ -166,6 +176,8 @@ class JSMin {
|
||||
$str = $this->a; // in case needed for exception
|
||||
while (true) {
|
||||
$this->output .= $this->a;
|
||||
$this->lastByteOut = $this->a;
|
||||
|
||||
$this->a = $this->get();
|
||||
if ($this->a === $this->b) { // end quote
|
||||
break;
|
||||
@@ -178,6 +190,8 @@ class JSMin {
|
||||
$str .= $this->a;
|
||||
if ($this->a === '\\') {
|
||||
$this->output .= $this->a;
|
||||
$this->lastByteOut = $this->a;
|
||||
|
||||
$this->a = $this->get();
|
||||
$str .= $this->a;
|
||||
}
|
||||
@@ -204,6 +218,7 @@ class JSMin {
|
||||
. $this->inputIndex .": {$pattern}");
|
||||
}
|
||||
$this->output .= $this->a;
|
||||
$this->lastByteOut = $this->a;
|
||||
}
|
||||
$this->b = $this->next();
|
||||
}
|
||||
|
@@ -1,2 +1,9 @@
|
||||
// JSMin should not alter this file
|
||||
if(!a.id)a.id="dp"+ ++this.uuid;
|
||||
a / ++b;
|
||||
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
|
||||
if(!a.id)a.id="dp"+ ++this.uuid;
|
||||
a/++b;a*--b;a++-b;a+--b;a-++b;a+-b;a+ ++b;a+--b;a- --b;
|
@@ -20,7 +20,12 @@ function test_JSMin()
|
||||
$src = file_get_contents($thisDir . '/_test_files/js/issue144.js');
|
||||
$minExpected = file_get_contents($thisDir . '/_test_files/js/issue144.min.js');
|
||||
$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)) {
|
||||
$src = file_get_contents($thisDir . '/_test_files/js/issue132.js');
|
||||
|
Reference in New Issue
Block a user