mirror of
https://github.com/mrclay/minify.git
synced 2025-08-07 06:36:29 +02:00
+ YUI Compressor-style comment preservation to CSS.php, adjusted tests to match
This commit is contained in:
@@ -24,12 +24,70 @@ class Minify_CSS {
|
|||||||
*
|
*
|
||||||
* @param string $css
|
* @param string $css
|
||||||
*
|
*
|
||||||
* @param array $options optional. To enable URL rewriting, set the value
|
* @param array $options available options:
|
||||||
|
*
|
||||||
|
* 'preserveComments': (default true) multi-line comments that begin
|
||||||
|
* with "/*!" will be preserved with newlines before and after to
|
||||||
|
* enhance readability.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function minify($css, $options = array())
|
||||||
|
{
|
||||||
|
if (isset($options['preserveComments'])
|
||||||
|
&& !$options['preserveComments']) {
|
||||||
|
return self::_minify($css, $options);
|
||||||
|
}
|
||||||
|
$ret = '';
|
||||||
|
while (1) {
|
||||||
|
list($beforeComment, $comment, $afterComment)
|
||||||
|
= self::_nextYuiComment($css);
|
||||||
|
$ret .= self::_minify($beforeComment, $options);
|
||||||
|
if (false === $comment) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$ret .= $comment;
|
||||||
|
$css = $afterComment;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract comments that YUI Compressor preserves.
|
||||||
|
*
|
||||||
|
* @param string $in input
|
||||||
|
*
|
||||||
|
* @return array 3 elements are returned. If a YUI comment is found, the
|
||||||
|
* 2nd element is the comment and the 1st and 2nd are the surrounding
|
||||||
|
* strings. If no comment is found, the entire string is returned as the
|
||||||
|
* 1st element and the other two are false.
|
||||||
|
*/
|
||||||
|
private static function _nextYuiComment($in)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
(false !== ($start = strpos($in, '/*!')))
|
||||||
|
&& (false !== ($end = strpos($in, '*/', $start + 3)))
|
||||||
|
)
|
||||||
|
? array(
|
||||||
|
substr($in, 0, $start)
|
||||||
|
,"\n/*" . substr($in, $start + 3, $end - $start - 1) . "\n"
|
||||||
|
,substr($in, -(strlen($in) - $end - 2))
|
||||||
|
)
|
||||||
|
: array($in, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minify a CSS string
|
||||||
|
*
|
||||||
|
* @param string $css
|
||||||
|
*
|
||||||
|
* @param array $options To enable URL rewriting, set the value
|
||||||
* for key 'prependRelativePath'.
|
* for key 'prependRelativePath'.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function minify($css, $options = array()) {
|
protected static function _minify($css, $options)
|
||||||
|
{
|
||||||
// preserve empty comment after '>'
|
// preserve empty comment after '>'
|
||||||
// http://www.webdevout.net/css-hacks#in_css-selectors
|
// http://www.webdevout.net/css-hacks#in_css-selectors
|
||||||
$css = preg_replace('/>\\/\\*\\s*\\*\\//', '>/*keep*/', $css);
|
$css = preg_replace('/>\\/\\*\\s*\\*\\//', '>/*keep*/', $css);
|
||||||
@@ -44,7 +102,7 @@ class Minify_CSS {
|
|||||||
$css = preg_replace_callback('/\\s*\\/\\*([\\s\\S]*?)\\*\\/\\s*/'
|
$css = preg_replace_callback('/\\s*\\/\\*([\\s\\S]*?)\\*\\/\\s*/'
|
||||||
,array('Minify_CSS', '_commentCB'), $css);
|
,array('Minify_CSS', '_commentCB'), $css);
|
||||||
|
|
||||||
// compress whitespace. Yes, this will affect "copyright" comments.
|
// compress whitespace.
|
||||||
$css = preg_replace('/\s+/', ' ', $css);
|
$css = preg_replace('/\s+/', ' ', $css);
|
||||||
|
|
||||||
// leave needed comments
|
// leave needed comments
|
||||||
@@ -116,16 +174,11 @@ class Minify_CSS {
|
|||||||
protected static function _commentCB($m)
|
protected static function _commentCB($m)
|
||||||
{
|
{
|
||||||
$m = $m[1];
|
$m = $m[1];
|
||||||
// $m is everything after the opening tokens and before the closing tokens
|
// $m is everything after the opening tokens and before the closing
|
||||||
// but return will replace the entire comment.
|
// tokens but return will replace the entire comment.
|
||||||
if ($m === 'keep') {
|
if ($m === 'keep') {
|
||||||
return '/*keep*/';
|
return '/*keep*/';
|
||||||
}
|
}
|
||||||
if (false !== strpos($m, 'copyright')) {
|
|
||||||
// contains copyright, preserve
|
|
||||||
self::$_inHack = false;
|
|
||||||
return "/*{$m}*/";
|
|
||||||
}
|
|
||||||
if (self::$_inHack) {
|
if (self::$_inHack) {
|
||||||
// inversion: feeding only to one browser
|
// inversion: feeding only to one browser
|
||||||
if (preg_match('/^\\/\\s*(\\S[\\s\\S]+?)\\s*\\/\\*/', $m, $n)) {
|
if (preg_match('/^\\/\\s*(\\S[\\s\\S]+?)\\s*\\/\\*/', $m, $n)) {
|
||||||
@@ -137,7 +190,7 @@ class Minify_CSS {
|
|||||||
self::$_inHack = true;
|
self::$_inHack = true;
|
||||||
return '/*\\*/';
|
return '/*\\*/';
|
||||||
}
|
}
|
||||||
if (substr($m, 0, 1) === '/') {
|
if ($m[0] === '/') {
|
||||||
self::$_inHack = true;
|
self::$_inHack = true;
|
||||||
return '/*/*/';
|
return '/*/*/';
|
||||||
}
|
}
|
||||||
|
@@ -17,17 +17,18 @@ class Minify_Javascript {
|
|||||||
/**
|
/**
|
||||||
* Minify a Javascript string
|
* Minify a Javascript string
|
||||||
*
|
*
|
||||||
* @param string $js input javascript
|
* @param string $js
|
||||||
*
|
*
|
||||||
* @param array $options available options:
|
* @param array $options available options:
|
||||||
*
|
*
|
||||||
* 'preserveComments': (default true) multi-line comments that begin
|
* 'preserveComments': (default true) multi-line comments that begin
|
||||||
* with "/*!" will be preserved with newlines before and after to
|
* with "/*!" will be preserved with newlines before and after to
|
||||||
* preserve readability.
|
* enhance readability.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function minify($js, $options = array()) {
|
public static function minify($js, $options = array())
|
||||||
|
{
|
||||||
if (isset($options['preserveComments'])
|
if (isset($options['preserveComments'])
|
||||||
&& !$options['preserveComments']) {
|
&& !$options['preserveComments']) {
|
||||||
return trim(JSMin::minify($js));
|
return trim(JSMin::minify($js));
|
||||||
@@ -49,26 +50,25 @@ class Minify_Javascript {
|
|||||||
/**
|
/**
|
||||||
* Extract comments that YUI Compressor preserves.
|
* Extract comments that YUI Compressor preserves.
|
||||||
*
|
*
|
||||||
* @param string $js input
|
* @param string $in input
|
||||||
*
|
*
|
||||||
* @return array 3 elements are returned. If a YUI comment is found, the
|
* @return array 3 elements are returned. If a YUI comment is found, the
|
||||||
* 2nd element is the comment and the 1st and 2nd are the surrounding
|
* 2nd element is the comment and the 1st and 2nd are the surrounding
|
||||||
* strings. If no comment is found, the entire string is returned as the 1st
|
* strings. If no comment is found, the entire string is returned as the
|
||||||
* element and the other two are false.
|
* 1st element and the other two are false.
|
||||||
*/
|
*/
|
||||||
private static function _nextYuiComment($js)
|
private static function _nextYuiComment($in)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
(false !== ($start = strpos($js, '/*!')))
|
(false !== ($start = strpos($in, '/*!')))
|
||||||
&& (false !== ($end = strpos($js, '*/')))
|
&& (false !== ($end = strpos($in, '*/', $start + 3)))
|
||||||
&& ($start < $end)
|
|
||||||
)
|
)
|
||||||
? array(
|
? array(
|
||||||
substr($js, 0, $start)
|
substr($in, 0, $start)
|
||||||
,"\n/*" . substr($js, $start + 3, $end - $start - 1) . "\n"
|
,"\n/*" . substr($in, $start + 3, $end - $start - 1) . "\n"
|
||||||
,substr($js, -(strlen($js) - $end - 2))
|
,substr($in, -(strlen($in) - $end - 2))
|
||||||
)
|
)
|
||||||
: array($js, false, false);
|
: array($in, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
/* block comments get removed */
|
/* block comments get removed */
|
||||||
|
|
||||||
/* comments containing the word "copyright" are left in, though */
|
/*! YUI Compressor style comments are preserved */
|
||||||
|
|
||||||
/* but all other comments are removed */
|
/* but all other comments are removed */
|
||||||
|
3
web/test/_test_files/css/comments.min.css
vendored
3
web/test/_test_files/css/comments.min.css
vendored
@@ -1 +1,2 @@
|
|||||||
/* comments containing the word "copyright" are left in, though */
|
|
||||||
|
/* YUI Compressor style comments are preserved */
|
||||||
|
@@ -49,7 +49,7 @@ if (is.ua.indexOf('gecko') >= 0) {
|
|||||||
</script>
|
</script>
|
||||||
<!--[if IE 6]>
|
<!--[if IE 6]>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
/* copyright: you'll need CDATA for this -- < & */
|
/*! copyright: you'll need CDATA for this < & */
|
||||||
body {background:white;}
|
body {background:white;}
|
||||||
</style>
|
</style>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" ><head><meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /><meta name="author" content="Dave Shea" /><meta name="keywords" content="design, css, cascading, style, sheets, xhtml, graphic design, w3c, web standards, visual, display" /><meta name="description" content="A demonstration of what can be accomplished visually through CSS-based design." /><meta name="robots" content="all" /><title>css Zen Garden: The Beauty in CSS Design</title><script type="text/javascript">var is={ie:navigator.appName=='Microsoft Internet Explorer',java:navigator.javaEnabled(),ns:navigator.appName=='Netscape',ua:navigator.userAgent.toLowerCase(),version:parseFloat(navigator.appVersion.substr(21))||parseFloat(navigator.appVersion),win:navigator.platform=='Win32'}
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" ><head><meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /><meta name="author" content="Dave Shea" /><meta name="keywords" content="design, css, cascading, style, sheets, xhtml, graphic design, w3c, web standards, visual, display" /><meta name="description" content="A demonstration of what can be accomplished visually through CSS-based design." /><meta name="robots" content="all" /><title>css Zen Garden: The Beauty in CSS Design</title><script type="text/javascript">var is={ie:navigator.appName=='Microsoft Internet Explorer',java:navigator.javaEnabled(),ns:navigator.appName=='Netscape',ua:navigator.userAgent.toLowerCase(),version:parseFloat(navigator.appVersion.substr(21))||parseFloat(navigator.appVersion),win:navigator.platform=='Win32'}
|
||||||
is.mac=is.ua.indexOf('mac')>=0;if(is.ua.indexOf('opera')>=0){is.ie=is.ns=false;is.opera=true;}
|
is.mac=is.ua.indexOf('mac')>=0;if(is.ua.indexOf('opera')>=0){is.ie=is.ns=false;is.opera=true;}
|
||||||
if(is.ua.indexOf('gecko')>=0){is.ie=is.ns=false;is.gecko=true;}</script><script type="text/javascript">/*<![CDATA[*/var i=0;while(++i<10)
|
if(is.ua.indexOf('gecko')>=0){is.ie=is.ns=false;is.gecko=true;}</script><script type="text/javascript">/*<![CDATA[*/var i=0;while(++i<10)
|
||||||
{}/*]]>*/</script><script type="text/javascript">i=1;</script><script type="text/javascript">/*<![CDATA[*/(i<1);/*]]>*/</script><!--[if IE 6]><style type="text/css">/*<![CDATA[*//* copyright: you'll need CDATA for this -- < & */body{background:white}/*]]>*/</style><![endif]--><style type="text/css" title="currentStyle" media="screen">@import "/001/001.css";/*\*/css hack{}/**//*/*/css hack{}/**/css hack{display/**/:/**/none;display:none}</style><link
|
{}/*]]>*/</script><script type="text/javascript">i=1;</script><script type="text/javascript">/*<![CDATA[*/(i<1);/*]]>*/</script><!--[if IE 6]><style type="text/css">/*<![CDATA[*/
|
||||||
|
/* copyright: you'll need CDATA for this < & */
|
||||||
|
body{background:white}/*]]>*/</style><![endif]--><style type="text/css" title="currentStyle" media="screen">@import "/001/001.css";/*\*/css hack{}/**//*/*/css hack{}/**/css hack{display/**/:/**/none;display:none}</style><link
|
||||||
rel="Shortcut Icon"
|
rel="Shortcut Icon"
|
||||||
type="image/x-icon"
|
type="image/x-icon"
|
||||||
href="http://www.csszengarden.com/favicon.ico" /><link
|
href="http://www.csszengarden.com/favicon.ico" /><link
|
||||||
|
@@ -72,8 +72,8 @@ function test_HTTP_Encoder()
|
|||||||
$variedLength = strlen($variedContent);
|
$variedLength = strlen($variedContent);
|
||||||
|
|
||||||
$encodingTests = array(
|
$encodingTests = array(
|
||||||
array('method' => 'deflate', 'exp' => 32156)
|
array('method' => 'deflate', 'exp' => 32157)
|
||||||
,array('method' => 'gzip', 'exp' => 32174)
|
,array('method' => 'gzip', 'exp' => 32175)
|
||||||
,array('method' => 'compress', 'exp' => 32210)
|
,array('method' => 'compress', 'exp' => 32210)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ function test_HTTP_Encoder()
|
|||||||
$ret = strlen($e->getContent());
|
$ret = strlen($e->getContent());
|
||||||
|
|
||||||
$desc = "HTTP_Encoder : {$test['method']} -> "
|
$desc = "HTTP_Encoder : {$test['method']} -> "
|
||||||
. sprintf('%4.2f%%', $ret/$variedLength*100);
|
. sprintf('%d(%4.2f%%)', $ret, $ret/$variedLength*100);
|
||||||
|
|
||||||
$passed = assertTrue($ret == $test['exp'], $desc);
|
$passed = assertTrue($ret == $test['exp'], $desc);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user