@@ -307,6 +307,7 @@ public function execute($path = null, $parents = array())
307307 */
308308 $ this ->extractStrings ();
309309 $ this ->stripComments ();
310+ $ this ->extractCalcs ();
310311 $ css = $ this ->replace ($ css );
311312
312313 $ css = $ this ->stripWhitespace ($ css );
@@ -585,11 +586,7 @@ protected function shortenZeroes($content)
585586 // `5px - 0px` is valid, but `5px - 0` is not
586587 // `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
587588 // `10 * 0` is invalid
588- // best to just leave `calc()`s alone, even if they could be optimized
589- // (which is a whole other undertaking, where units & order of
590- // operations all need to be considered...)
591- $ calcs = $ this ->findCalcs ($ content );
592- $ content = str_replace ($ calcs , array_keys ($ calcs ), $ content );
589+ // we've extracted calcs earlier, so we don't need to worry about this
593590
594591 // reusable bits of code throughout these regexes:
595592 // before & after are used to make sure we don't match lose unintended
@@ -626,9 +623,6 @@ protected function shortenZeroes($content)
626623 $ content = preg_replace ('/flex:([0-9]+\s[0-9]+\s)0([;\}])/ ' , 'flex:${1}0%${2} ' , $ content );
627624 $ content = preg_replace ('/flex-basis:0([;\}])/ ' , 'flex-basis:0%${1} ' , $ content );
628625
629- // restore `calc()` expressions
630- $ content = str_replace (array_keys ($ calcs ), $ calcs , $ content );
631-
632626 return $ content ;
633627 }
634628
@@ -674,8 +668,8 @@ protected function stripWhitespace($content)
674668 // remove whitespace around meta characters
675669 // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
676670 $ content = preg_replace ('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/ ' , '$1 ' , $ content );
677- $ content = preg_replace ('/([\[(:])\s+/ ' , '$1 ' , $ content );
678- $ content = preg_replace ('/\s+([\]\)])/ ' , '$1 ' , $ content );
671+ $ content = preg_replace ('/([\[(:>\+ ])\s+/ ' , '$1 ' , $ content );
672+ $ content = preg_replace ('/\s+([\]\)>\+ ])/ ' , '$1 ' , $ content );
679673 $ content = preg_replace ('/\s+(:)(?![^\}]*\{)/ ' , '$1 ' , $ content );
680674
681675 // whitespace around + and - can only be stripped inside some pseudo-
@@ -692,18 +686,13 @@ protected function stripWhitespace($content)
692686 }
693687
694688 /**
695- * Find all `calc()` occurrences.
696- *
697- * @param string $content The CSS content to find `calc()`s in.
698- *
699- * @return string[]
689+ * Replace all `calc()` occurrences.
700690 */
701- protected function findCalcs ( $ content )
691+ protected function extractCalcs ( )
702692 {
703- $ results = array ();
704- preg_match_all ('/calc(\(.+?)(?=$|;|calc\()/ ' , $ content , $ matches , PREG_SET_ORDER );
705-
706- foreach ($ matches as $ match ) {
693+ // PHP only supports $this inside anonymous functions since 5.4
694+ $ minifier = $ this ;
695+ $ callback = function ($ match ) use ($ minifier ) {
707696 $ length = strlen ($ match [1 ]);
708697 $ expr = '' ;
709698 $ opened = 0 ;
@@ -717,11 +706,17 @@ protected function findCalcs($content)
717706 break ;
718707 }
719708 }
709+ $ rest = str_replace ($ expr , '' , $ match [1 ]);
710+ $ expr = trim (substr ($ expr , 1 , -1 ));
720711
721- $ results ['calc( ' .count ($ results ).') ' ] = 'calc ' .$ expr ;
722- }
712+ $ count = count ($ minifier ->extracted );
713+ $ placeholder = 'calc( ' .$ count .') ' ;
714+ $ minifier ->extracted [$ placeholder ] = 'calc( ' .$ expr .') ' ;
715+
716+ return $ placeholder .$ rest ;
717+ };
723718
724- return $ results ;
719+ $ this -> registerPattern ( ' /calc(\(.+?)(?=$|;|calc\()/ ' , $ callback ) ;
725720 }
726721
727722 /**
0 commit comments