diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index f84bfd2a74b8f..22dfdba97fbb8 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -228,14 +228,42 @@ function gutenberg_typography_get_css_variable_inline_style( $attributes, $featu return sprintf( '%s:var(--wp--preset--%s--%s);', $css_property, $css_property, $slug ); } +/** + * Renders typography styles/content to the block wrapper. + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ +function gutenberg_render_typography_support( $block_content, $block ) { + if ( ! isset( $block['attrs']['style']['typography']['fontSize'] ) ) { + return $block_content; + } + + $custom_font_size = $block['attrs']['style']['typography']['fontSize']; + $fluid_font_size = gutenberg_get_typography_font_size_value( array( 'size' => $custom_font_size ) ); + + /* + * Checks that $fluid_font_size does not match $custom_font_size, + * which means it's been mutated by the fluid font size functions. + */ + if ( ! empty( $fluid_font_size ) && $fluid_font_size !== $custom_font_size ) { + // Replaces the first instance of `font-size:$custom_font_size` with `font-size:$fluid_font_size`. + return preg_replace( '/font-size\s*:\s*' . preg_quote( $custom_font_size, '/' ) . '\s*;?/', 'font-size:' . esc_attr( $fluid_font_size ) . ';', $block_content, 1 ); + } + + return $block_content; + +} + /** * Internal method that checks a string for a unit and value and returns an array consisting of `'value'` and `'unit'`, e.g., [ '42', 'rem' ]. * A raw font size of `value + unit` is expected. If the value is a number, it will convert to `value + 'px'`. * * @access private * - * @param string $raw_value Raw size value from theme.json. - * @param array $options { + * @param string|number $raw_value Raw size value from theme.json. + * @param array $options { * Optional. An associative array of options. Default is empty array. * * @type string $coerce_to Coerce the value to rem or px. Default `'rem'`. @@ -380,9 +408,13 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { * } * @param bool $should_use_fluid_typography An override to switch fluid typography "on". Can be used for unit testing. Default is `false`. * - * @return string Font-size value. + * @return string|null Font-size value or `null` if a size is not passed in $preset. */ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_typography = false ) { + if ( ! isset( $preset['size'] ) || empty( $preset['size'] ) ) { + return null; + } + // Check if fluid font sizes are activated. $typography_settings = gutenberg_get_global_settings( array( 'typography' ) ); $should_use_fluid_typography = isset( $typography_settings['fluid'] ) && true === $typography_settings['fluid'] ? true : $should_use_fluid_typography; @@ -452,3 +484,8 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty 'apply' => 'gutenberg_apply_typography_support', ) ); + +if ( function_exists( 'wp_render_typography_support' ) ) { + remove_filter( 'render_block', 'wp_render_typography_support' ); +} +add_filter( 'render_block', 'gutenberg_render_typography_support', 10, 2 ); diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php index 0b1cba6c83c80..d21619a3a5286 100644 --- a/phpunit/block-supports/typography-test.php +++ b/phpunit/block-supports/typography-test.php @@ -12,20 +12,59 @@ class WP_Block_Supports_Typography_Test extends WP_UnitTestCase { */ private $test_block_name; + /** + * Stores the current test theme root. + * + * @var string|null + */ + private $theme_root; + + /** + * Caches the original theme directory global value in order + * to restore it in tear down. + * + * @var string|null + */ + private $orig_theme_dir; + /** * Sets up tests. */ public function set_up() { parent::set_up(); + $this->test_block_name = null; + + // Sets up the `wp-content/themes/` directory to ensure consistency when running tests. + $this->theme_root = realpath( __DIR__ . '/../data/themedir1' ); + $this->orig_theme_dir = $GLOBALS['wp_theme_directories']; + $GLOBALS['wp_theme_directories'] = array( WP_CONTENT_DIR . '/themes', $this->theme_root ); + + $theme_root_callback = function () { + return $this->theme_root; + }; + add_filter( 'theme_root', $theme_root_callback ); + add_filter( 'stylesheet_root', $theme_root_callback ); + add_filter( 'template_root', $theme_root_callback ); + + // Clear caches. + wp_clean_themes_cache(); + unset( $GLOBALS['wp_themes'] ); } /** * Tears down tests. */ public function tear_down() { + // Restores the original theme directory setup. + $GLOBALS['wp_theme_directories'] = $this->orig_theme_dir; + wp_clean_themes_cache(); + unset( $GLOBALS['wp_themes'] ); + + // Resets test block name. unregister_block_type( $this->test_block_name ); $this->test_block_name = null; + parent::tear_down(); } @@ -301,6 +340,24 @@ public function data_generate_font_size_preset_fixtures() { 'expected_output' => '28px', ), + 'default_return_value_when_value_is_already_clamped' => array( + 'font_size_preset' => array( + 'size' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)', + 'fluid' => false, + ), + 'should_use_fluid_typography' => true, + 'expected_output' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)', + ), + + 'default_return_value_with_unsupported_unit' => array( + 'font_size_preset' => array( + 'size' => '1000%', + 'fluid' => false, + ), + 'should_use_fluid_typography' => true, + 'expected_output' => '1000%', + ), + 'return_fluid_value' => array( 'font_size_preset' => array( 'size' => '1.75rem', @@ -382,4 +439,86 @@ public function data_generate_font_size_preset_fixtures() { ), ); } + + /** + * Tests that custom font sizes are converted to fluid values + * in inline block supports styles, + * when "settings.typography.fluid" is set to `true`. + * + * @covers ::gutenberg_render_typography_support + * + * @dataProvider data_generate_replace_inline_font_styles_with_fluid_values_fixtures + * + * @param string $block_content HTML block content. + * @param string $font_size_value The block supports custom font size value. + * @param bool $should_use_fluid_typography An override to switch fluid typography "on". Can be used for unit testing. + * @param string $expected_output Expected value of style property from gutenberg_apply_typography_support(). + */ + public function test_should_replace_inline_font_styles_with_fluid_values( $block_content, $font_size_value, $should_use_fluid_typography, $expected_output ) { + if ( $should_use_fluid_typography ) { + switch_theme( 'block-theme-child-with-fluid-typography' ); + } else { + switch_theme( 'default' ); + } + + $block = array( + 'blockName' => 'core/image', + 'attrs' => array( + 'style' => array( + 'typography' => array( + 'fontSize' => $font_size_value, + ), + ), + ), + ); + $actual = gutenberg_render_typography_support( $block_content, $block ); + + $this->assertSame( $expected_output, $actual ); + } + + /** + * Data provider for test_should_replace_inline_font_styles_with_fluid_values. + * + * @return array + */ + public function data_generate_replace_inline_font_styles_with_fluid_values_fixtures() { + return array( + 'default_return_content' => array( + 'block_content' => '
A paragraph inside a group
', + 'font_size_value' => '20px', + 'should_use_fluid_typography' => true, + 'expected_output' => 'A paragraph inside a group
', + ), + 'return_content_css_var' => array( + 'block_content' => 'A paragraph inside a group
', + 'font_size_value' => 'var:preset|font-size|x-large', + 'should_use_fluid_typography' => true, + 'expected_output' => 'A paragraph inside a group
', + ), + 'return_content_with_spaces' => array( + 'block_content' => 'A paragraph inside a group
', + 'font_size_value' => '20px', + 'should_use_fluid_typography' => true, + 'expected_output' => 'A paragraph inside a group
', + ), + 'return_content_with_first_match_replace_only' => array( + 'block_content' => "A paragraph inside a group
A paragraph inside a group