Skip to content

Commit

Permalink
feat: extract @font-face rules and inject it into head <styles> element
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron Gerig committed May 25, 2020
1 parent 6baf0c1 commit 1f1da9a
Showing 1 changed file with 45 additions and 8 deletions.
53 changes: 45 additions & 8 deletions src/CssInliner.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,13 @@ public function inlineCss(string $css = ''): self
$cssWithoutComments = $this->removeCssComments($combinedCss);
list($cssWithoutCommentsCharsetOrImport, $cssImportRules)
= $this->extractImportAndCharsetRules($cssWithoutComments);
list($cssWithoutCommentsCharsetOrImportAndFontFaces, $cssFontFaces)
= $this->extractFontFaces($cssWithoutCommentsCharsetOrImport);

$uninlinableCss = $cssImportRules . $cssFontFaces;

$excludedNodes = $this->getNodesToExclude();
$cssRules = $this->parseCssRules($cssWithoutCommentsCharsetOrImport);
$cssRules = $this->parseCssRules($cssWithoutCommentsCharsetOrImportAndFontFaces);
$cssSelectorConverter = $this->getCssSelectorConverter();
foreach ($cssRules['inlinable'] as $cssRule) {
try {
Expand Down Expand Up @@ -202,7 +206,7 @@ public function inlineCss(string $css = ''): self
$this->removeImportantAnnotationFromAllInlineStyles();

$this->determineMatchingUninlinableCssRules($cssRules['uninlinable']);
$this->copyUninlinableCssToStyleNode($cssImportRules);
$this->copyUninlinableCssToStyleNode($uninlinableCss);

return $this;
}
Expand Down Expand Up @@ -525,6 +529,39 @@ private function extractImportAndCharsetRules(string $css): array
return [$possiblyModifiedCss, $importRules];
}

/**
* Extracts `@font-face` rules from the supplied CSS. Note that `@font-face` rules can be placed anywhere in your
* CSS and are not case sensitive.
*
* @param string $css CSS with comments, import and charset removed
*
* @return string[] The first element is the CSS with the valid `@font-face` rules removed. The second
* element contains a concatenation of the valid `@font-face` rules, each followed by whatever whitespace followed it
* in the original CSS (so that either unminified or minified formatting is preserved); if there were no `@font-face`
* rules, it will be an empty string.
*/
private function extractFontFaces($css)
{
$possiblyModifiedCss = $css;
$fontFaces = '';

while (
\preg_match(
'/(@font-face\\s[^}]++}\\s*+)/i',
$possiblyModifiedCss,
$matches
)
) {
list($fullMatch, $atRuleAndFollowingWhitespace) = $matches;

$fontFaces .= $atRuleAndFollowingWhitespace;

$possiblyModifiedCss = \str_replace($fullMatch, '', $possiblyModifiedCss);
}

return [$possiblyModifiedCss, $fontFaces];
}

/**
* Find the nodes that are not to be emogrified.
*
Expand Down Expand Up @@ -1070,16 +1107,16 @@ private function replaceUnmatchableNotComponent(array $matches): string
* Applies `$this->matchingUninlinableCssRules` to `$this->domDocument` by placing them as CSS in a `<style>`
* element.
*
* @param string $cssImportRules This may contain any `@import` rules that should precede the CSS placed in the
* `<style>` element. If there are no unlinlinable CSS rules to copy there, a `<style>` element will be
* created containing just `$cssImportRules`. `$cssImportRules` may be an empty string; if it is, and there
* are no unlinlinable CSS rules, an empty `<style>` element will not be created.
* @param string $uninlinableCss This may contain any `@import` or `@font-face` rules that should precede the CSS
* placed in the `<style>` element. If there are no unlinlinable CSS rules to copy there, a `<style>` element
* will be created containing just `$uninlinableCss`. `$uninlinableCss` may be an empty string; if it is,
* and there are no unlinlinable CSS rules, an empty `<style>` element will not be created.
*
* @return void
*/
private function copyUninlinableCssToStyleNode(string $cssImportRules)
private function copyUninlinableCssToStyleNode(string $uninlinableCss)
{
$css = $cssImportRules;
$css = $uninlinableCss;

// avoid including unneeded class dependency if there are no rules
if ($this->matchingUninlinableCssRules !== []) {
Expand Down

0 comments on commit 1f1da9a

Please sign in to comment.