Refactor font family rendering using CSS inlining
We don't reset font family on any level, so there is no need to bubble the setting using a preprocessor and render the inline styles explicitly in every block. In this commit, I change how font-family settings are distributed/rendered in the email renderer. In the new approach, we rely on class names defining font-family and a generated CSS sheet with font-family definitions. We apply the font-family CSS by inlining CSS rules for families in the later phase of rendering after all individual blocks are processed. [MAILPOET-5740]
This commit is contained in:
committed by
Jan Lysý
parent
a7aaf97070
commit
e8bb1b5ac0
@ -12,7 +12,6 @@ class TypographyPreprocessor implements Preprocessor {
|
||||
private const TYPOGRAPHY_STYLES = [
|
||||
'color',
|
||||
'font-size',
|
||||
'font-family',
|
||||
'text-decoration',
|
||||
];
|
||||
|
||||
@ -54,9 +53,6 @@ class TypographyPreprocessor implements Preprocessor {
|
||||
if (isset($block['attrs']['style']['color']['text'])) {
|
||||
$emailAttrs['color'] = $block['attrs']['style']['color']['text'];
|
||||
}
|
||||
if (isset($block['attrs']['fontFamily'])) {
|
||||
$emailAttrs['font-family'] = $this->getFontFamilyBySlug($block['attrs']['fontFamily']);
|
||||
}
|
||||
if (isset($block['attrs']['style']['typography']['fontSize'])) {
|
||||
$emailAttrs['font-size'] = $block['attrs']['style']['typography']['fontSize'];
|
||||
}
|
||||
@ -80,20 +76,6 @@ class TypographyPreprocessor implements Preprocessor {
|
||||
if (!($block['email_attrs']['font-size'] ?? '')) {
|
||||
$block['email_attrs']['font-size'] = $contentStyles['typography']['fontSize'];
|
||||
}
|
||||
if (!($block['email_attrs']['font-family'] ?? '')) {
|
||||
$block['email_attrs']['font-family'] = $contentStyles['typography']['fontFamily'];
|
||||
}
|
||||
return $block;
|
||||
}
|
||||
|
||||
private function getFontFamilyBySlug(string $slug): ?string {
|
||||
$themeData = $this->settingsController->getTheme()->get_data();
|
||||
$fontFamilies = $themeData['settings']['typography']['fontFamilies'] ?? [];
|
||||
foreach ($fontFamilies as $fontFamily) {
|
||||
if ($fontFamily['slug'] === $slug) {
|
||||
return $fontFamily['fontFamily'];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ class Renderer {
|
||||
$renderedBody = $this->renderBlocks($parsedBlocks);
|
||||
|
||||
$styles = (string)file_get_contents(dirname(__FILE__) . '/' . self::TEMPLATE_STYLES_FILE);
|
||||
$styles .= $this->settingsController->getStylesheetForRendering();
|
||||
$styles = apply_filters('mailpoet_email_renderer_styles', $styles, $post);
|
||||
|
||||
$template = (string)file_get_contents(dirname(__FILE__) . '/' . self::TEMPLATE_FILE);
|
||||
|
@ -236,4 +236,14 @@ class SettingsController {
|
||||
/** @var array $themeJson */
|
||||
return new \WP_Theme_JSON($themeJson);
|
||||
}
|
||||
|
||||
public function getStylesheetForRendering(): string {
|
||||
$settings = $this->getTheme()->get_settings();
|
||||
$css = '';
|
||||
// Font family classes
|
||||
foreach ($settings['typography']['fontFamilies']['theme'] as $fontFamily) {
|
||||
$css .= ".has-{$fontFamily['slug']}-font-family { font-family: {$fontFamily['fontFamily']}; } \n";
|
||||
}
|
||||
return $css;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,11 @@ class Button implements BlockRenderer {
|
||||
return '';
|
||||
}
|
||||
|
||||
$buttonOriginalWrapper = $buttonDom->getElementsByTagName('div')->item(0);
|
||||
$buttonClasses = $buttonOriginalWrapper instanceof \DOMElement ? $buttonOriginalWrapper->getAttribute('class') : '';
|
||||
|
||||
$markup = $this->getMarkup();
|
||||
$markup = str_replace('{classes}', $buttonClasses, $markup);
|
||||
|
||||
// Add Link Text
|
||||
$markup = str_replace('{linkText}', $buttonLink->textContent ?: '', $markup);
|
||||
@ -91,8 +95,6 @@ class Button implements BlockRenderer {
|
||||
// Escaping
|
||||
$wrapperStyles = array_map('esc_attr', $wrapperStyles);
|
||||
$linkStyles = array_map('esc_attr', $linkStyles);
|
||||
// Font family may contain single quotes
|
||||
$linkStyles['font-family'] = str_replace(''', "'", esc_attr("{$parsedBlock['email_attrs']['font-family']}"));
|
||||
|
||||
$markup = str_replace('{linkStyles}', $settingsController->convertStylesToString($linkStyles), $markup);
|
||||
$markup = str_replace('{wrapperStyles}', $settingsController->convertStylesToString($wrapperStyles), $markup);
|
||||
@ -103,7 +105,7 @@ class Button implements BlockRenderer {
|
||||
private function getMarkup(): string {
|
||||
return '<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:middle;border-collapse:separate;line-height:100%;width:{width};">
|
||||
<tr>
|
||||
<td align="center" bgcolor="{backgroundColor}" role="presentation" style="{wrapperStyles}" valign="middle">
|
||||
<td align="center" class="{classes}" bgcolor="{backgroundColor}" role="presentation" style="{wrapperStyles}" valign="middle">
|
||||
<a href="{linkUrl}" style="{linkStyles}" target="_blank">{linkText}</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -42,9 +42,6 @@ class Heading implements BlockRenderer {
|
||||
if (!isset($styles['font-size'])) {
|
||||
$styles['font-size'] = $contentStyles['typography']['fontSize'];
|
||||
}
|
||||
if (!isset($styles['font-family'])) {
|
||||
$styles['font-family'] = $contentStyles['typography']['fontFamily'];
|
||||
}
|
||||
|
||||
$styles = array_merge($styles, $this->fetchStylesFromBlockAttrs($availableStylesheets, $parsedBlock['attrs']));
|
||||
|
||||
|
@ -23,9 +23,6 @@ class ListBlock implements BlockRenderer {
|
||||
if (!isset($styles['font-size'])) {
|
||||
$styles['font-size'] = $contentStyles['typography']['fontSize'];
|
||||
}
|
||||
if (!isset($styles['font-family'])) {
|
||||
$styles['font-family'] = $contentStyles['typography']['fontFamily'];
|
||||
}
|
||||
|
||||
$html->set_attribute('style', $settingsController->convertStylesToString($styles));
|
||||
$blockContent = $html->get_updated_html();
|
||||
|
@ -41,9 +41,6 @@ class Paragraph implements BlockRenderer {
|
||||
if (!isset($styles['font-size'])) {
|
||||
$styles['font-size'] = $contentStyles['typography']['fontSize'];
|
||||
}
|
||||
if (!isset($styles['font-family'])) {
|
||||
$styles['font-family'] = $contentStyles['typography']['fontFamily'];
|
||||
}
|
||||
|
||||
$styles = array_merge($styles, $this->fetchStylesFromBlockAttrs($availableStylesheets, $parsedBlock['attrs'] ?? []));
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\EmailEditor\Engine;
|
||||
|
||||
class SettingsControllerTest extends \MailPoetTest {
|
||||
/** @var SettingsController */
|
||||
private $settingsController;
|
||||
|
||||
public function _before() {
|
||||
parent::_before();
|
||||
$this->settingsController = $this->diContainer->get(SettingsController::class);
|
||||
}
|
||||
|
||||
public function testItGeneratesCssStylesForThemeWithFontFamilies() {
|
||||
$css = $this->settingsController->getStylesheetForRendering();
|
||||
verify($css)->stringContainsString('.has-system-sans-serif-font-family');
|
||||
verify($css)->stringContainsString('.has-system-Serif-font-family');
|
||||
}
|
||||
}
|
@ -150,15 +150,4 @@ class ButtonTest extends \MailPoetTest {
|
||||
verify($output)->stringContainsString('border-bottom-left-radius:3px;');
|
||||
verify($output)->stringContainsString('border-bottom-right-radius:4px;');
|
||||
}
|
||||
|
||||
public function testItAllowsSingleQuotesInFontFamilyDefinition(): void {
|
||||
$settingsControllerMock = $this->createPartialMock(SettingsController::class, ['getEmailContentStyles']);
|
||||
$settingsControllerMock->method('getEmailContentStyles')->willReturn([
|
||||
'typography' => [
|
||||
'fontFamily' => '"Font\'", serif',
|
||||
],
|
||||
]);
|
||||
$output = $this->buttonRenderer->render($this->parsedButton['innerHTML'], $this->parsedButton, $settingsControllerMock);
|
||||
verify($output)->stringContainsString('"Font\'", serif');
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,6 @@ class TypographyPreprocessorTest extends \MailPoetUnitTest {
|
||||
]];
|
||||
$expectedEmailAttrs = [
|
||||
'color' => '#aa00dd',
|
||||
'font-family' => 'Arial',
|
||||
'font-size' => '12px',
|
||||
'text-decoration' => 'underline',
|
||||
];
|
||||
@ -121,8 +120,8 @@ class TypographyPreprocessorTest extends \MailPoetUnitTest {
|
||||
$result = $this->preprocessor->preprocess($blocks, []);
|
||||
$result = $result[0];
|
||||
verify($result['innerBlocks'])->arrayCount(2);
|
||||
verify($result['email_attrs'])->equals(['width' => '640px', 'color' => '#000000', 'font-size' => '13px', 'font-family' => 'Arial']);
|
||||
$defaultFontStyles = ['color' => '#000000', 'font-size' => '13px', 'font-family' => 'Arial'];
|
||||
verify($result['email_attrs'])->equals(['width' => '640px', 'color' => '#000000', 'font-size' => '13px']);
|
||||
$defaultFontStyles = ['color' => '#000000', 'font-size' => '13px'];
|
||||
verify($result['innerBlocks'][0]['email_attrs'])->equals($defaultFontStyles);
|
||||
verify($result['innerBlocks'][1]['email_attrs'])->equals($defaultFontStyles);
|
||||
verify($result['innerBlocks'][1]['innerBlocks'][0]['email_attrs'])->equals($defaultFontStyles);
|
||||
@ -207,12 +206,10 @@ class TypographyPreprocessorTest extends \MailPoetUnitTest {
|
||||
];
|
||||
$expectedEmailAttrs1 = [
|
||||
'color' => '#aa00dd',
|
||||
'font-family' => 'Arial',
|
||||
'font-size' => '12px',
|
||||
];
|
||||
$expectedEmailAttrs2 = [
|
||||
'color' => '#cc22aa',
|
||||
'font-family' => 'Georgia',
|
||||
'font-size' => '18px',
|
||||
];
|
||||
$result = $this->preprocessor->preprocess($blocks, []);
|
||||
@ -225,7 +222,7 @@ class TypographyPreprocessorTest extends \MailPoetUnitTest {
|
||||
verify($child1['innerBlocks'][1]['email_attrs'])->equals($expectedEmailAttrs1);
|
||||
verify($child1['innerBlocks'][1]['innerBlocks'][0]['email_attrs'])->equals($expectedEmailAttrs1);
|
||||
verify($child2['innerBlocks'])->arrayCount(1);
|
||||
verify($child2['email_attrs'])->equals(['color' => '#000000', 'font-size' => '13px', 'font-family' => 'Arial']);
|
||||
verify($child2['email_attrs'])->equals(['color' => '#000000', 'font-size' => '13px']);
|
||||
verify($child2['innerBlocks'][0]['email_attrs'])->equals($expectedEmailAttrs2);
|
||||
verify($child2['innerBlocks'][0]['innerBlocks'][0]['email_attrs'])->equals($expectedEmailAttrs2);
|
||||
}
|
||||
|
Reference in New Issue
Block a user