_selectorsCB callback strips off whitespace inside calc() expressions
sedimentation-fault opened this issue · 0 comments
Problem
Take this CSS as an example:
body {
font-size: calc(15px + 0.39vw);
}
body, #contents {
width: 100%;
}
minify will transorm it to
body{font-size:calc(15px+0.39vw)}body, #contents{width:100%}
which is incorrect, because '+'
and '-'
inside calc()
expressions must retain whitespace around them:
The + and - operators must be surrounded by whitespace. For instance, calc(50% -8px) will be parsed as "a percentage followed by a negative length" — which is an invalid expression — while calc(50% - 8px) is "a percentage followed by a subtraction operator and a length". Likewise, calc(8px + -50%) is treated as "a length followed by an addition operator and a negative percentage".
(from: MDN - calc())
Reason
The _selectorsCB()
callback in minify/lib/Minify/CSS/Compressor.php
is passed
' body{font-size:calc(15px + 0.39vw)}body, #contents{'
(the string inside the single quotes, without the quotes, but including the blank at the start) as parameter and interprets it as a "selector" for 'body', so it strips whitespace out of it.
Solution
Replace
protected function _selectorsCB($m)
{
// remove ws around the combinators
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
}
with
protected function _selectorsCB($m)
{
$pos = strpos($m[0], 'calc(');
if ($pos !== false) {
return $m[0];
}
// remove ws around the combinators
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
}
i.e. if the "selector" contains 'calc('
don't do anything with it. Maybe not a true solution [*], but at least a workaround...
[*] because, theoretically, you would want to leave only the calc()
part of $m[0]
untouched, not the whole $m[0]
, but anyway...