diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ef81b007..80bc018a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ 3. [](#bugfix) * Fixed CLI `--env` and `--lang` options having no effect if they aren't added before all the other options * Fixed scaled image medium filename when using non-existing retina file + * Fixed an issue with JS `imports` and pipelining Assets # v1.7.26.1 ## 01/04/2022 diff --git a/system/src/Grav/Common/Assets/Pipeline.php b/system/src/Grav/Common/Assets/Pipeline.php index 4e7348942..42b794976 100644 --- a/system/src/Grav/Common/Assets/Pipeline.php +++ b/system/src/Grav/Common/Assets/Pipeline.php @@ -36,6 +36,9 @@ class Pipeline extends PropertyObject /** @const Regex to match CSS urls */ protected const CSS_URL_REGEX = '{url\(([\'\"]?)(.*?)\1\)}'; + /** @const Regex to match JS imports */ + protected const JS_IMPORT_REGEX = '{import.*from\s?[\'|\"](.+?)[\'|\"]}'; + /** @const Regex to match CSS sourcemap comments */ protected const CSS_SOURCEMAP_REGEX = '{\/\*# (.*?) \*\/}'; @@ -276,6 +279,42 @@ class Pipeline extends PropertyObject return $file; } + /** + * Finds relative JS urls() and rewrites the URL with an absolute one + * + * @param string $file the css source file + * @param string $dir , $local relative path to the css file + * @param bool $local is this a local or remote asset + * @return string + */ + protected function jsRewrite($file, $dir, $local) + { + // Find any js import elements, grab the URLs and calculate an absolute path + // Then replace the old url with the new one + $file = (string)preg_replace_callback(self::JS_IMPORT_REGEX, function ($matches) use ($dir, $local) { + + $old_url = $matches[1]; + + // Ensure link is not rooted to web server, a data URL, or to a remote host + if (preg_match(self::FIRST_FORWARDSLASH_REGEX, $old_url) || $this->isRemoteLink($old_url)) { + return $matches[0]; + } + + // clean leading / + $old_url = Utils::normalizePath($dir . '/' . $old_url); + $old_url = str_replace('/./', '/', $old_url); + if (preg_match(self::FIRST_FORWARDSLASH_REGEX, $old_url)) { + $old_url = ltrim($old_url, '/'); + } + + $new_url = ($local ? $this->base_url : '') . $old_url; + + return str_replace($matches[1], $new_url, $matches[0]); + }, $file); + + return $file; + } + /** * @param string $type * @return bool diff --git a/system/src/Grav/Common/Assets/Traits/AssetUtilsTrait.php b/system/src/Grav/Common/Assets/Traits/AssetUtilsTrait.php index 5b1087d6c..f04ba438f 100644 --- a/system/src/Grav/Common/Assets/Traits/AssetUtilsTrait.php +++ b/system/src/Grav/Common/Assets/Traits/AssetUtilsTrait.php @@ -62,13 +62,13 @@ trait AssetUtilsTrait * Download and concatenate the content of several links. * * @param array $assets - * @param bool $css + * @param int $type * @return string */ - protected function gatherLinks(array $assets, $css = true) + protected function gatherLinks(array $assets, int $type = self::CSS_ASSET): string { $buffer = ''; - foreach ($assets as $id => $asset) { + foreach ($assets as $asset) { $local = true; $link = $asset->getAsset(); @@ -100,21 +100,25 @@ trait AssetUtilsTrait } // Double check last character being - if (!$css) { + if ($type === self::CSS_ASSET) { $file = rtrim($file, ' ;') . ';'; } // If this is CSS + the file is local + rewrite enabled - if ($css && $this->css_rewrite) { + if ($type === self::CSS_ASSET && $this->css_rewrite) { $file = $this->cssRewrite($file, $relative_dir, $local); } + if ($type === self::JS_MODULE_ASSET) { + $file = $this->jsRewrite($file, $relative_dir, $local); + } + $file = rtrim($file) . PHP_EOL; $buffer .= $file; } // Pull out @imports and move to top - if ($css) { + if ($type === self::CSS_ASSET) { $buffer = $this->moveImports($buffer); }