PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.36.0
MailPoet – Newsletters, Email Marketing, and Automation v5.36.0
5.36.0 5.35.1 5.35.0 5.34.3 5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / vendor / woocommerce / email-editor / src / Engine / Renderer / ContentRenderer / class-content-renderer.php
mailpoet / vendor / woocommerce / email-editor / src / Engine / Renderer / ContentRenderer Last commit date
Layout 4 days ago Postprocessors 11 months ago Preprocessors 2 weeks ago class-block-renderer.php 11 months ago class-blocks-parser.php 11 months ago class-content-renderer.php 4 days ago class-preset-variable-resolver.php 3 months ago class-process-manager.php 3 months ago class-rendering-context.php 3 months ago content.css 11 months ago index.php 11 months ago
class-content-renderer.php
349 lines
1 <?php
2 declare(strict_types = 1);
3 namespace Automattic\WooCommerce\EmailEditor\Engine\Renderer\ContentRenderer;
4 if (!defined('ABSPATH')) exit;
5 use Automattic\WooCommerce\EmailEditor\Engine\Logger\Email_Editor_Logger;
6 use Automattic\WooCommerce\EmailEditor\Engine\Renderer\Css_Inliner;
7 use Automattic\WooCommerce\EmailEditor\Engine\Theme_Controller;
8 use Automattic\WooCommerce\EmailEditor\Integrations\Core\Renderer\Blocks\Fallback;
9 use Automattic\WooCommerce\EmailEditor\Integrations\Core\Renderer\Blocks\Post_Content;
10 use Automattic\WooCommerce\EmailEditor\Integrations\Utils\Table_Wrapper_Helper;
11 use WP_Block_Template;
12 use WP_Block_Type_Registry;
13 use WP_Post;
14 use WP_Style_Engine;
15 class Content_Renderer {
16 private Process_Manager $process_manager;
17 private Theme_Controller $theme_controller;
18 const CONTENT_STYLES_FILE = 'content.css';
19 private WP_Block_Type_Registry $block_type_registry;
20 private $backup_template_content;
21 private $backup_template_id;
22 private $backup_post;
23 private $backup_query;
24 private Fallback $fallback_renderer;
25 private Email_Editor_Logger $logger;
26 private $backup_post_content_callback;
27 private ?string $post_content_width = null;
28 private array $container_padding = array();
29 private Css_Inliner $css_inliner;
30 private ?Rendering_Context $rendering_context = null;
31 public function __construct(
32 Process_Manager $preprocess_manager,
33 Css_Inliner $css_inliner,
34 Theme_Controller $theme_controller,
35 Email_Editor_Logger $logger
36 ) {
37 $this->process_manager = $preprocess_manager;
38 $this->css_inliner = $css_inliner;
39 $this->theme_controller = $theme_controller;
40 $this->logger = $logger;
41 $this->block_type_registry = WP_Block_Type_Registry::get_instance();
42 $this->fallback_renderer = new Fallback();
43 }
44 private function initialize() {
45 add_filter( 'render_block', array( $this, 'render_block' ), 10, 2 );
46 add_filter( 'block_parser_class', array( $this, 'block_parser' ) );
47 add_filter( 'woocommerce_email_blocks_renderer_parsed_blocks', array( $this, 'preprocess_parsed_blocks' ) );
48 // Swap core/post-content render callback for email rendering.
49 // This prevents issues with WordPress's static $seen_ids array when rendering
50 // multiple emails in a single request (e.g., MailPoet batch processing).
51 $post_content_type = $this->block_type_registry->get_registered( 'core/post-content' );
52 if ( $post_content_type ) {
53 // Save the original callback (may be null or WordPress's default).
54 $this->backup_post_content_callback = $post_content_type->render_callback;
55 // Replace with our stateless renderer.
56 $post_content_renderer = new Post_Content();
57 $post_content_type->render_callback = array( $post_content_renderer, 'render_stateless' );
58 }
59 }
60 public function set_rendering_context( Rendering_Context $rendering_context ): void {
61 $this->rendering_context = $rendering_context;
62 }
63 public function get_current_rendering_context(): ?Rendering_Context {
64 return $this->rendering_context;
65 }
66 public function restore_rendering_context( ?Rendering_Context $rendering_context ): void {
67 $this->rendering_context = $rendering_context;
68 }
69 public function render( WP_Post $post, WP_Block_Template $template ): string {
70 $result = $this->render_without_css_inline( $post, $template );
71 $styles = '<style>' . $result['styles'] . '</style>';
72 $html = $this->css_inliner->from_html( $styles . $result['html'] )->inline_css()->render();
73 return $this->process_manager->postprocess( $html );
74 }
75 public function render_without_css_inline( WP_Post $post, WP_Block_Template $template ): array {
76 if ( null === $this->rendering_context ) {
77 $this->rendering_context = $this->create_rendering_context( null, $post, $template );
78 }
79 $this->set_template_globals( $post, $template );
80 $this->initialize();
81 try {
82 do_action( 'woocommerce_email_editor_render_start' );
83 $rendered_html = get_the_block_template_html();
84 } finally {
85 $this->reset();
86 }
87 return array(
88 'html' => $rendered_html,
89 'styles' => $this->collect_styles( $post, $template ),
90 );
91 }
92 public function block_parser() {
93 return 'Automattic\WooCommerce\EmailEditor\Engine\Renderer\ContentRenderer\Blocks_Parser';
94 }
95 public function preprocess_parsed_blocks( array $parsed_blocks ): array {
96 $styles = $this->theme_controller->get_styles();
97 $layout = $this->theme_controller->get_layout_settings();
98 // Pass the CSS variables map so preprocessors can resolve preset
99 // references (e.g. var:preset|spacing|20) in block attributes.
100 $styles['__variables_map'] = $this->theme_controller->get_variables_values_map();
101 // Second pass (user blocks inside post-content): if root padding was
102 // applied to a container above post-content in the first pass (indicated
103 // by post_content_width < contentSize), remove root padding from styles
104 // to prevent double application. If the template delegates root padding
105 // (post_content_width == contentSize), keep it for user blocks.
106 if ( null !== $this->post_content_width ) {
107 $post_content_num = (float) str_replace( 'px', '', $this->post_content_width );
108 $content_size_num = (float) str_replace( 'px', '', $layout['contentSize'] );
109 // Use epsilon tolerance for floating-point comparison since width
110 // calculations involve round() and division that may produce imprecision.
111 if ( $post_content_num < $content_size_num - 0.01 ) {
112 unset( $styles['spacing']['padding']['left'], $styles['spacing']['padding']['right'] );
113 // Constrain user blocks to the (inset) post-content width so they
114 // fit inside it instead of overflowing at the full contentSize.
115 $layout['contentSize'] = $this->post_content_width;
116 }
117 // Pass container padding from the first pass so the
118 // Spacing_Preprocessor can distribute it to user blocks.
119 if ( ! empty( $this->container_padding ) ) {
120 $styles['__container_padding'] = $this->container_padding;
121 }
122 }
123 $result = $this->process_manager->preprocess( $parsed_blocks, $layout, $styles, $this->get_rendering_context() );
124 // After the first pass: find the post-content block's width and container padding.
125 if ( null === $this->post_content_width ) {
126 $this->post_content_width = $this->find_post_content_width( $result );
127 $this->container_padding = $this->find_container_padding( $result );
128 }
129 return $result;
130 }
131 private function find_post_content_width( array $blocks, ?array $post_content_block_names = null ): ?string {
132 if ( null === $post_content_block_names ) {
133 $post_content_block_names = (array) apply_filters(
134 'woocommerce_email_editor_post_content_block_names',
135 array( 'core/post-content' )
136 );
137 }
138 foreach ( $blocks as $block ) {
139 $block_name = $block['blockName'] ?? '';
140 if ( in_array( $block_name, $post_content_block_names, true ) ) {
141 return $block['email_attrs']['width'] ?? null;
142 }
143 if ( ! empty( $block['innerBlocks'] ) ) {
144 $found = $this->find_post_content_width( $block['innerBlocks'], $post_content_block_names );
145 if ( null !== $found ) {
146 return $found;
147 }
148 }
149 }
150 return null;
151 }
152 private function find_container_padding( array $blocks ): array {
153 $variables_map = $this->theme_controller->get_variables_values_map();
154 foreach ( $blocks as $block ) {
155 $email_attrs = $block['email_attrs'] ?? array();
156 if ( ! empty( $email_attrs['suppress-horizontal-padding'] ) ) {
157 $padding = $block['attrs']['style']['spacing']['padding'] ?? array();
158 $result = array();
159 if ( isset( $padding['left'] ) && is_string( $padding['left'] ) ) {
160 $result['left'] = Preset_Variable_Resolver::resolve( $padding['left'], $variables_map );
161 }
162 if ( isset( $padding['right'] ) && is_string( $padding['right'] ) ) {
163 $result['right'] = Preset_Variable_Resolver::resolve( $padding['right'], $variables_map );
164 }
165 if ( ! empty( $result ) ) {
166 return $result;
167 }
168 }
169 if ( ! empty( $block['innerBlocks'] ) ) {
170 $found = $this->find_container_padding( $block['innerBlocks'] );
171 if ( ! empty( $found ) ) {
172 return $found;
173 }
174 }
175 }
176 return array();
177 }
178 public function render_block( string $block_content, array $parsed_block ): string {
179 $context = $this->get_rendering_context();
180 $block_type = $this->block_type_registry->get_registered( $parsed_block['blockName'] );
181 $result = null;
182 try {
183 if ( $block_type && isset( $block_type->render_email_callback ) && is_callable( $block_type->render_email_callback ) ) {
184 $result = call_user_func( $block_type->render_email_callback, $block_content, $parsed_block, $context );
185 }
186 } catch ( \Exception $error ) {
187 $this->logger->error(
188 'Error thrown while rendering block.',
189 array(
190 'exception' => $error,
191 'block_name' => $parsed_block['blockName'],
192 'parsed_block' => $parsed_block,
193 'message' => $error->getMessage(),
194 )
195 );
196 // Returning the original content.
197 return $block_content;
198 }
199 if ( null === $result ) {
200 $result = $this->fallback_renderer->render( $block_content, $parsed_block, $context );
201 }
202 return $this->add_root_horizontal_padding( $result, $parsed_block['email_attrs'] ?? array() );
203 }
204 private function add_root_horizontal_padding( string $content, array $email_attrs ): string {
205 $padding_left = $this->sum_padding_values(
206 $email_attrs['root-padding-left'] ?? null,
207 $email_attrs['container-padding-left'] ?? null
208 );
209 $padding_right = $this->sum_padding_values(
210 $email_attrs['root-padding-right'] ?? null,
211 $email_attrs['container-padding-right'] ?? null
212 );
213 $css_attrs = array();
214 if ( $padding_left > 0 ) {
215 $css_attrs['padding-left'] = $padding_left . 'px';
216 }
217 if ( $padding_right > 0 ) {
218 $css_attrs['padding-right'] = $padding_right . 'px';
219 }
220 if ( empty( $css_attrs ) ) {
221 return $content;
222 }
223 $padding_style = WP_Style_Engine::compile_css( $css_attrs, '' );
224 if ( empty( $padding_style ) ) {
225 return $content;
226 }
227 $table_attrs = array(
228 'align' => $this->get_rendering_context()->get_default_text_align(),
229 'width' => '100%',
230 );
231 $cell_attrs = array(
232 'style' => $padding_style,
233 );
234 $div_content = sprintf(
235 '<div class="email-root-padding" style="%1$s">%2$s</div>',
236 esc_attr( $padding_style ),
237 $content
238 );
239 return Table_Wrapper_Helper::render_outlook_table_wrapper( $div_content, $table_attrs, $cell_attrs );
240 }
241 private function sum_padding_values( ?string $value1, ?string $value2 ): float {
242 $sum = 0.0;
243 if ( null !== $value1 ) {
244 $sum += (float) str_replace( 'px', '', $value1 );
245 }
246 if ( null !== $value2 ) {
247 $sum += (float) str_replace( 'px', '', $value2 );
248 }
249 return $sum;
250 }
251 private function set_template_globals( WP_Post $email_post, WP_Block_Template $template ) {
252 global $_wp_current_template_content, $_wp_current_template_id, $wp_query, $post;
253 // Backup current values of globals.
254 // Because overriding the globals can affect rendering of the page itself, we need to backup the current values.
255 $this->backup_template_content = $_wp_current_template_content;
256 $this->backup_template_id = $_wp_current_template_id;
257 $this->backup_query = $wp_query;
258 $this->backup_post = $post;
259 $_wp_current_template_id = $template->id;
260 $_wp_current_template_content = $template->content;
261 if ( $email_post->ID > 0 ) {
262 $wp_query = new \WP_Query( array( 'p' => $email_post->ID ) ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- We need to set the query for correct rendering the blocks.
263 } else {
264 // Synthetic post (e.g. file-template rendering): querying `p => 0` would
265 // run a real "latest posts" query, so populate an empty query manually.
266 $wp_query = new \WP_Query(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- We need to set the query for correct rendering the blocks.
267 $wp_query->post = $email_post;
268 $wp_query->posts = array( $email_post );
269 $wp_query->post_count = 1;
270 $wp_query->found_posts = 1;
271 }
272 $post = $email_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- We need to set the post for correct rendering the blocks.
273 }
274 private function reset(): void {
275 remove_filter( 'render_block', array( $this, 'render_block' ) );
276 remove_filter( 'block_parser_class', array( $this, 'block_parser' ) );
277 remove_filter( 'woocommerce_email_blocks_renderer_parsed_blocks', array( $this, 'preprocess_parsed_blocks' ) );
278 $this->post_content_width = null;
279 $this->container_padding = array();
280 $this->rendering_context = null;
281 // Restore the original core/post-content render callback.
282 // Note: We always restore it, even if it was null originally.
283 $post_content_type = $this->block_type_registry->get_registered( 'core/post-content' );
284 if ( $post_content_type ) {
285 // @phpstan-ignore-next-line -- WordPress core allows null for render_callback despite type definition.
286 $post_content_type->render_callback = $this->backup_post_content_callback;
287 }
288 // Restore globals to their original values.
289 global $_wp_current_template_content, $_wp_current_template_id, $wp_query, $post;
290 $_wp_current_template_content = $this->backup_template_content;
291 $_wp_current_template_id = $this->backup_template_id;
292 $wp_query = $this->backup_query; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Restoring of the query.
293 $post = $this->backup_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Restoring of the post.
294 }
295 private function get_rendering_context(): Rendering_Context {
296 if ( null === $this->rendering_context ) {
297 $this->rendering_context = $this->create_rendering_context();
298 }
299 return $this->rendering_context;
300 }
301 public function create_rendering_context( ?string $language = null, ?WP_Post $post = null, ?WP_Block_Template $template = null ): Rendering_Context {
302 $email_context = apply_filters( 'woocommerce_email_editor_rendering_email_context', array(), $post, $template );
303 if ( ! is_array( $email_context ) ) {
304 $email_context = array();
305 }
306 return new Rendering_Context( $this->theme_controller->get_theme(), $email_context, $language );
307 }
308 private function collect_styles( WP_Post $post, $template = null ): string {
309 $styles = (string) file_get_contents( __DIR__ . '/' . self::CONTENT_STYLES_FILE );
310 $styles .= (string) file_get_contents( __DIR__ . '/../../content-shared.css' );
311 // Apply default contentWidth to constrained blocks.
312 $layout = $this->theme_controller->get_layout_settings();
313 $styles .= sprintf(
314 '
315 .is-layout-constrained > *:not(.alignleft):not(.alignright):not(.alignfull) {
316 max-width: %1$s;
317 margin-left: auto !important;
318 margin-right: auto !important;
319 }
320 .is-layout-constrained > .alignwide {
321 max-width: %2$s;
322 margin-left: auto !important;
323 margin-right: auto !important;
324 }
325 ',
326 $layout['contentSize'],
327 $layout['wideSize'] ?? $layout['contentSize']
328 );
329 // Get styles from theme.
330 $styles .= $this->theme_controller->get_stylesheet_for_rendering( $post, $template );
331 $block_support_styles = $this->theme_controller->get_stylesheet_from_context( 'block-supports', array() );
332 // Get styles from block-supports stylesheet. This includes rules such as layout (contentWidth) that some blocks use.
333 // @see https://github.com/WordPress/WordPress/blob/3c5da9c74344aaf5bf8097f2e2c6a1a781600e03/wp-includes/script-loader.php#L3134
334 // @internal :where is not supported by emogrifier, so we need to replace it with *.
335 $block_support_styles = str_replace(
336 ':where(:not(.alignleft):not(.alignright):not(.alignfull))',
337 '*:not(.alignleft):not(.alignright):not(.alignfull)',
338 $block_support_styles
339 );
340 $block_support_styles = preg_replace(
341 '/group-is-layout-(\d+) >/',
342 'group-is-layout-$1 > tbody tr td >',
343 $block_support_styles
344 );
345 $styles .= $block_support_styles;
346 return wp_strip_all_tags( (string) apply_filters( 'woocommerce_email_content_renderer_styles', $styles, $post ) );
347 }
348 }
349