mirror of
https://github.com/mrclay/minify.git
synced 2025-08-08 07:06:49 +02:00
builder/index.php : fix Issue 67
Minify.php : allow minifier = '' Minify/CSS.php : more extensible (Issue 64) Minify/HTML.php : more extensible Minify/Lines.php : fix Issue 55 Minify/Packer.php : usability test_environment.php : test DOCUMENT_ROOT test_Minify_Lines.php : test Issue 55
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// check for auto-encoding
|
// check for auto-encoding
|
||||||
$encodeOutput = ! ini_get('zlib.output_compression');
|
$encodeOutput = (function_exists('gzdeflate')
|
||||||
|
&& !ini_get('zlib.output_compression'));
|
||||||
|
|
||||||
require dirname(__FILE__) . '/../config.php';
|
require dirname(__FILE__) . '/../config.php';
|
||||||
|
|
||||||
|
@@ -12,4 +12,23 @@
|
|||||||
return array(
|
return array(
|
||||||
// 'js' => array('//js/file1.js', '//js/file2.js'),
|
// 'js' => array('//js/file1.js', '//js/file2.js'),
|
||||||
// 'css' => array('//css/file1.css', '//css/file2.css'),
|
// 'css' => array('//css/file1.css', '//css/file2.css'),
|
||||||
|
|
||||||
|
// custom source example
|
||||||
|
/*'js2' => array(
|
||||||
|
dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
|
||||||
|
// do NOT process this file
|
||||||
|
new Minify_Source(array(
|
||||||
|
'filepath' => dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
|
||||||
|
'minifier' => create_function('$a', 'return $a;')
|
||||||
|
))
|
||||||
|
),//*/
|
||||||
|
|
||||||
|
/*'js3' => array(
|
||||||
|
dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
|
||||||
|
// do NOT process this file
|
||||||
|
new Minify_Source(array(
|
||||||
|
'filepath' => dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
|
||||||
|
'minifier' => array('Minify_Packer', 'minify')
|
||||||
|
))
|
||||||
|
),//*/
|
||||||
);
|
);
|
@@ -56,9 +56,9 @@ class Minify {
|
|||||||
* need to recombine files, minify and encode the output.
|
* need to recombine files, minify and encode the output.
|
||||||
*
|
*
|
||||||
* @param mixed $cache object with identical interface as Minify_Cache_File or
|
* @param mixed $cache object with identical interface as Minify_Cache_File or
|
||||||
* a directory path. (default = '')
|
* a directory path. (default = '')
|
||||||
*
|
*
|
||||||
* @param bool $fileLocking (default = true) This only applies if the first
|
* @param bool $fileLocking (default = true) This only applies if the first
|
||||||
* parameter is a string.
|
* parameter is a string.
|
||||||
*
|
*
|
||||||
* @return null
|
* @return null
|
||||||
@@ -347,17 +347,17 @@ class Minify {
|
|||||||
*/
|
*/
|
||||||
public static function setDocRoot($unsetPathInfo = false)
|
public static function setDocRoot($unsetPathInfo = false)
|
||||||
{
|
{
|
||||||
if (isset($_SERVER['SERVER_SOFTWARE'])
|
if (isset($_SERVER['SERVER_SOFTWARE'])
|
||||||
&& 0 === strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/')
|
&& 0 === strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/')
|
||||||
) {
|
) {
|
||||||
$_SERVER['DOCUMENT_ROOT'] = substr(
|
$_SERVER['DOCUMENT_ROOT'] = substr(
|
||||||
$_SERVER['PATH_TRANSLATED']
|
$_SERVER['PATH_TRANSLATED']
|
||||||
,0
|
,0
|
||||||
,strlen($_SERVER['PATH_TRANSLATED']) - strlen($_SERVER['SCRIPT_NAME'])
|
,strlen($_SERVER['PATH_TRANSLATED']) - strlen($_SERVER['SCRIPT_NAME'])
|
||||||
);
|
);
|
||||||
if ($unsetPathInfo) {
|
if ($unsetPathInfo) {
|
||||||
unset($_SERVER['PATH_INFO']);
|
unset($_SERVER['PATH_INFO']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +439,7 @@ class Minify {
|
|||||||
$options = (null !== $source->minifyOptions)
|
$options = (null !== $source->minifyOptions)
|
||||||
? array_merge($defaultOptions, $source->minifyOptions)
|
? array_merge($defaultOptions, $source->minifyOptions)
|
||||||
: $defaultOptions;
|
: $defaultOptions;
|
||||||
if ($defaultMinifier) {
|
if ($minifier) {
|
||||||
self::$_controller->loadMinifier($minifier);
|
self::$_controller->loadMinifier($minifier);
|
||||||
// get source content and minify it
|
// get source content and minify it
|
||||||
$pieces[] = call_user_func($minifier, $source->getContent(), $options);
|
$pieces[] = call_user_func($minifier, $source->getContent(), $options);
|
||||||
|
@@ -1,322 +1,330 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Class Minify_CSS
|
* Class Minify_CSS
|
||||||
* @package Minify
|
* @package Minify
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compress CSS
|
* Compress CSS
|
||||||
*
|
*
|
||||||
* This is a heavy regex-based removal of whitespace, unnecessary
|
* This is a heavy regex-based removal of whitespace, unnecessary
|
||||||
* comments and tokens, and some CSS value minimization, where practical.
|
* comments and tokens, and some CSS value minimization, where practical.
|
||||||
* Many steps have been taken to avoid breaking comment-based hacks,
|
* Many steps have been taken to avoid breaking comment-based hacks,
|
||||||
* including the ie5/mac filter (and its inversion), but expect tricky
|
* including the ie5/mac filter (and its inversion), but expect tricky
|
||||||
* hacks involving comment tokens in 'content' value strings to break
|
* hacks involving comment tokens in 'content' value strings to break
|
||||||
* minimization badly. A test suite is available.
|
* minimization badly. A test suite is available.
|
||||||
*
|
*
|
||||||
* @package Minify
|
* @package Minify
|
||||||
* @author Stephen Clay <steve@mrclay.org>
|
* @author Stephen Clay <steve@mrclay.org>
|
||||||
*/
|
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
|
||||||
class Minify_CSS {
|
*/
|
||||||
|
class Minify_CSS {
|
||||||
/**
|
|
||||||
* Minify a CSS string
|
/**
|
||||||
*
|
* Defines which class to call as part of callbacks, change this
|
||||||
* @param string $css
|
* if you extend Minify_CSS
|
||||||
*
|
* @var string
|
||||||
* @param array $options available options:
|
*/
|
||||||
*
|
protected static $className = 'Minify_CSS';
|
||||||
* 'preserveComments': (default true) multi-line comments that begin
|
|
||||||
* with "/*!" will be preserved with newlines before and after to
|
/**
|
||||||
* enhance readability.
|
* Minify a CSS string
|
||||||
*
|
*
|
||||||
* 'prependRelativePath': (default null) if given, this string will be
|
* @param string $css
|
||||||
* prepended to all relative URIs in import/url declarations
|
*
|
||||||
*
|
* @param array $options available options:
|
||||||
* 'currentDir': (default null) if given, this is assumed to be the
|
*
|
||||||
* directory of the current CSS file. Using this, minify will rewrite
|
* 'preserveComments': (default true) multi-line comments that begin
|
||||||
* all relative URIs in import/url declarations to correctly point to
|
* with "/*!" will be preserved with newlines before and after to
|
||||||
* the desired files. For this to work, the files *must* exist and be
|
* enhance readability.
|
||||||
* visible by the PHP process.
|
*
|
||||||
*
|
* 'prependRelativePath': (default null) if given, this string will be
|
||||||
* @return string
|
* prepended to all relative URIs in import/url declarations
|
||||||
*/
|
*
|
||||||
public static function minify($css, $options = array())
|
* 'currentDir': (default null) if given, this is assumed to be the
|
||||||
{
|
* directory of the current CSS file. Using this, minify will rewrite
|
||||||
if (isset($options['preserveComments'])
|
* all relative URIs in import/url declarations to correctly point to
|
||||||
&& !$options['preserveComments']) {
|
* the desired files. For this to work, the files *must* exist and be
|
||||||
return self::_minify($css, $options);
|
* visible by the PHP process.
|
||||||
}
|
*
|
||||||
require_once 'Minify/CommentPreserver.php';
|
* @return string
|
||||||
// recursive calls don't preserve comments
|
*/
|
||||||
$options['preserveComments'] = false;
|
public static function minify($css, $options = array())
|
||||||
return Minify_CommentPreserver::process(
|
{
|
||||||
$css
|
if (isset($options['preserveComments'])
|
||||||
,array('Minify_CSS', 'minify')
|
&& !$options['preserveComments']) {
|
||||||
,array($options)
|
return self::_minify($css, $options);
|
||||||
);
|
}
|
||||||
}
|
require_once 'Minify/CommentPreserver.php';
|
||||||
|
// recursive calls don't preserve comments
|
||||||
/**
|
$options['preserveComments'] = false;
|
||||||
* Minify a CSS string
|
return Minify_CommentPreserver::process(
|
||||||
*
|
$css
|
||||||
* @param string $css
|
,array(self::$className, 'minify')
|
||||||
*
|
,array($options)
|
||||||
* @param array $options To enable URL rewriting, set the value
|
);
|
||||||
* for key 'prependRelativePath'.
|
}
|
||||||
*
|
|
||||||
* @return string
|
/**
|
||||||
*/
|
* Minify a CSS string
|
||||||
protected static function _minify($css, $options)
|
*
|
||||||
{
|
* @param string $css
|
||||||
$css = str_replace("\r\n", "\n", $css);
|
*
|
||||||
|
* @param array $options To enable URL rewriting, set the value
|
||||||
// preserve empty comment after '>'
|
* for key 'prependRelativePath'.
|
||||||
// http://www.webdevout.net/css-hacks#in_css-selectors
|
*
|
||||||
$css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
|
* @return string
|
||||||
|
*/
|
||||||
// preserve empty comment between property and value
|
protected static function _minify($css, $options)
|
||||||
// http://css-discuss.incutio.com/?page=BoxModelHack
|
{
|
||||||
$css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
|
$css = str_replace("\r\n", "\n", $css);
|
||||||
$css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
|
|
||||||
|
// preserve empty comment after '>'
|
||||||
// apply callback to all valid comments (and strip out surrounding ws
|
// http://www.webdevout.net/css-hacks#in_css-selectors
|
||||||
self::$_inHack = false;
|
$css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
|
||||||
$css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@'
|
|
||||||
,array('Minify_CSS', '_commentCB'), $css);
|
// preserve empty comment between property and value
|
||||||
|
// http://css-discuss.incutio.com/?page=BoxModelHack
|
||||||
// remove ws around { } and last semicolon in declaration block
|
$css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
|
||||||
$css = preg_replace('/\\s*{\\s*/', '{', $css);
|
$css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
|
||||||
$css = preg_replace('/;?\\s*}\\s*/', '}', $css);
|
|
||||||
|
// apply callback to all valid comments (and strip out surrounding ws
|
||||||
// remove ws surrounding semicolons
|
self::$_inHack = false;
|
||||||
$css = preg_replace('/\\s*;\\s*/', ';', $css);
|
$css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@'
|
||||||
|
,array(self::$className, '_commentCB'), $css);
|
||||||
// remove ws around urls
|
|
||||||
$css = preg_replace('/
|
// remove ws around { } and last semicolon in declaration block
|
||||||
url\\( # url(
|
$css = preg_replace('/\\s*{\\s*/', '{', $css);
|
||||||
\\s*
|
$css = preg_replace('/;?\\s*}\\s*/', '}', $css);
|
||||||
([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
|
|
||||||
\\s*
|
// remove ws surrounding semicolons
|
||||||
\\) # )
|
$css = preg_replace('/\\s*;\\s*/', ';', $css);
|
||||||
/x', 'url($1)', $css);
|
|
||||||
|
// remove ws around urls
|
||||||
// remove ws between rules and colons
|
$css = preg_replace('/
|
||||||
$css = preg_replace('/
|
url\\( # url(
|
||||||
\\s*
|
\\s*
|
||||||
([{;]) # 1 = beginning of block or rule separator
|
([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
|
||||||
\\s*
|
\\s*
|
||||||
([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
|
\\) # )
|
||||||
\\s*
|
/x', 'url($1)', $css);
|
||||||
:
|
|
||||||
\\s*
|
// remove ws between rules and colons
|
||||||
(\\b|[#\'"]) # 3 = first character of a value
|
$css = preg_replace('/
|
||||||
/x', '$1$2:$3', $css);
|
\\s*
|
||||||
|
([{;]) # 1 = beginning of block or rule separator
|
||||||
// remove ws in selectors
|
\\s*
|
||||||
$css = preg_replace_callback('/
|
([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
|
||||||
(?: # non-capture
|
\\s*
|
||||||
\\s*
|
:
|
||||||
[^~>+,\\s]+ # selector part
|
\\s*
|
||||||
\\s*
|
(\\b|[#\'"]) # 3 = first character of a value
|
||||||
[,>+~] # combinators
|
/x', '$1$2:$3', $css);
|
||||||
)+
|
|
||||||
\\s*
|
// remove ws in selectors
|
||||||
[^~>+,\\s]+ # selector part
|
$css = preg_replace_callback('/
|
||||||
{ # open declaration block
|
(?: # non-capture
|
||||||
/x'
|
\\s*
|
||||||
,array('Minify_CSS', '_selectorsCB'), $css);
|
[^~>+,\\s]+ # selector part
|
||||||
|
\\s*
|
||||||
// minimize hex colors
|
[,>+~] # combinators
|
||||||
$css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i'
|
)+
|
||||||
, '$1#$2$3$4$5', $css);
|
\\s*
|
||||||
|
[^~>+,\\s]+ # selector part
|
||||||
// remove spaces between font families
|
{ # open declaration block
|
||||||
$css = preg_replace_callback('/font-family:([^;}]+)([;}])/'
|
/x'
|
||||||
,array('Minify_CSS', '_fontFamilyCB'), $css);
|
,array(self::$className, '_selectorsCB'), $css);
|
||||||
|
|
||||||
$css = preg_replace('/@import\\s+url/', '@import url', $css);
|
// minimize hex colors
|
||||||
|
$css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i'
|
||||||
// replace any ws involving newlines with a single newline
|
, '$1#$2$3$4$5', $css);
|
||||||
$css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css);
|
|
||||||
|
// remove spaces between font families
|
||||||
// separate common descendent selectors w/ newlines (to limit line lengths)
|
$css = preg_replace_callback('/font-family:([^;}]+)([;}])/'
|
||||||
$css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css);
|
,array(self::$className, '_fontFamilyCB'), $css);
|
||||||
|
|
||||||
// Use newline after 1st numeric value (to limit line lengths).
|
$css = preg_replace('/@import\\s+url/', '@import url', $css);
|
||||||
$css = preg_replace('/
|
|
||||||
((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
|
// replace any ws involving newlines with a single newline
|
||||||
\\s+
|
$css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css);
|
||||||
/x'
|
|
||||||
,"$1\n", $css);
|
// separate common descendent selectors w/ newlines (to limit line lengths)
|
||||||
|
$css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css);
|
||||||
$rewrite = false;
|
|
||||||
if (isset($options['prependRelativePath'])) {
|
// Use newline after 1st numeric value (to limit line lengths).
|
||||||
self::$_tempPrepend = $options['prependRelativePath'];
|
$css = preg_replace('/
|
||||||
$rewrite = true;
|
((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
|
||||||
} elseif (isset($options['currentDir'])) {
|
\\s+
|
||||||
self::$_tempCurrentDir = $options['currentDir'];
|
/x'
|
||||||
$rewrite = true;
|
,"$1\n", $css);
|
||||||
}
|
|
||||||
if ($rewrite) {
|
$rewrite = false;
|
||||||
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
if (isset($options['prependRelativePath'])) {
|
||||||
,array('Minify_CSS', '_urlCB'), $css);
|
self::$_tempPrepend = $options['prependRelativePath'];
|
||||||
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
$rewrite = true;
|
||||||
,array('Minify_CSS', '_urlCB'), $css);
|
} elseif (isset($options['currentDir'])) {
|
||||||
}
|
self::$_tempCurrentDir = $options['currentDir'];
|
||||||
self::$_tempPrepend = self::$_tempCurrentDir = '';
|
$rewrite = true;
|
||||||
return trim($css);
|
}
|
||||||
}
|
if ($rewrite) {
|
||||||
|
$css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
|
||||||
/**
|
,array(self::$className, '_urlCB'), $css);
|
||||||
* Replace what looks like a set of selectors
|
$css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
|
||||||
*
|
,array(self::$className, '_urlCB'), $css);
|
||||||
* @param array $m regex matches
|
}
|
||||||
*
|
self::$_tempPrepend = self::$_tempCurrentDir = '';
|
||||||
* @return string
|
return trim($css);
|
||||||
*/
|
}
|
||||||
protected static function _selectorsCB($m)
|
|
||||||
{
|
/**
|
||||||
// remove ws around the combinators
|
* Replace what looks like a set of selectors
|
||||||
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
|
*
|
||||||
}
|
* @param array $m regex matches
|
||||||
|
*
|
||||||
/**
|
* @return string
|
||||||
* @var bool Are we "in" a hack?
|
*/
|
||||||
*
|
protected static function _selectorsCB($m)
|
||||||
* I.e. are some browsers targetted until the next comment?
|
{
|
||||||
*/
|
// remove ws around the combinators
|
||||||
protected static $_inHack = false;
|
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @var string string to be prepended to relative URIs
|
/**
|
||||||
*/
|
* @var bool Are we "in" a hack?
|
||||||
protected static $_tempPrepend = '';
|
*
|
||||||
|
* I.e. are some browsers targetted until the next comment?
|
||||||
/**
|
*/
|
||||||
* @var string directory of this stylesheet for rewriting purposes
|
protected static $_inHack = false;
|
||||||
*/
|
|
||||||
protected static $_tempCurrentDir = '';
|
/**
|
||||||
|
* @var string string to be prepended to relative URIs
|
||||||
/**
|
*/
|
||||||
* Process a comment and return a replacement
|
protected static $_tempPrepend = '';
|
||||||
*
|
|
||||||
* @param array $m regex matches
|
/**
|
||||||
*
|
* @var string directory of this stylesheet for rewriting purposes
|
||||||
* @return string
|
*/
|
||||||
*/
|
protected static $_tempCurrentDir = '';
|
||||||
protected static function _commentCB($m)
|
|
||||||
{
|
/**
|
||||||
$m = $m[1];
|
* Process a comment and return a replacement
|
||||||
// $m is the comment content w/o the surrounding tokens,
|
*
|
||||||
// but the return value will replace the entire comment.
|
* @param array $m regex matches
|
||||||
if ($m === 'keep') {
|
*
|
||||||
return '/**/';
|
* @return string
|
||||||
}
|
*/
|
||||||
if ($m === '" "') {
|
protected static function _commentCB($m)
|
||||||
// component of http://tantek.com/CSS/Examples/midpass.html
|
{
|
||||||
return '/*" "*/';
|
$m = $m[1];
|
||||||
}
|
// $m is the comment content w/o the surrounding tokens,
|
||||||
if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
|
// but the return value will replace the entire comment.
|
||||||
// component of http://tantek.com/CSS/Examples/midpass.html
|
if ($m === 'keep') {
|
||||||
return '/*";}}/* */';
|
return '/**/';
|
||||||
}
|
}
|
||||||
if (self::$_inHack) {
|
if ($m === '" "') {
|
||||||
// inversion: feeding only to one browser
|
// component of http://tantek.com/CSS/Examples/midpass.html
|
||||||
if (preg_match('@
|
return '/*" "*/';
|
||||||
^/ # comment started like /*/
|
}
|
||||||
\\s*
|
if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
|
||||||
(\\S[\\s\\S]+?) # has at least some non-ws content
|
// component of http://tantek.com/CSS/Examples/midpass.html
|
||||||
\\s*
|
return '/*";}}/* */';
|
||||||
/\\* # ends like /*/ or /**/
|
}
|
||||||
@x', $m, $n)) {
|
if (self::$_inHack) {
|
||||||
// end hack mode after this comment, but preserve the hack and comment content
|
// inversion: feeding only to one browser
|
||||||
self::$_inHack = false;
|
if (preg_match('@
|
||||||
return "/*/{$n[1]}/**/";
|
^/ # comment started like /*/
|
||||||
}
|
\\s*
|
||||||
}
|
(\\S[\\s\\S]+?) # has at least some non-ws content
|
||||||
if (substr($m, -1) === '\\') { // comment ends like \*/
|
\\s*
|
||||||
// begin hack mode and preserve hack
|
/\\* # ends like /*/ or /**/
|
||||||
self::$_inHack = true;
|
@x', $m, $n)) {
|
||||||
return '/*\\*/';
|
// end hack mode after this comment, but preserve the hack and comment content
|
||||||
}
|
self::$_inHack = false;
|
||||||
if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
|
return "/*/{$n[1]}/**/";
|
||||||
// begin hack mode and preserve hack
|
}
|
||||||
self::$_inHack = true;
|
}
|
||||||
return '/*/*/';
|
if (substr($m, -1) === '\\') { // comment ends like \*/
|
||||||
}
|
// begin hack mode and preserve hack
|
||||||
if (self::$_inHack) {
|
self::$_inHack = true;
|
||||||
// a regular comment ends hack mode but should be preserved
|
return '/*\\*/';
|
||||||
self::$_inHack = false;
|
}
|
||||||
return '/**/';
|
if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
|
||||||
}
|
// begin hack mode and preserve hack
|
||||||
return ''; // remove all other comments
|
self::$_inHack = true;
|
||||||
}
|
return '/*/*/';
|
||||||
|
}
|
||||||
protected static function _urlCB($m)
|
if (self::$_inHack) {
|
||||||
{
|
// a regular comment ends hack mode but should be preserved
|
||||||
$isImport = (0 === strpos($m[0], '@import'));
|
self::$_inHack = false;
|
||||||
if ($isImport) {
|
return '/**/';
|
||||||
$quote = $m[1];
|
}
|
||||||
$url = $m[2];
|
return ''; // remove all other comments
|
||||||
} else {
|
}
|
||||||
// is url()
|
|
||||||
// $m[1] is either quoted or not
|
protected static function _urlCB($m)
|
||||||
$quote = ($m[1][0] === "'" || $m[1][0] === '"')
|
{
|
||||||
? $m[1][0]
|
$isImport = (0 === strpos($m[0], '@import'));
|
||||||
: '';
|
if ($isImport) {
|
||||||
$url = ($quote === '')
|
$quote = $m[1];
|
||||||
? $m[1]
|
$url = $m[2];
|
||||||
: substr($m[1], 1, strlen($m[1]) - 2);
|
} else {
|
||||||
}
|
// is url()
|
||||||
if ('/' !== $url[0]) {
|
// $m[1] is either quoted or not
|
||||||
if (strpos($url, '//') > 0) {
|
$quote = ($m[1][0] === "'" || $m[1][0] === '"')
|
||||||
// probably starts with protocol, do not alter
|
? $m[1][0]
|
||||||
} else {
|
: '';
|
||||||
// relative URI, rewrite!
|
$url = ($quote === '')
|
||||||
if (self::$_tempPrepend) {
|
? $m[1]
|
||||||
$url = self::$_tempPrepend . $url;
|
: substr($m[1], 1, strlen($m[1]) - 2);
|
||||||
} else {
|
}
|
||||||
// rewrite absolute url from scratch!
|
if ('/' !== $url[0]) {
|
||||||
// prepend path with current dir separator (OS-independent)
|
if (strpos($url, '//') > 0) {
|
||||||
$path = self::$_tempCurrentDir
|
// probably starts with protocol, do not alter
|
||||||
. DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR);
|
} else {
|
||||||
// strip doc root
|
// relative URI, rewrite!
|
||||||
$path = substr($path, strlen(realpath($_SERVER['DOCUMENT_ROOT'])));
|
if (self::$_tempPrepend) {
|
||||||
// fix to absolute URL
|
$url = self::$_tempPrepend . $url;
|
||||||
$url = strtr($path, DIRECTORY_SEPARATOR, '/');
|
} else {
|
||||||
// remove /./ and /../ where possible
|
// rewrite absolute url from scratch!
|
||||||
$url = str_replace('/./', '/', $url);
|
// prepend path with current dir separator (OS-independent)
|
||||||
// inspired by patch from Oleg Cherniy
|
$path = self::$_tempCurrentDir
|
||||||
do {
|
. DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR);
|
||||||
$url = preg_replace('@/[^/]+/\\.\\./@', '/', $url, -1, $changed);
|
// strip doc root
|
||||||
} while ($changed);
|
$path = substr($path, strlen(realpath($_SERVER['DOCUMENT_ROOT'])));
|
||||||
}
|
// fix to absolute URL
|
||||||
}
|
$url = strtr($path, DIRECTORY_SEPARATOR, '/');
|
||||||
}
|
// remove /./ and /../ where possible
|
||||||
return $isImport
|
$url = str_replace('/./', '/', $url);
|
||||||
? "@import {$quote}{$url}{$quote}"
|
// inspired by patch from Oleg Cherniy
|
||||||
: "url({$quote}{$url}{$quote})";
|
do {
|
||||||
}
|
$url = preg_replace('@/[^/]+/\\.\\./@', '/', $url, -1, $changed);
|
||||||
|
} while ($changed);
|
||||||
/**
|
}
|
||||||
* Process a font-family listing and return a replacement
|
}
|
||||||
*
|
}
|
||||||
* @param array $m regex matches
|
return $isImport
|
||||||
*
|
? "@import {$quote}{$url}{$quote}"
|
||||||
* @return string
|
: "url({$quote}{$url}{$quote})";
|
||||||
*/
|
}
|
||||||
protected static function _fontFamilyCB($m)
|
|
||||||
{
|
/**
|
||||||
$m[1] = preg_replace('/
|
* Process a font-family listing and return a replacement
|
||||||
\\s*
|
*
|
||||||
(
|
* @param array $m regex matches
|
||||||
"[^"]+" # 1 = family in double qutoes
|
*
|
||||||
|\'[^\']+\' # or 1 = family in single quotes
|
* @return string
|
||||||
|[\\w\\-]+ # or 1 = unquoted family
|
*/
|
||||||
)
|
protected static function _fontFamilyCB($m)
|
||||||
\\s*
|
{
|
||||||
/x', '$1', $m[1]);
|
$m[1] = preg_replace('/
|
||||||
return 'font-family:' . $m[1] . $m[2];
|
\\s*
|
||||||
}
|
(
|
||||||
}
|
"[^"]+" # 1 = family in double qutoes
|
||||||
|
|\'[^\']+\' # or 1 = family in single quotes
|
||||||
|
|[\\w\\-]+ # or 1 = unquoted family
|
||||||
|
)
|
||||||
|
\\s*
|
||||||
|
/x', '$1', $m[1]);
|
||||||
|
return 'font-family:' . $m[1] . $m[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -17,7 +17,14 @@
|
|||||||
* @author Stephen Clay <steve@mrclay.org>
|
* @author Stephen Clay <steve@mrclay.org>
|
||||||
*/
|
*/
|
||||||
class Minify_HTML {
|
class Minify_HTML {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines which class to call as part of callbacks, change this
|
||||||
|
* if you extend Minify_HTML
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected static $className = 'Minify_HTML';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Minify" an HTML page
|
* "Minify" an HTML page
|
||||||
*
|
*
|
||||||
@@ -59,30 +66,30 @@ class Minify_HTML {
|
|||||||
// replace SCRIPTs (and minify) with placeholders
|
// replace SCRIPTs (and minify) with placeholders
|
||||||
$html = preg_replace_callback(
|
$html = preg_replace_callback(
|
||||||
'/\\s*(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>\\s*/i'
|
'/\\s*(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>\\s*/i'
|
||||||
,array('Minify_HTML', '_removeScriptCB')
|
,array(self::$className, '_removeScriptCB')
|
||||||
,$html);
|
,$html);
|
||||||
|
|
||||||
// replace STYLEs (and minify) with placeholders
|
// replace STYLEs (and minify) with placeholders
|
||||||
$html = preg_replace_callback(
|
$html = preg_replace_callback(
|
||||||
'/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i'
|
'/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i'
|
||||||
,array('Minify_HTML', '_removeStyleCB')
|
,array(self::$className, '_removeStyleCB')
|
||||||
,$html);
|
,$html);
|
||||||
|
|
||||||
// remove HTML comments (not containing IE conditional comments).
|
// remove HTML comments (not containing IE conditional comments).
|
||||||
$html = preg_replace_callback(
|
$html = preg_replace_callback(
|
||||||
'/<!--([\\s\\S]*?)-->/'
|
'/<!--([\\s\\S]*?)-->/'
|
||||||
,array('Minify_HTML', '_commentCB')
|
,array(self::$className, '_commentCB')
|
||||||
,$html);
|
,$html);
|
||||||
|
|
||||||
// replace PREs with placeholders
|
// replace PREs with placeholders
|
||||||
$html = preg_replace_callback('/\\s*(<pre\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
|
$html = preg_replace_callback('/\\s*(<pre\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
|
||||||
,array('Minify_HTML', '_removePreCB')
|
,array(self::$className, '_removePreCB')
|
||||||
, $html);
|
, $html);
|
||||||
|
|
||||||
// replace TEXTAREAs with placeholders
|
// replace TEXTAREAs with placeholders
|
||||||
$html = preg_replace_callback(
|
$html = preg_replace_callback(
|
||||||
'/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
'/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
||||||
,array('Minify_HTML', '_removeTaCB')
|
,array(self::$className, '_removeTaCB')
|
||||||
, $html);
|
, $html);
|
||||||
|
|
||||||
// trim each line.
|
// trim each line.
|
||||||
@@ -99,7 +106,7 @@ class Minify_HTML {
|
|||||||
// remove ws outside of all elements
|
// remove ws outside of all elements
|
||||||
$html = preg_replace_callback(
|
$html = preg_replace_callback(
|
||||||
'/>([^<]+)</'
|
'/>([^<]+)</'
|
||||||
,array('Minify_HTML', '_outsideTagCB')
|
,array(self::$className, '_outsideTagCB')
|
||||||
,$html);
|
,$html);
|
||||||
|
|
||||||
// use newlines before 1st attribute in open tags (to limit line lengths)
|
// use newlines before 1st attribute in open tags (to limit line lengths)
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
*
|
*
|
||||||
* @package Minify
|
* @package Minify
|
||||||
* @author Stephen Clay <steve@mrclay.org>
|
* @author Stephen Clay <steve@mrclay.org>
|
||||||
|
* @author Adam Pedersen (Issue 55 fix)
|
||||||
*/
|
*/
|
||||||
class Minify_Lines {
|
class Minify_Lines {
|
||||||
|
|
||||||
@@ -71,7 +72,13 @@ class Minify_Lines {
|
|||||||
if (false === $pos) {
|
if (false === $pos) {
|
||||||
return $inComment;
|
return $inComment;
|
||||||
} else {
|
} else {
|
||||||
$inComment = ! $inComment;
|
if ($pos == 0
|
||||||
|
|| ($inComment
|
||||||
|
? substr($line, $pos, 3)
|
||||||
|
: substr($line, $pos-1, 3)) != '*/*')
|
||||||
|
{
|
||||||
|
$inComment = ! $inComment;
|
||||||
|
}
|
||||||
$line = substr($line, $pos + 2);
|
$line = substr($line, $pos + 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,13 @@
|
|||||||
* @package Minify
|
* @package Minify
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require 'class.JavaScriptPacker.php';
|
if (false === (@include 'class.JavaScriptPacker.php')) {
|
||||||
|
trigger_error(
|
||||||
|
'The script "class.JavaScriptPacker.php" is required. Please see: http:'
|
||||||
|
.'//code.google.com/p/minify/source/browse/trunk/min/lib/Minify/Packer.php'
|
||||||
|
,E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minify Javascript using Dean Edward's Packer
|
* Minify Javascript using Dean Edward's Packer
|
||||||
|
2
min_unit_tests/_test_files/minify/lines_bugs.js
Normal file
2
min_unit_tests/_test_files/minify/lines_bugs.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
var triggerBug = {_default: "*/*"};
|
||||||
|
var essentialFunctionality = true;
|
@@ -26,6 +26,12 @@
|
|||||||
/* 23 */ };
|
/* 23 */ };
|
||||||
/* 24 */ })();
|
/* 24 */ })();
|
||||||
;
|
;
|
||||||
|
/* lines_bugs.js */
|
||||||
|
|
||||||
|
/* 1 */ var triggerBug = {_default: "*/*"};
|
||||||
|
/* 2 */ var essentialFunctionality = true;
|
||||||
|
/* 3 */
|
||||||
|
;
|
||||||
/* QueryString.js */
|
/* QueryString.js */
|
||||||
|
|
||||||
/* 1 */ var MrClay = window.MrClay || {};
|
/* 1 */ var MrClay = window.MrClay || {};
|
||||||
|
@@ -15,6 +15,7 @@ function test_Lines()
|
|||||||
,'encodeOutput' => false
|
,'encodeOutput' => false
|
||||||
,'files' => array(
|
,'files' => array(
|
||||||
"{$thisDir}/_test_files/minify/email.js"
|
"{$thisDir}/_test_files/minify/email.js"
|
||||||
|
,"{$thisDir}/_test_files/minify/lines_bugs.js"
|
||||||
,"{$thisDir}/_test_files/minify/QueryString.js"
|
,"{$thisDir}/_test_files/minify/QueryString.js"
|
||||||
,"{$thisDir}/_test_files/js/before.js"
|
,"{$thisDir}/_test_files/js/before.js"
|
||||||
)
|
)
|
||||||
|
@@ -19,8 +19,22 @@ require_once '_inc.php';
|
|||||||
function test_environment()
|
function test_environment()
|
||||||
{
|
{
|
||||||
global $thisDir;
|
global $thisDir;
|
||||||
|
|
||||||
$thisUrl = 'http://'
|
// check DOCROOT
|
||||||
|
$noSlash = assertTrue(
|
||||||
|
0 === preg_match('@[\\\\/]$@', $_SERVER['DOCUMENT_ROOT'])
|
||||||
|
,'environment : DOCUMENT_ROOT should not end in trailing slash'
|
||||||
|
);
|
||||||
|
$goodRoot = assertTrue(
|
||||||
|
0 === strpos(realpath(__FILE__), realpath($_SERVER['DOCUMENT_ROOT']))
|
||||||
|
,'environment : DOCUMENT_ROOT should be real path and contain this test file'
|
||||||
|
);
|
||||||
|
if (! $noSlash || ! $goodRoot) {
|
||||||
|
echo "!NOTE: If you cannot modify DOCUMENT_ROOT, see this comment for a workaround:"
|
||||||
|
,"\n http://code.google.com/p/minify/issues/detail?id=68#c6\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$thisUrl = 'http://'
|
||||||
. $_SERVER['HTTP_HOST'] // avoid redirects when SERVER_NAME doesn't match
|
. $_SERVER['HTTP_HOST'] // avoid redirects when SERVER_NAME doesn't match
|
||||||
. ('80' === $_SERVER['SERVER_PORT'] ? '' : ":{$_SERVER['SERVER_PORT']}")
|
. ('80' === $_SERVER['SERVER_PORT'] ? '' : ":{$_SERVER['SERVER_PORT']}")
|
||||||
. dirname($_SERVER['REQUEST_URI'])
|
. dirname($_SERVER['REQUEST_URI'])
|
||||||
@@ -37,9 +51,9 @@ function test_environment()
|
|||||||
}
|
}
|
||||||
|
|
||||||
$fp = fopen($thisUrl . '?hello=1', 'r', false, stream_context_create(array(
|
$fp = fopen($thisUrl . '?hello=1', 'r', false, stream_context_create(array(
|
||||||
'http' => array(
|
'http' => array(
|
||||||
'method' => "GET",
|
'method' => "GET",
|
||||||
'header' => "Accept-Encoding: deflate, gzip\r\n"
|
'header' => "Accept-Encoding: deflate, gzip\r\n"
|
||||||
)
|
)
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user