diff --git a/lib/minify/matthiasmullie-minify/src/CSS.php b/lib/minify/matthiasmullie-minify/src/CSS.php
index e00856f6003..f50d96bbf47 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);
@@ -706,19 +707,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 +737,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.');
}
}
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 bc8eb66e5a3..c71d2d45616 100644
--- a/lib/thirdpartylibs.xml
+++ b/lib/thirdpartylibs.xml
@@ -60,7 +60,7 @@
minify/matthiasmullie-minify
MatthiasMullie\Minify
MIT
- 1.3.63
+ 1.3.66