From d77e0a6dae563d54daf93d37e008a9b52c929793 Mon Sep 17 00:00:00 2001 From: Sara Arjona Date: Tue, 11 Jan 2022 10:37:06 +0100 Subject: [PATCH 1/3] MDL-71702 lib: Upgrade minify to 1.3.66 --- lib/minify/matthiasmullie-minify/src/CSS.php | 88 ++++++++++--------- lib/minify/matthiasmullie-minify/src/JS.php | 2 +- .../matthiasmullie-minify/src/Minify.php | 10 ++- 3 files changed, 55 insertions(+), 45 deletions(-) diff --git a/lib/minify/matthiasmullie-minify/src/CSS.php b/lib/minify/matthiasmullie-minify/src/CSS.php index e00856f6003..eb98e52ed38 100644 --- a/lib/minify/matthiasmullie-minify/src/CSS.php +++ b/lib/minify/matthiasmullie-minify/src/CSS.php @@ -216,7 +216,7 @@ class CSS extends Minify // grab referenced file & minify it (which may include importing // yet other @import statements recursively) - $minifier = new static($importPath); + $minifier = new self($importPath); $minifier->setMaxImportSize($this->maxImportSize); $minifier->setImportExtensions($this->importExtensions); $importContent = $minifier->execute($source, $parents); @@ -307,7 +307,8 @@ class CSS extends Minify */ $this->extractStrings(); $this->stripComments(); - $this->extractCalcs(); + $this->extractMath(); + $this->extractCustomProperties(); $css = $this->replace($css); $css = $this->stripWhitespace($css); @@ -636,35 +637,7 @@ class CSS extends Minify return $placeholder; }; - // Moodle-specific change MDL-68191 starts. - /* This was the old code: $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback); - */ - // This is the new, more accurate and faster regex. - $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); - // Moodle-specific change MDL-68191. $this->registerPattern('/\/\*.*?\*\//s', ''); } @@ -706,19 +679,29 @@ class CSS extends Minify } /** - * Replace all `calc()` occurrences. + * Replace all occurrences of functions that may contain math, where + * whitespace around operators needs to be preserved (e.g. calc, clamp) */ - protected function extractCalcs() + protected function extractMath() { + $functions = array('calc', 'clamp', 'min', 'max'); + $pattern = '/\b('. implode('|', $functions) .')(\(.+?)(?=$|;|})/m'; + // PHP only supports $this inside anonymous functions since 5.4 $minifier = $this; - $callback = function ($match) use ($minifier) { - $length = strlen($match[1]); + $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[1][$i]; + $char = $match[2][$i]; $expr .= $char; if ($char === '(') { $opened++; @@ -726,18 +709,41 @@ class CSS extends Minify break; } } - $rest = str_replace($expr, '', $match[1]); - $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 = 'calc('.$count.')'; - $minifier->extracted[$placeholder] = 'calc('.$expr.')'; + $placeholder = 'math('.$count.')'; + $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; }; - $this->registerPattern('/calc(\(.+?)(?=$|;|}|calc\()/', $callback); - $this->registerPattern('/calc(\(.+?)(?=$|;|}|calc\()/m', $callback); + $this->registerPattern($pattern, $callback); + } + + /** + * Replace custom properties, whose values may be used in scenarios where + * we wouldn't want them to be minified (e.g. inside calc) + */ + protected function extractCustomProperties() + { + // PHP only supports $this inside anonymous functions since 5.4 + $minifier = $this; + $this->registerPattern( + '/(?<=^|[;}])(--[^:;{}"\'\s]+)\s*:([^;{}]+)/m', + function ($match) use ($minifier) { + $placeholder = '--custom-'. count($minifier->extracted) . ':0'; + $minifier->extracted[$placeholder] = $match[1] .':'. trim($match[2]); + return $placeholder; + + } + ); } /** diff --git a/lib/minify/matthiasmullie-minify/src/JS.php b/lib/minify/matthiasmullie-minify/src/JS.php index 92389cdd5d0..a0fa649d3a9 100644 --- a/lib/minify/matthiasmullie-minify/src/JS.php +++ b/lib/minify/matthiasmullie-minify/src/JS.php @@ -254,7 +254,7 @@ class JS extends Minify // of the RegExp methods (a `\` followed by a variable or value is // likely part of a division, not a regex) $keywords = array('do', 'in', 'new', 'else', 'throw', 'yield', 'delete', 'return', 'typeof'); - $before = '([=:,;\+\-\*\/\}\(\{\[&\|!]|^|'.implode('|', $keywords).')\s*'; + $before = '(^|[=:,;\+\-\*\/\}\(\{\[&\|!]|'.implode('|', $keywords).')\s*'; $propertiesAndMethods = array( // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties_2 'constructor', diff --git a/lib/minify/matthiasmullie-minify/src/Minify.php b/lib/minify/matthiasmullie-minify/src/Minify.php index 3f40bc1578c..4d8dcf40ed6 100644 --- a/lib/minify/matthiasmullie-minify/src/Minify.php +++ b/lib/minify/matthiasmullie-minify/src/Minify.php @@ -105,7 +105,7 @@ abstract class Minify * @param string|string[] $data * * @return static - * + * * @throws IOException */ public function addFile($data /* $data = null, ... */) @@ -472,7 +472,7 @@ abstract class Minify */ protected function openFileForWriting($path) { - if (($handler = @fopen($path, 'w')) === false) { + if ($path === '' || ($handler = @fopen($path, 'w')) === false) { throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.'); } @@ -490,7 +490,11 @@ abstract class Minify */ protected function writeToFile($handler, $content, $path = '') { - if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) { + if ( + !is_resource($handler) || + ($result = @fwrite($handler, $content)) === false || + ($result < strlen($content)) + ) { throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.'); } } From f744eb816149926939470e679a7e4d86c863a8b3 Mon Sep 17 00:00:00 2001 From: Peter Dias Date: Wed, 13 Jan 2021 10:20:15 +0800 Subject: [PATCH 2/3] MDL-71702 core: Add custom Moodle patch to minify There is a Pull-request from Tim Hunt to the project in GitHub (https://github.com/matthiasmullie/minify/issues/317) but, for now, as it hasn't been applied yet, we need to manually cherry-pick this change. --- lib/minify/matthiasmullie-minify/src/CSS.php | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lib/minify/matthiasmullie-minify/src/CSS.php b/lib/minify/matthiasmullie-minify/src/CSS.php index eb98e52ed38..f50d96bbf47 100644 --- a/lib/minify/matthiasmullie-minify/src/CSS.php +++ b/lib/minify/matthiasmullie-minify/src/CSS.php @@ -637,7 +637,35 @@ class CSS extends Minify return $placeholder; }; + // Moodle-specific change MDL-68191 starts. + /* This was the old code: $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback); + */ + // This is the new, more accurate and faster regex. + $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); + // Moodle-specific change MDL-68191. $this->registerPattern('/\/\*.*?\*\//s', ''); } From 4752452fd5109fbba60bb19960103c21ade0e0c5 Mon Sep 17 00:00:00 2001 From: Sara Arjona Date: Tue, 11 Jan 2022 10:41:08 +0100 Subject: [PATCH 3/3] MDL-71702 lib: Set Moodle files after minify upgrade --- lib/minify/readme_moodle.txt | 19 +++++++------------ lib/thirdpartylibs.xml | 2 +- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/lib/minify/readme_moodle.txt b/lib/minify/readme_moodle.txt index 5d2f45408d1..18c8417a173 100644 --- a/lib/minify/readme_moodle.txt +++ b/lib/minify/readme_moodle.txt @@ -1,15 +1,16 @@ Description of MatthiasMullie\Minify import into Moodle -1) Download https://github.com/matthiasmullie/minify/archive/1.3.51.zip and unzip +1) Download https://github.com/matthiasmullie/minify/archive/X.Y.ZZ.zip and unzip -mv minify-1.3.51/src /path/to/moodle/lib/minify/matthiasmullie-minify/ -mv minify-1.3.51/data /path/to/moodle/lib/minify/matthiasmullie-minify/ +mv minify-X.Y.ZZ/src /path/to/moodle/lib/minify/matthiasmullie-minify/ +mv minify-X.Y.ZZ/data /path/to/moodle/lib/minify/matthiasmullie-minify/ -2) Download https://github.com/matthiasmullie/path-converter/archive/1.1.0.zip and unzip +2) Download https://github.com/matthiasmullie/path-converter/archive/A.B.C.zip and unzip -mv path-converter-1.1.0/src/ /path/to/moodle/lib/minify/matthiasmullie-pathconverter/ +mv path-converter-A.B.C/src/ /path/to/moodle/lib/minify/matthiasmullie-pathconverter/ -Local changes applied: + +3) Apply the following patches: MDL-68191: https://github.com/matthiasmullie/minify/issues/317 is a bug that stops large sections of the CSS from being minimised, and also is a huge performance drain. @@ -18,9 +19,3 @@ MDL-68191: https://github.com/matthiasmullie/minify/issues/317 is a bug that sto a few seconds. This is one of the reasons Behat runs in the browser are so slow.) Whenever this library is updated check if the fix is included and remove this note. NOTE: As of 2020/12/08, only the first commit was brought into Moodle - - -2020-12-07 - Peter Dias ------------------------ -* Removed php74 compliance step as it is now part of the library -* Updated minify to 1.3.63 and pathconverter to 1.1.3 \ No newline at end of file diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index 7f9d7d3a24b..66778738f0c 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -53,7 +53,7 @@ minify/matthiasmullie-minify MatthiasMullie\Minify MIT - 1.3.63 + 1.3.66