diff --git a/src/CssInliner.php b/src/CssInliner.php index 0634126e..5cbd0d10 100644 --- a/src/CssInliner.php +++ b/src/CssInliner.php @@ -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 { @@ -202,7 +206,7 @@ public function inlineCss(string $css = ''): self $this->removeImportantAnnotationFromAllInlineStyles(); $this->determineMatchingUninlinableCssRules($cssRules['uninlinable']); - $this->copyUninlinableCssToStyleNode($cssImportRules); + $this->copyUninlinableCssToStyleNode($uninlinableCss); return $this; } @@ -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. * @@ -1070,16 +1107,16 @@ private function replaceUnmatchableNotComponent(array $matches): string * Applies `$this->matchingUninlinableCssRules` to `$this->domDocument` by placing them as CSS in a `