diff --git a/gzip.xml b/gzip.xml index f44e76d..e169161 100644 --- a/gzip.xml +++ b/gzip.xml @@ -299,6 +299,10 @@ + + + + diff --git a/helpers/CSS.php b/helpers/CSS.php index b070c81..721968d 100644 --- a/helpers/CSS.php +++ b/helpers/CSS.php @@ -20,6 +20,7 @@ use TBela\CSS\Element\Stylesheet; use TBela\CSS\Parser; use TBela\CSS\Renderer; +use TBela\CSS\Value; use function file_get_contents; use function file_put_contents; use function getimagesize; @@ -56,6 +57,8 @@ public function processHTML($html, array $options = []) $hashFile = GZipHelper::getHashMethod($options); $cssParser = new Parser(); + $cssRenderer = new Renderer($css_options); + $headStyle = new Stylesheet(); $parseUrls = function ($html) use($path, $root) { @@ -98,11 +101,11 @@ public function processHTML($html, array $options = []) }, $html); }; - $html = preg_replace_callback('#]*)>#', function ($matches) use ($parseUrls, &$links, $ignore, $remove, $cssParser, $path, $fetch_remote, $options) { + $html = preg_replace_callback('#<('.(empty($options['parseinlinecss']) ? 'link' : '[^\s>]+').')([^>]*)>#', function ($matches) use ($css_options, $cssRenderer, $parseUrls, &$links, $ignore, $remove, $cssParser, $path, $fetch_remote, $options) { $attributes = []; - if (preg_match_all(GZipHelper::regexAttr, $matches[1], $attr)) { + if (preg_match_all(GZipHelper::regexAttr, $matches[2], $attr)) { foreach ($attr[2] as $k => $att) { @@ -110,6 +113,36 @@ public function processHTML($html, array $options = []) } } + if ($matches[1] != 'link') { + + if (!empty($options['parseinlinecss']) && !empty($attributes['style'])) { + + $attributes['style'] = str_replace("\n", '', trim(preg_replace('~^\.foo\s*\{([^}]+)\}~s', '$1', $cssRenderer->render((new Parser('.foo { '.preg_replace_callback('~url\(([^)]+)\)~', function ($matches) { + + $name = preg_replace('#(^["\'])([^\1]+)\1#', '$2', trim($matches[1])); + + if (strpos($matches[0], 'data:') !== false || !GZipHelper::isFile($name)) { + + return $matches[0]; + } + + return 'url('.GZipHelper::url($name).')'; + + }, $attributes['style']).' }', $css_options))->parse())))); + + $result = '<'.$matches[1].' '; + + foreach ($attributes as $key => $value) { + + $result .= $key.'="'.$value.'" '; + } + + return rtrim($result).'>'; + } + + return $matches[0]; + } + if (!empty($attributes)) { if (isset($attributes['rel']) && $attributes['rel'] == 'stylesheet' && isset($attributes['href'])) { @@ -199,7 +232,7 @@ public function processHTML($html, array $options = []) $cssParser->append($attr['href']); } - file_put_contents($file, $parseUrls((new Renderer($css_options))->render($cssParser->parse()))); + file_put_contents($file, $parseUrls($cssRenderer->render($cssParser->parse()))); } $links[$position]['links'] = [ @@ -231,7 +264,7 @@ public function processHTML($html, array $options = []) if (!is_file($file)) { $cssParser->load($attr['href']); - file_put_contents($file, $parseUrls((new Renderer($css_options))->render($cssParser->parse()))); + file_put_contents($file, $parseUrls($cssRenderer->render($cssParser->parse()))); } } @@ -293,9 +326,6 @@ public function processHTML($html, array $options = []) $cssResize = null; $webFont = null; - $headStyle = new Stylesheet(); - $cssRenderer = new Renderer($css_options); - if ($parseWebFonts || $parseCritical || $parseCssResize) { if ($parseWebFonts) { @@ -367,23 +397,42 @@ public function processHTML($html, array $options = []) foreach ($headStyle->query('[@name="background"]|[@name="background-image"]') as $property) { $images = []; + $property->getValue()->map(function ($value) use(&$images) { - foreach ($property->getValue() as $value) { + /** + * @var Value $value + */ if ($value->type == 'css-url') { $name = GZipHelper::getName(preg_replace('#(^["\'])([^\1]+)\1#', '$2', trim($value->arguments->{0}))); - if (GZipHelper::isFile($name) && in_array(strtolower(pathinfo($name, PATHINFO_EXTENSION)), ['jpg', 'png', 'webp'])) { + if (GZipHelper::isFile($name)) { - $images[] = [ + if (in_array(strtolower(pathinfo($name, PATHINFO_EXTENSION)), ['jpg', 'png', 'webp'])) { - 'file' => $name, - 'size' => getimagesize($name) - ]; + $images[] = [ + + 'file' => $name, + 'size' => getimagesize($name) + ]; + } + + return Value::getInstance((object) [ + 'name' => 'url', + 'type' => 'css-url', + 'arguments' => new Value\Set([ + Value::getInstance((object) [ + 'type' => 'css-string', + 'value' => GZipHelper::url($name) + ]) + ]) + ]); } } - } + + return $value; + }); // ignore multiple backgrounds if (count($images) == 1) { @@ -465,7 +514,7 @@ public function processHTML($html, array $options = []) if ($headStyle->hasChildren()) { $headStyle->deduplicate(); - $head_string .= ''; + $head_string .= ''; } foreach ($links as $position => $blob) { diff --git a/helpers/HTML.php b/helpers/HTML.php index 49c3f5b..2b926c6 100644 --- a/helpers/HTML.php +++ b/helpers/HTML.php @@ -87,7 +87,7 @@ public function postProcessHTML ($html, array $options = []) { * attempt to fix invalidHTML - missing space between attributes - before minifying *
=>
*/ - $html = preg_replace_callback('#<(\S+)([^>]+)>#s', function ($matches) { + $html = preg_replace_callback('#<([^\s>]+)([^>]+)>#s', function ($matches) { $result = '<'.$matches[1]; @@ -168,7 +168,6 @@ public function postProcessHTML ($html, array $options = []) { $html = preg_replace('##s', '', $html); } - // $html = str_replace($options['scheme'].'://', '//', $html); $html = preg_replace_callback('#]+)?>(.*?)#si', function ($matches) { return ''. preg_replace('#>[\r\n\t ]+<#s', '><', $matches[2]).''; diff --git a/language/en-GB/en-GB.plg_system_gzip.ini b/language/en-GB/en-GB.plg_system_gzip.ini index 314944c..0fed285 100644 --- a/language/en-GB/en-GB.plg_system_gzip.ini +++ b/language/en-GB/en-GB.plg_system_gzip.ini @@ -173,6 +173,9 @@ PLG_GZIP_FIELD_FETCHCSS_DESCRIPTION="" PLG_GZIP_FIELD_MERGECSS_LABEL="Merge CSS" PLG_GZIP_FIELD_MERGECSS_DESCRIPTION="" +PLG_GZIP_FIELD_PARSE_INLINE_CSS_LABEL="Parse Inline CSS Attribute" +PLG_GZIP_FIELD_PARSE_INLINE_CSS_DESCRIPTION="" + PLG_GZIP_FIELD_FONT_REPLOAD_LABEL="Preload Web Font" PLG_GZIP_FIELD_FONT_REPLOAD_DESCRIPTION=""