MDL-65744 lib: Update minify minify lib

This commit is contained in:
Mathew May 2019-06-11 13:02:45 +08:00
parent f7e108438f
commit 0918e156a0
9 changed files with 282 additions and 137 deletions

View File

@ -0,0 +1,18 @@
Copyright (c) 2012 Matthias Mullie
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,4 +1,13 @@
<?php
/**
* CSS Minifier
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify;
@ -7,10 +16,11 @@ use MatthiasMullie\PathConverter\ConverterInterface;
use MatthiasMullie\PathConverter\Converter;
/**
* CSS minifier.
* CSS minifier
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @package Minify
* @author Matthias Mullie <minify@mullie.eu>
* @author Tijs Verkoyen <minify@verkoyen.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
@ -19,12 +29,12 @@ use MatthiasMullie\PathConverter\Converter;
class CSS extends Minify
{
/**
* @var int
* @var int maximum inport size in kB
*/
protected $maxImportSize = 5;
/**
* @var string[]
* @var string[] valid import extensions
*/
protected $importExtensions = array(
'gif' => 'data:image/gif',
@ -76,14 +86,14 @@ class CSS extends Minify
*/
protected function moveImportsToTop($content)
{
if (preg_match_all('/@import[^;]+;/', $content, $matches)) {
if (preg_match_all('/(;?)(@import (?<url>url\()?(?P<quotes>["\']?).+?(?P=quotes)(?(url)\)));?/', $content, $matches)) {
// remove from content
foreach ($matches[0] as $import) {
$content = str_replace($import, '', $content);
}
// add to top
$content = implode('', $matches[0]).$content;
$content = implode(';', $matches[2]).';'.trim($content, ';');
}
return $content;
@ -207,6 +217,8 @@ class CSS extends Minify
// grab referenced file & minify it (which may include importing
// yet other @import statements recursively)
$minifier = new static($importPath);
$minifier->setMaxImportSize($this->maxImportSize);
$minifier->setImportExtensions($this->importExtensions);
$importContent = $minifier->execute($source, $parents);
// check if this is only valid for certain media
@ -295,10 +307,11 @@ class CSS extends Minify
*/
$this->extractStrings();
$this->stripComments();
$this->extractCalcs();
$css = $this->replace($css);
$css = $this->stripWhitespace($css);
$css = $this->shortenHex($css);
$css = $this->shortenColors($css);
$css = $this->shortenZeroes($css);
$css = $this->shortenFontWeights($css);
$css = $this->stripEmptyTags($css);
@ -469,12 +482,16 @@ class CSS extends Minify
*
* @return string
*/
protected function shortenHex($content)
protected function shortenColors($content)
{
$content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?=[; }])/i', '#$1$2$3', $content);
$content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?:([0-9a-z])\\4)?(?=[; }])/i', '#$1$2$3$4', $content);
// remove alpha channel if it's pointless...
$content = preg_replace('/(?<=[: ])#([0-9a-z]{6})ff?(?=[; }])/i', '#$1', $content);
$content = preg_replace('/(?<=[: ])#([0-9a-z]{3})f?(?=[; }])/i', '#$1', $content);
// we can shorten some even more by replacing them with their color name
$colors = array(
// we can shorten some even more by replacing them with their color name
'#F0FFFF' => 'azure',
'#F5F5DC' => 'beige',
'#A52A2A' => 'brown',
@ -502,6 +519,9 @@ class CSS extends Minify
'#FF6347' => 'tomato',
'#EE82EE' => 'violet',
'#F5DEB3' => 'wheat',
// or the other way around
'WHITE' => '#fff',
'BLACK' => '#000',
);
return preg_replace_callback(
@ -543,6 +563,12 @@ class CSS extends Minify
*/
protected function shortenZeroes($content)
{
// we don't want to strip units in `calc()` expressions:
// `5px - 0px` is valid, but `5px - 0` is not
// `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
// `10 * 0` is invalid
// we've extracted calcs earlier, so we don't need to worry about this
// reusable bits of code throughout these regexes:
// before & after are used to make sure we don't match lose unintended
// 0-like values (e.g. in #000, or in http://url/1.0)
@ -571,28 +597,11 @@ class CSS extends Minify
// strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
$content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);
// remove zeroes where they make no sense in calc: e.g. calc(100px - 0)
// the 0 doesn't have any effect, and this isn't even valid without unit
// strip all `+ 0` or `- 0` occurrences: calc(10% + 0) -> calc(10%)
// looped because there may be multiple 0s inside 1 group of parentheses
do {
$previous = $content;
$content = preg_replace('/\(([^\(\)]+) [\+\-] 0( [^\(\)]+)?\)/', '(\\1\\2)', $content);
} while ($content !== $previous);
// strip all `0 +` occurrences: calc(0 + 10%) -> calc(10%)
$content = preg_replace('/\(0 \+ ([^\(\)]+)\)/', '(\\1)', $content);
// strip all `0 -` occurrences: calc(0 - 10%) -> calc(-10%)
$content = preg_replace('/\(0 \- ([^\(\)]+)\)/', '(-\\1)', $content);
// I'm not going to attempt to optimize away `x * 0` instances:
// it's dumb enough code already that it likely won't occur, and it's
// too complex to do right (order of operations would have to be
// respected etc)
// what I cared about most here was fixing incorrectly truncated units
// IE doesn't seem to understand a unitless flex-basis value, so let's
// add it in again (make it `%`, which is only 1 char: 0%, 0px, 0
// anything, it's all just the same)
$content = preg_replace('/flex:([^ ]+ [^ ]+ )0([;\}])/', 'flex:${1}0%${2}', $content);
// IE doesn't seem to understand a unitless flex-basis value (correct -
// it goes against the spec), so let's add it in again (make it `%`,
// which is only 1 char: 0%, 0px, 0 anything, it's all just the same)
// @see https://developer.mozilla.org/nl/docs/Web/CSS/flex
$content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content);
$content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
return $content;
@ -607,7 +616,10 @@ class CSS extends Minify
*/
protected function stripEmptyTags($content)
{
return preg_replace('/(^|\}|;)[^\{\};]+\{\s*\}/', '\\1', $content);
$content = preg_replace('/(?<=^)[^\{\};]+\{\s*\}/', '', $content);
$content = preg_replace('/(?<=(\}|;))[^\{\};]+\{\s*\}/', '', $content);
return $content;
}
/**
@ -615,6 +627,17 @@ class CSS extends Minify
*/
protected function stripComments()
{
// PHP only supports $this inside anonymous functions since 5.4
$minifier = $this;
$callback = function ($match) use ($minifier) {
$count = count($minifier->extracted);
$placeholder = '/*'.$count.'*/';
$minifier->extracted[$placeholder] = $match[0];
return $placeholder;
};
$this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback);
$this->registerPattern('/\/\*.*?\*\//s', '');
}
@ -637,8 +660,8 @@ class CSS extends Minify
// remove whitespace around meta characters
// inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
$content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
$content = preg_replace('/([\[(:])\s+/', '$1', $content);
$content = preg_replace('/\s+([\]\)])/', '$1', $content);
$content = preg_replace('/([\[(:>\+])\s+/', '$1', $content);
$content = preg_replace('/\s+([\]\)>\+])/', '$1', $content);
$content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
// whitespace around + and - can only be stripped inside some pseudo-
@ -654,6 +677,40 @@ class CSS extends Minify
return trim($content);
}
/**
* Replace all `calc()` occurrences.
*/
protected function extractCalcs()
{
// PHP only supports $this inside anonymous functions since 5.4
$minifier = $this;
$callback = function ($match) use ($minifier) {
$length = strlen($match[1]);
$expr = '';
$opened = 0;
for ($i = 0; $i < $length; $i++) {
$char = $match[1][$i];
$expr .= $char;
if ($char === '(') {
$opened++;
} elseif ($char === ')' && --$opened === 0) {
break;
}
}
$rest = str_replace($expr, '', $match[1]);
$expr = trim(substr($expr, 1, -1));
$count = count($minifier->extracted);
$placeholder = 'calc('.$count.')';
$minifier->extracted[$placeholder] = 'calc('.$expr.')';
return $placeholder.$rest;
};
$this->registerPattern('/calc(\(.+?)(?=$|;|calc\()/', $callback);
}
/**
* Check if file is small enough to be imported.
*

View File

@ -1,10 +1,18 @@
<?php
/**
* Base Exception
*
* @deprecated Use Exceptions\BasicException instead
*
* @author Matthias Mullie <minify@mullie.eu>
*/
namespace MatthiasMullie\Minify;
/**
* Base Exception Class
* @deprecated Use Exceptions\BasicException instead
*
* @package Minify
* @author Matthias Mullie <minify@mullie.eu>
*/
abstract class Exception extends \Exception

View File

@ -1,10 +1,21 @@
<?php
/**
* Basic exception
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify\Exceptions;
use MatthiasMullie\Minify\Exception;
/**
* Basic Exception Class
*
* @package Minify\Exception
* @author Matthias Mullie <minify@mullie.eu>
*/
abstract class BasicException extends Exception

View File

@ -1,8 +1,19 @@
<?php
/**
* File Import Exception
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify\Exceptions;
/**
* File Import Exception Class
*
* @package Minify\Exception
* @author Matthias Mullie <minify@mullie.eu>
*/
class FileImportException extends BasicException

View File

@ -1,8 +1,19 @@
<?php
/**
* IO Exception
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify\Exceptions;
/**
* IO Exception Class
*
* @package Minify\Exception
* @author Matthias Mullie <minify@mullie.eu>
*/
class IOException extends BasicException

View File

@ -1,13 +1,22 @@
<?php
namespace MatthiasMullie\Minify;
/**
* JavaScript minifier.
* JavaScript minifier
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify;
/**
* JavaScript Minifier Class
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @package Minify
* @author Matthias Mullie <minify@mullie.eu>
* @author Tijs Verkoyen <minify@verkoyen.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
@ -110,11 +119,6 @@ class JS extends Minify
*/
protected $operatorsAfter = array();
/**
* @var array
*/
protected $nestedExtracted = array();
/**
* {@inheritdoc}
*/
@ -144,19 +148,6 @@ class JS extends Minify
{
$content = '';
// loop files
foreach ($this->data as $source => $js) {
/*
* Combine js: separating the scripts by a ;
* I'm also adding a newline: it will be eaten when whitespace is
* stripped, but we need to make sure we're not just appending
* a new script right after a previous script that ended with a
* singe-line comment on the last line (in which case it would also
* be seen as part of that comment)
*/
$content .= $js."\n;";
}
/*
* Let's first take out strings, comments and regular expressions.
* All of these can contain JS code-like characters, and we should make
@ -171,11 +162,24 @@ class JS extends Minify
$this->extractStrings('\'"`');
$this->stripComments();
$this->extractRegex();
$content = $this->replace($content);
$content = $this->propertyNotation($content);
$content = $this->shortenBools($content);
$content = $this->stripWhitespace($content);
// loop files
foreach ($this->data as $source => $js) {
// take out strings, comments & regex (for which we've registered
// the regexes just a few lines earlier)
$js = $this->replace($js);
$js = $this->propertyNotation($js);
$js = $this->shortenBools($js);
$js = $this->stripWhitespace($js);
// combine js: separating the scripts by a ;
$content .= $js.";";
}
// clean up leftover `;`s from the combination of multiple scripts
$content = ltrim($content, ';');
$content = (string) substr($content, 0, -1);
/*
* Earlier, we extracted strings & regular expressions and replaced them
@ -191,11 +195,21 @@ class JS extends Minify
*/
protected function stripComments()
{
// PHP only supports $this inside anonymous functions since 5.4
$minifier = $this;
$callback = function ($match) use ($minifier) {
$count = count($minifier->extracted);
$placeholder = '/*'.$count.'*/';
$minifier->extracted[$placeholder] = $match[0];
return $placeholder;
};
// multi-line comments
$this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback);
$this->registerPattern('/\/\*.*?\*\//s', '');
// single-line comments
$this->registerPattern('/\/\/.*$/m', '');
// multi-line comments
$this->registerPattern('/\/\*.*?\*\//s', '');
}
/**
@ -222,38 +236,26 @@ class JS extends Minify
$callback = function ($match) use ($minifier) {
$count = count($minifier->extracted);
$placeholder = '"'.$count.'"';
$minifier->extracted[$placeholder] = $match['regex'];
$minifier->extracted[$placeholder] = $match[0];
// because we're also trying to find regular expressions that follow
// if/when/for statements, we should also make sure that the content
// within these statements is also minified...
// e.g. `if("some string"/* or comment */)` should become
// `if("some string")`
if (isset($match['before'])) {
$other = new static();
$other->extractStrings('\'"`', "$count-");
$other->stripComments();
$match['before'] = $other->replace($match['before']);
$this->nestedExtracted += $other->extracted;
}
return (isset($match['before']) ? $match['before'] : '').
$placeholder.
(isset($match['after']) ? $match['after'] : '');
return $placeholder;
};
$pattern = '(?P<regex>\/.+?((?<!\\\\)\\\\\\\\)*\/[gimy]*)(?![0-9a-zA-Z\/])';
// match all chars except `/` and `\`
// `\` is allowed though, along with whatever char follows (which is the
// one being escaped)
// this should allow all chars, except for an unescaped `/` (= the one
// closing the regex)
// then also ignore bare `/` inside `[]`, where they don't need to be
// escaped: anything inside `[]` can be ignored safely
$pattern = '\\/(?!\*)(?:[^\\[\\/\\\\\n\r]++|(?:\\\\.)++|(?:\\[(?:[^\\]\\\\\n\r]++|(?:\\\\.)++)++\\])++)++\\/[gimuy]*';
// a regular expression can only be followed by a few operators or some
// of the RegExp methods (a `\` followed by a variable or value is
// likely part of a division, not a regex)
$keywords = array('do', 'in', 'new', 'else', 'throw', 'yield', 'delete', 'return', 'typeof');
$before = '(?P<before>[=:,;\}\(\{&\|!]|^|'.implode('|', $keywords).')';
$before = '([=:,;\+\-\*\/\}\(\{\[&\|!]|^|'.implode('|', $keywords).')\s*';
$propertiesAndMethods = array(
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties
'prototype',
'length',
'lastIndex',
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties_2
'constructor',
'flags',
@ -267,29 +269,28 @@ class JS extends Minify
'compile(',
'exec(',
'test(',
'match',
'replace(',
'search(',
'split(',
'toSource(',
'toString(',
);
$delimiters = array_fill(0, count($propertiesAndMethods), '/');
$propertiesAndMethods = array_map('preg_quote', $propertiesAndMethods, $delimiters);
$after = '(?P<after>[\.,;\)\}&\|+]|$|\.('.implode('|', $propertiesAndMethods).'))';
$this->registerPattern('/'.$before.'\s*'.$pattern.'\s*'.$after.'/', $callback);
$after = '(?=\s*([\.,;\)\}&\|+]|\/\/|$|\.('.implode('|', $propertiesAndMethods).')))';
$this->registerPattern('/'.$before.'\K'.$pattern.$after.'/', $callback);
// we didn't check for regular expressions after `)`, because that is
// more often than not not a character where a regex can follow (e.g.
// (1+2)/3/4 -> /3/ could be considered a regex, but it's not)
// however, after single-line if/while/for, there could very well be a
// regex after `)` (e.g. if(true)/regex/)
// there is one problem, though: it's (near) impossible to check for
// when the if/while/for statement is closed (same amount of closing
// brackets as there were opened), so I'll ignore single-line statements
// with nested brackets followed by a regex for now...
$before = '(?P<before>\b(if|while|for)\s*\((?P<code>[^\(]+?)\))';
$this->registerPattern('/'.$before.'\s*'.$pattern.'\s*'.$after.'/', $callback);
// regular expressions following a `)` are rather annoying to detect...
// quite often, `/` after `)` is a division operator & if it happens to
// be followed by another one (or a comment), it is likely to be
// confused for a regular expression
// however, it's perfectly possible for a regex to follow a `)`: after
// a single-line `if()`, `while()`, ... statement, for example
// since, when they occur like that, they're always the start of a
// statement, there's only a limited amount of ways they can be useful:
// by calling the regex methods directly
// if a regex following `)` is not followed by `.<property or method>`,
// it's quite likely not a regex
$before = '\)\s*';
$after = '(?=\s*\.('.implode('|', $propertiesAndMethods).'))';
$this->registerPattern('/'.$before.'\K'.$pattern.$after.'/', $callback);
// 1 more edge case: a regex can be followed by a lot more operators or
// keywords if there's a newline (ASI) in between, where the operator
@ -297,25 +298,8 @@ class JS extends Minify
// (https://github.com/matthiasmullie/minify/issues/56)
$operators = $this->getOperatorsForRegex($this->operatorsBefore, '/');
$operators += $this->getOperatorsForRegex($this->keywordsReserved, '/');
$after = '(?P<after>\n\s*('.implode('|', $operators).'))';
$this->registerPattern('/'.$pattern.'\s*'.$after.'/', $callback);
}
/**
* In addition to the regular restore routine, we also need to restore a few
* more things that have been extracted as part of the regex extraction...
*
* {@inheritdoc}
*/
protected function restoreExtractedData($content)
{
// restore regular extracted stuff
$content = parent::restoreExtractedData($content);
// restore nested stuff from within regex extraction
$content = strtr($content, $this->nestedExtracted);
return $content;
$after = '(?=\s*\n\s*('.implode('|', $operators).'))';
$this->registerPattern('/'.$pattern.$after.'/', $callback);
}
/**
@ -361,7 +345,9 @@ class JS extends Minify
array(
'/('.implode('|', $operatorsBefore).')\s+/',
'/\s+('.implode('|', $operatorsAfter).')/',
), '\\1', $content
),
'\\1',
$content
);
// make sure + and - can't be mistaken for, or joined into ++ and --
@ -369,7 +355,9 @@ class JS extends Minify
array(
'/(?<![\+\-])\s*([\+\-])(?![\+\-])/',
'/(?<![\+\-])([\+\-])\s*(?![\+\-])/',
), '\\1', $content
),
'\\1',
$content
);
// collapse whitespace around reserved words into single space
@ -387,6 +375,16 @@ class JS extends Minify
$content = preg_replace('/('.implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content);
$content = preg_replace('/[^\S\n]+('.implode('|', $operatorsDiffAfter).')/', '\\1', $content);
/*
* Whitespace after `return` can be omitted in a few occasions
* (such as when followed by a string or regex)
* Same for whitespace in between `)` and `{`, or between `{` and some
* keywords.
*/
$content = preg_replace('/\breturn\s+(["\'\/\+\-])/', 'return$1', $content);
$content = preg_replace('/\)\s+\{/', '){', $content);
$content = preg_replace('/}\n(else|catch|finally)\b/', '}$1', $content);
/*
* Get rid of double semicolons, except where they can be used like:
* "for(v=1,_=b;;)", "for(v=1;;v++)" or "for(;;ja||(ja=true))".
@ -404,12 +402,19 @@ class JS extends Minify
* semicolon), like: `for(i=1;i<3;i++);`, of `for(i in list);`
* Here, nothing happens during the loop; it's just used to keep
* increasing `i`. With that ; omitted, the next line would be expected
* to be the for-loop's body...
* to be the for-loop's body... Same goes for while loops.
* I'm going to double that semicolon (if any) so after the next line,
* which strips semicolons here & there, we're still left with this one.
*/
$content = preg_replace('/(for\([^;\{]*;[^;\{]*;[^;\{]*\));(\}|$)/s', '\\1;;\\2', $content);
$content = preg_replace('/(for\([^;\{]+\s+in\s+[^;\{]+\));(\}|$)/s', '\\1;;\\2', $content);
/*
* Below will also keep `;` after a `do{}while();` along with `while();`
* While these could be stripped after do-while, detecting this
* distinction is cumbersome, so I'll play it safe and make sure `;`
* after any kind of `while` is kept.
*/
$content = preg_replace('/(while\([^;\{]+\));(\}|$)/s', '\\1;;\\2', $content);
/*
* We also can't strip empty else-statements. Even though they're

View File

@ -1,5 +1,13 @@
<?php
/**
* Abstract minifier class
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify;
use MatthiasMullie\Minify\Exceptions\IOException;
@ -10,6 +18,7 @@ use Psr\Cache\CacheItemInterface;
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @package Minify
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
@ -230,6 +239,12 @@ abstract class Minify
foreach ($this->patterns as $i => $pattern) {
list($pattern, $replacement) = $pattern;
// we can safely ignore patterns for positions we've unset earlier,
// because we know these won't show up anymore
if (array_key_exists($i, $positions) == false) {
continue;
}
// no need to re-run matches that are still in the part of the
// content that hasn't been processed
if ($positions[$i] >= 0) {
@ -237,19 +252,18 @@ abstract class Minify
}
$match = null;
if (preg_match($pattern, $content, $match)) {
if (preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE)) {
$matches[$i] = $match;
// we'll store the match position as well; that way, we
// don't have to redo all preg_matches after changing only
// the first (we'll still know where those others are)
$positions[$i] = strpos($content, $match[0]);
$positions[$i] = $match[0][1];
} else {
// if the pattern couldn't be matched, there's no point in
// executing it again in later runs on this same content;
// ignore this one until we reach end of content
unset($matches[$i]);
$positions[$i] = strlen($content);
unset($matches[$i], $positions[$i]);
}
}
@ -264,7 +278,7 @@ abstract class Minify
// other found was not inside what the first found)
$discardLength = min($positions);
$firstPattern = array_search($discardLength, $positions);
$match = $matches[$firstPattern][0];
$match = $matches[$firstPattern][0][0];
// execute the pattern that matches earliest in the content string
list($pattern, $replacement) = $this->patterns[$firstPattern];
@ -272,7 +286,7 @@ abstract class Minify
// figure out which part of the string was unmatched; that's the
// part we'll execute the patterns on again next
$content = substr($content, $discardLength);
$content = (string) substr($content, $discardLength);
$unmatched = (string) substr($content, strpos($content, $match) + strlen($match));
// move the replaced part to $processed and prepare $content to
@ -396,6 +410,16 @@ abstract class Minify
*/
protected function canImportFile($path)
{
$parsed = parse_url($path);
if (
// file is elsewhere
isset($parsed['host']) ||
// file responds to queries (may change, or need to bypass cache)
isset($parsed['query'])
) {
return false;
}
return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path);
}

View File

@ -53,7 +53,7 @@
<location>minify/matthiasmullie-minify</location>
<name>MatthiasMullie\Minify</name>
<license>MIT</license>
<version>1.3.51</version>
<version>1.3.61</version>
<licenseversion></licenseversion>
</library>
<library>