diff --git a/src/CSS.php b/src/CSS.php index a8bd125..09cedee 100644 --- a/src/CSS.php +++ b/src/CSS.php @@ -632,18 +632,7 @@ protected function stripEmptyTags($content) */ protected function stripComments() { - // PHP only supports $this inside anonymous functions since 5.4 - $minifier = $this; - $callback = function ($match) use ($minifier) { - $count = count($minifier->extracted); - $placeholder = '/*' . $count . '*/'; - $minifier->extracted[$placeholder] = $match[0]; - - return $placeholder; - }; - $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback); - - $this->registerPattern('/\/\*.*?\*\//s', ''); + $this->stripMultilineComments(); } /** diff --git a/src/JS.php b/src/JS.php index ac5e98d..d592b08 100644 --- a/src/JS.php +++ b/src/JS.php @@ -198,28 +198,7 @@ public function execute($path = null) */ protected function stripComments() { - // PHP only supports $this inside anonymous functions since 5.4 - $minifier = $this; - $callback = function ($match) use ($minifier) { - if ( - substr($match[2], 0, 1) === '!' || - strpos($match[2], '@license') !== false || - strpos($match[2], '@preserve') !== false - ) { - // preserve multi-line comments that start with /*! - // or contain @license or @preserve annotations - $count = count($minifier->extracted); - $placeholder = '/*' . $count . '*/'; - $minifier->extracted[$placeholder] = $match[0]; - - return $match[1] . $placeholder . $match[3]; - } - - return $match[1] . $match[3]; - }; - - // multi-line comments - $this->registerPattern('/(\n?)\/\*(.*?)\*\/(\n?)/s', $callback); + $this->stripMultilineComments(); // single-line comments $this->registerPattern('/\/\/.*$/m', ''); diff --git a/src/Minify.php b/src/Minify.php index 19faf98..f77478b 100644 --- a/src/Minify.php +++ b/src/Minify.php @@ -260,6 +260,49 @@ protected function registerPattern($pattern, $replacement = '') $this->patterns[] = array($pattern, $replacement); } + /** + * Both JS and CSS use the same form of multi-line comment, so putting the common code here. + */ + protected function stripMultilineComments() + { + // First extract comments we want to keep, so they can be restored later + // PHP only supports $this inside anonymous functions since 5.4 + $minifier = $this; + $callback = function ($match) use ($minifier) { + $count = count($minifier->extracted); + $placeholder = '/*'.$count.'*/'; + $minifier->extracted[$placeholder] = $match[0]; + + return $placeholder; + }; + $this->registerPattern('/ + # optional newline + \n? + + # start comment + \/\* + + # comment content + (?: + # either starts with an ! + ! + | + # or, after some number of characters which do not end the comment + (?:(?!\*\/).)*? + + # there is either a @license or @preserve tag + @(?:license|preserve) + ) + + # then match to the end of the comment + .*?\*\/\n? + + /ixs', $callback); + + // Then strip all other comments + $this->registerPattern('/\/\*.*?\*\//s', ''); + } + /** * We can't "just" run some regular expressions against JavaScript: it's a * complex language. E.g. having an occurrence of // xyz would be a comment, diff --git a/tests/CSS/CSSTest.php b/tests/CSS/CSSTest.php index c2ee9d1..3fdc28d 100644 --- a/tests/CSS/CSSTest.php +++ b/tests/CSS/CSSTest.php @@ -172,6 +172,13 @@ public static function dataProvider() '/* @preserve This is a CSS comment */', ); + $tests[] = array( + '/* Do not preserve me */ + body { color: red; } + /* @preserve This is a CSS comment */', + 'body{color:red}/* @preserve This is a CSS comment */', + ); + // strip whitespace $tests[] = array( 'body { color: red; }', diff --git a/tests/JS/JSTest.php b/tests/JS/JSTest.php index b6ef2a2..ff82068 100644 --- a/tests/JS/JSTest.php +++ b/tests/JS/JSTest.php @@ -183,6 +183,13 @@ public static function dataProvider() '/* @preserve This is a JS comment */', ); + $tests[] = array( + '/* Do not preserve me */ + x = 1; + /* @preserve This is a JS comment */', + 'x=1;/* @preserve This is a JS comment */', + ); + // make sure no ; is added in places it shouldn't $tests[] = array( 'if(true){}else{}',