Skip to content

Commit

Permalink
More robust calc() detection
Browse files Browse the repository at this point in the history
Fixes #312
  • Loading branch information
matthiasmullie committed Dec 23, 2020
1 parent 21678a3 commit 022cd72
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 13 deletions.
31 changes: 18 additions & 13 deletions src/CSS.php
Original file line number Diff line number Diff line change
Expand Up @@ -684,14 +684,22 @@ protected function stripWhitespace($content)
*/
protected function extractMath()
{
$functions = array('calc', 'clamp', 'min', 'max');
$pattern = '/('. implode($functions, '|') .')(\(.+?)(?=$|;|})/m';

This comment has been minimized.

Copy link
@ArnaudLigny

ArnaudLigny Dec 26, 2020

You should reverse arguments for better compatibility (PHP 8).


// PHP only supports $this inside anonymous functions since 5.4
$minifier = $this;
$callback = function ($match) use ($minifier) {
$callback = function ($match) use ($minifier, $pattern, &$callback) {
$function = $match[1];
$length = strlen($match[2]);
$expr = '';
$opened = 0;

// the regular expression for extracting math has 1 significant problem:
// it can't determine the correct closing parenthesis...
// instead, it'll match a larger portion of code to where it's certain that
// the calc() musts have ended, and we'll figure out which is the correct
// closing parenthesis here, by counting how many have opened
for ($i = 0; $i < $length; $i++) {
$char = $match[2][$i];
$expr .= $char;
Expand All @@ -701,25 +709,22 @@ protected function extractMath()
break;
}
}
$rest = str_replace($expr, '', $match[2]);
$expr = trim(substr($expr, 1, -1));

// now that we've figured out where the calc() starts and ends, extract it
$count = count($minifier->extracted);
$placeholder = 'math('.$count.')';
$minifier->extracted[$placeholder] = $function.'('.$expr.')';
$minifier->extracted[$placeholder] = $function.'('.trim(substr($expr, 1, -1)).')';

// and since we've captured more code than required, we may have some leftover
// calc() in here too - go recursive on the remaining but of code to go figure
// that out and extract what is needed
$rest = str_replace($function.$expr, '', $match[0]);
$rest = preg_replace_callback($pattern, $callback, $rest);

return $placeholder.$rest;
};

$functions = array('calc', 'clamp', 'min', 'max');
$this->registerPattern(
'/('. implode($functions, '|') .')(\(.+?)(?=$|;|}|('. implode($functions, '|') .')\()/',
$callback
);
$this->registerPattern(
'/('. implode($functions, '|') .')(\(.+?)(?=$|;|}|('. implode($functions, '|') .')\()/m',
$callback
);
$this->registerPattern($pattern, $callback);
}

/**
Expand Down
10 changes: 10 additions & 0 deletions tests/css/CSSTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,16 @@ public function dataProvider()
'--headlineFontSize:16px + var(--multiplicator);font-size:calc(var(--headlineFontSize));',
);

// https://github.com/matthiasmullie/minify/issues/312
$tests[] = array(
'.alignfull { width: calc(100% + calc(2 * var(--central-padding))); }',
'.alignfull{width:calc(100% + calc(2 * var(--central-padding)))}',
);
$tests[] = array(
'*{margin-left: calc(0.5rem * calc(1 - var(--space-x-reverse)));}',
'*{margin-left:calc(0.5rem * calc(1 - var(--space-x-reverse)))}',
);

return $tests;
}

Expand Down

0 comments on commit 022cd72

Please sign in to comment.