gpt4 book ai didi

php - 使用正则表达式缩小/压缩 CSS?

转载 作者:IT王子 更新时间:2023-10-28 23:45:15 25 4
gpt4 key购买 nike

在 PHP 中,您可以使用正则表达式 (PCRE) 压缩/缩小 CSS 吗?

(作为正则表达式的理论。我确信那里有库可以很好地做到这一点。)

背景说明:花了几个小时写了一个 deleted (half crap) question 的答案后,我想我会发布一部分基本问题并自己回答。希望没事。

最佳答案

简单的正则表达式 CSS 缩小器/压缩器

(好吧,它可能不是太简单,但非常简单。)

要求

这个答案假定要求是:

  • 删除评论
  • 用一个空格替换长于 1 个空格的空格组合
  • 删除元字符周围的所有空格:{, }, ;, ,, >, ~, +, -
  • 删除 !important 周围的空格>
  • 移除 : 周围的空格,除了选择器(你必须在它之前保留一个空格)
  • 删除运算符周围的空格,如 $=
  • 删除(/[)/]左边的所有空格
  • 去掉字符串开头和结尾的所有空格
  • 删除 block 中的最后一个;
  • 不要改变字符串中的任何内容
  • 不必处理无效的 CSS

请注意,此处的要求不包括将 CSS 属性转换为较短的版本(例如使用速记属性而不是几个完整的属性,在不需要的地方删除引号)。这是一般正则表达式无法解决的问题。

解决方案

分两步解决这个问题更容易:首先删除评论,然后删除其他所有内容。

应该可以一次性完成,但随后您必须将所有 \s 替换为匹配空格和注释(以及其他一些修改)的表达式。

删除评论的第一遍表达式:

(?xs)
# quotes
(
"(?:[^"\\]++|\\.)*+"
| '(?:[^'\\]++|\\.)*+'
)
|
# comments
/\* (?> .*? \*/ )

替换为$1

并删除您可以使用的所有其他内容:

(?six)
# quotes
(
"(?:[^"\\]++|\\.)*+"
| '(?:[^'\\]++|\\.)*+'
)
|
# ; before } (and the spaces after it while we're here)
\s*+ ; \s*+ ( } ) \s*+
|
# all spaces around meta chars/operators
\s*+ ( [*$~^|]?+= | [{};,>~+-] | !important\b ) \s*+
|
# spaces right of ( [ :
( [[(:] ) \s++
|
# spaces left of ) ]
\s++ ( [])] )
|
# spaces left (and right) of :
\s++ ( : ) \s*+
# but not in selectors: not followed by a {
(?!
(?>
[^{}"']++
| "(?:[^"\\]++|\\.)*+"
| '(?:[^'\\]++|\\.)*+'
)*+
{
)
|
# spaces at beginning/end of string
^ \s++ | \s++ \z
|
# double spaces to single
(\s)\s+

替换为 $1$2$3$4$5$6$7

与适当的解析器相比,选择器检查 : 之前删除空格(负先行)可以减慢速度。解析器已经知道它们是否在选择器中,并且不必进行额外的搜索来检查。

PHP 中的示例实现

function minify_css($str){
# remove comments first (simplifies the other regex)
$re1 = <<<'EOS'
(?sx)
# quotes
(
"(?:[^"\\]++|\\.)*+"
| '(?:[^'\\]++|\\.)*+'
)
|
# comments
/\* (?> .*? \*/ )
EOS;

$re2 = <<<'EOS'
(?six)
# quotes
(
"(?:[^"\\]++|\\.)*+"
| '(?:[^'\\]++|\\.)*+'
)
|
# ; before } (and the spaces after it while we're here)
\s*+ ; \s*+ ( } ) \s*+
|
# all spaces around meta chars/operators
\s*+ ( [*$~^|]?+= | [{};,>~+-] | !important\b ) \s*+
|
# spaces right of ( [ :
( [[(:] ) \s++
|
# spaces left of ) ]
\s++ ( [])] )
|
# spaces left (and right) of :
\s++ ( : ) \s*+
# but not in selectors: not followed by a {
(?!
(?>
[^{}"']++
| "(?:[^"\\]++|\\.)*+"
| '(?:[^'\\]++|\\.)*+'
)*+
{
)
|
# spaces at beginning/end of string
^ \s++ | \s++ \z
|
# double spaces to single
(\s)\s+
EOS;

$str = preg_replace("%$re1%", '$1', $str);
return preg_replace("%$re2%", '$1$2$3$4$5$6$7', $str);
}

快速测试

可以查到at ideone.com :

$in = <<<'EOS'

p * i , html
/* remove spaces */

/* " comments have no escapes \*/
body/* keep */ /* space */p,
p [ remove ~= " spaces " ] :nth-child( 3 + 2n ) > b span i , div::after

{
/* comment */
background : url( " /* string */ " ) blue !important ;
content : " escapes \" allowed \\" ;
width: calc( 100% - 3em + 5px ) ;
margin-top : 0;
margin-bottom : 0;
margin-left : 10px;
margin-right : 10px;
}

EOS;


$out = minify_css($in);

echo "input:\n";
var_dump($in);

echo "\n\n";
echo "output:\n";
var_dump($out);

输出:

input:
string(435) "
p * i , html
/* remove spaces */

/* " comments have no escapes \*/
body/* keep */ /* space */p,
p [ remove ~= " spaces " ] :nth-child( 3 + 2n ) > b span i , div::after

{
/* comment */
background : url( " /* string */ " ) blue !important ;
content : " escapes \" allowed \\" ;
width: calc( 100% - 3em + 5px ) ;
margin-top : 0;
margin-bottom : 0;
margin-left : 10px;
margin-right : 10px;
}
"


output:
string(251) "p * i,html body p,p [remove~=" spaces "] :nth-child(3+2n)>b span i,div::after{background:url(" /* string */ ") blue!important;content:" escapes \" allowed \\";width:calc(100%-3em+5px);margin-top:0;margin-bottom:0;margin-left:10px;margin-right:10px}"

比较

cssminifier.com

cssminifier.com 的结果对于与上述测试相同的输入:

p * i,html /*\*/body/**/p,p [remove ~= " spaces  "] :nth-child(3+2n)>b span i,div::after{background:url("  /* string */  ") blue;content:" escapes \" allowed \\";width:calc(100% - 3em+5px);margin-top:0;margin-bottom:0;margin-left:10px;margin-right:10px}

长度 263 字节。比上面的正则表达式缩小器的输出长 12 个字节。

cssminifier.com与这个正则表达式压缩器相比有一些缺点:

  • 留下部分评论。 (这可能是有原因的。也许是一些 CSS hack。)
  • 它不会删除某些表达式中运算符周围的空格

CSSTidy

CSSTidy 1.3 的输出(通过 codebeautifier.com )在预设的最高压缩级别:

p * i,html /* remove spaces */
/* " comments have no escapes \*/
body/* keep */ /* space */p,p [ remove ~= " spaces " ] :nth-child( 3 + 2n ) > b span i,div::after{background:url(" /* string */ ") blue!important;content:" escapes \" allowed \\";width:calc(100%-3em+5px);margin:0 10px;}

长度 286 字节。比正则表达式缩小器的输出长 35 个字节。

CSSTidy 不会删除某些选择器中的注释或空格。但它确实缩小了速记属性。后者可能有助于更多地压缩普通 CSS。

并排比较

对于与上例中相同的输入,来自不同缩小器的缩小输出。(剩余的换行符替换为空格。)

this answern    (251): p * i,html body p,p [remove~=" spaces  "] :nth-child(3+2n)>b span i,div::after{background:url("  /* string */  ") blue!important;content:" escapes \" allowed \\";width:calc(100%-3em+5px);margin-top:0;margin-bottom:0;margin-left:10px;margin-right:10px}
cssminifier.com (263): p * i,html /*\*/body/**/p,p [remove ~= " spaces "] :nth-child(3+2n)>b span i,div::after{background:url(" /* string */ ") blue!important;content:" escapes \" allowed \\";width:calc(100% - 3em+5px);margin-top:0;margin-bottom:0;margin-left:10px;margin-right:10px}
CSSTidy 1.3 (286): p * i,html /* remove spaces */ /* " comments have no escapes \*/ body/* keep */ /* space */p,p [ remove ~= " spaces " ] :nth-child( 3 + 2n ) > b span i,div::after{background:url(" /* string */ ") blue!important;content:" escapes \" allowed \\";width:calc(100%-3em+5px);margin:0 10px;}

对于普通的 CSS,CSSTidy 可能是最好的,因为它可以转换为速记属性。

我假设还有其他压缩器(如 YUI 压缩器)应该在这方面做得更好,并且给出的结果比这个正则表达式压缩器更短。

关于php - 使用正则表达式缩小/压缩 CSS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15195750/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com