Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fluid Typography: Backport PHP changes for custom font sizes #3431

47 changes: 42 additions & 5 deletions src/wp-includes/block-supports/typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@ function wp_apply_typography_support( $block_type, $block_attributes ) {
$custom_font_size = isset( $block_attributes['style']['typography']['fontSize'] )
? $block_attributes['style']['typography']['fontSize']
: null;
$typography_block_styles['fontSize'] = $preset_font_size ? $preset_font_size : $custom_font_size;
$typography_block_styles['fontSize'] = $preset_font_size ? $preset_font_size : wp_get_typography_font_size_value(
array(
'size' => $custom_font_size,
)
);
}

if ( $has_font_family_support && ! $should_skip_font_family ) {
Expand Down Expand Up @@ -244,6 +248,33 @@ function wp_typography_get_preset_inline_style_value( $style_value, $css_propert
return sprintf( 'var(--wp--preset--%s--%s);', $css_property, $slug );
}

/**
* Renders typography styles/content to the block wrapper.
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @since 6.1.0 for new function

* @param string $block_content Rendered block content.
* @param array $block Block object.
dream-encode marked this conversation as resolved.
Show resolved Hide resolved
* @return string Filtered block content.
dream-encode marked this conversation as resolved.
Show resolved Hide resolved
*/
function wp_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 = wp_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;
}

/**
* Checks a string for a unit and value and returns an array
* consisting of `'value'` and `'unit'`, e.g., [ '42', 'rem' ].
Expand Down Expand Up @@ -395,15 +426,19 @@ function wp_get_computed_fluid_typography_value( $args = array() ) {
* @param array $preset {
* Required. fontSizes preset value as seen in theme.json.
*
* @type string $name Name of the font size preset.
* @type string $slug Kebab-case unique identifier for the font size preset.
* @type string $size CSS font-size value, including units where applicable.
* @type string $name Name of the font size preset.
* @type string $slug Kebab-case unique identifier for the font size preset.
* @type string|int $size CSS font-size value, including units where applicable.
* }
* @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 wp_get_typography_font_size_value( $preset, $should_use_fluid_typography = false ) {
if ( ! isset( $preset['size'] ) || empty( $preset['size'] ) ) {
return null;
}

// Checks if fluid font sizes are activated.
$typography_settings = wp_get_global_settings( array( 'typography' ) );
$should_use_fluid_typography = isset( $typography_settings['fluid'] ) && true === $typography_settings['fluid'] ? true : $should_use_fluid_typography;
Expand Down Expand Up @@ -473,3 +508,5 @@ function wp_get_typography_font_size_value( $preset, $should_use_fluid_typograph
'apply' => 'wp_apply_typography_support',
)
);

add_filter( 'render_block', 'wp_render_typography_support', 10, 2 );
12 changes: 12 additions & 0 deletions src/wp-includes/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,18 @@ protected static function compute_style_properties( $styles, $settings = array()
continue;
}

// Calculates fluid typography rules where available.
if ( 'font-size' === $css_property ) {
/*
* wp_get_typography_font_size_value() will check
* if fluid typography has been activated and also
* whether the incoming value can be converted to a fluid value.
* Values that already have a "clamp()" function will not pass the test,
* and therefore the original $value will be returned.
*/
$value = wp_get_typography_font_size_value( array( 'size' => $value ) );
}

$declarations[] = array(
'name' => $css_property,
'value' => $value,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Theme Name: Block Theme Child Theme With Fluid Typography
Theme URI: https://wordpress.org/
Description: For testing purposes only.
Template: block-theme
Version: 1.0.0
Text Domain: block-theme-child-with-fluid-typography
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"version": 2,
"settings": {
"appearanceTools": true,
"typography": {
"fluid": true
}
}
}
212 changes: 212 additions & 0 deletions tests/phpunit/tests/block-supports/typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,56 @@ class Tests_Block_Supports_Typography 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;

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_TESTDATA . '/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'] );
}

/**
* Unregisters block type after each test.
*/
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();
}

Expand Down Expand Up @@ -298,6 +337,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',
Expand Down Expand Up @@ -371,4 +428,159 @@ 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`.
*
* @ticket 56467
*
* @covers ::wp_register_typography_support
*
* @dataProvider data_generate_block_supports_font_size_fixtures
*
* @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 wp_apply_typography_support().
*/
public function test_should_covert_font_sizes_to_fluid_values( $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' );
}

$this->test_block_name = 'test/font-size-fluid-value';
register_block_type(
$this->test_block_name,
array(
'api_version' => 2,
'attributes' => array(
'style' => array(
'type' => 'object',
),
),
'supports' => array(
'typography' => array(
'fontSize' => true,
),
),
)
);
$registry = WP_Block_Type_Registry::get_instance();
$block_type = $registry->get_registered( $this->test_block_name );
$block_attributes = array(
'style' => array(
'typography' => array(
'fontSize' => $font_size_value,
),
),
);

$actual = wp_apply_typography_support( $block_type, $block_attributes );
$expected = array( 'style' => $expected_output );

$this->assertSame( $expected, $actual );
}

/**
* Data provider for test_should_covert_font_sizes_to_fluid_values.
*
* @return array
*/
public function data_generate_block_supports_font_size_fixtures() {
return array(
'default_return_value' => array(
'font_size_value' => '50px',
'should_use_fluid_typography' => false,
'expected_output' => 'font-size:50px;',
),
'return_value_with_fluid_typography' => array(
'font_size_value' => '50px',
'should_use_fluid_typography' => true,
'expected_output' => 'font-size:clamp(37.5px, 2.34375rem + ((1vw - 7.68px) * 4.507), 75px);',
),
);
}

/**
* Tests that a block element's custom font size in the inline style attribute
* is replaced with a fluid value when "settings.typography.fluid" is set to `true`,
* and the correct block content is generated.
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also be added to @ticket 56467?

* @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 wp_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 = wp_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' => '<h2 class="has-vivid-red-background-color has-background has-link-color" style="margin-top:var(--wp--preset--spacing--60);font-size:4rem;font-style:normal;font-weight:600;letter-spacing:29px;text-decoration:underline;text-transform:capitalize">This is a heading</h2>',
'font_size_value' => '4rem',
'should_use_fluid_typography' => false,
'expected_output' => '<h2 class="has-vivid-red-background-color has-background has-link-color" style="margin-top:var(--wp--preset--spacing--60);font-size:4rem;font-style:normal;font-weight:600;letter-spacing:29px;text-decoration:underline;text-transform:capitalize">This is a heading</h2>',
),
'return_content_with_replaced_fluid_font_size_inline_style' => array(
'block_content' => '<h2 class="has-vivid-red-background-color has-background has-link-color" style="margin-top:var(--wp--preset--spacing--60);font-size:4rem;font-style:normal;font-weight:600;letter-spacing:29px;text-decoration:underline;text-transform:capitalize">This is a heading</h2>',
'font_size_value' => '4rem',
'should_use_fluid_typography' => true,
'expected_output' => '<h2 class="has-vivid-red-background-color has-background has-link-color" style="margin-top:var(--wp--preset--spacing--60);font-size:clamp(3rem, 3rem + ((1vw - 0.48rem) * 5.769), 6rem);font-style:normal;font-weight:600;letter-spacing:29px;text-decoration:underline;text-transform:capitalize">This is a heading</h2>',
),
'return_content_if_no_inline_font_size_found' => array(
'block_content' => '<p class="has-medium-font-size" style="font-style:normal;font-weight:600;letter-spacing:29px;">A paragraph inside a group</p>',
'font_size_value' => '20px',
'should_use_fluid_typography' => true,
'expected_output' => '<p class="has-medium-font-size" style="font-style:normal;font-weight:600;letter-spacing:29px;">A paragraph inside a group</p>',
),
'return_content_css_var' => array(
'block_content' => '<p class="has-medium-font-size" style="font-size:var(--wp--preset--font-size--x-large);">A paragraph inside a group</p>',
'font_size_value' => 'var:preset|font-size|x-large',
'should_use_fluid_typography' => true,
'expected_output' => '<p class="has-medium-font-size" style="font-size:var(--wp--preset--font-size--x-large);">A paragraph inside a group</p>',
),
'return_content_with_spaces' => array(
'block_content' => '<p class="has-medium-font-size" style=" font-size: 20px ; ">A paragraph inside a group</p>',
'font_size_value' => '20px',
'should_use_fluid_typography' => true,
'expected_output' => '<p class="has-medium-font-size" style=" font-size:clamp(15px, 0.9375rem + ((1vw - 7.68px) * 1.803), 30px); ">A paragraph inside a group</p>',
),
'return_content_with_first_match_replace_only' => array(
'block_content' => "<div class=\"wp-block-group\" style=\"font-size:1em\"> \n \n<p style=\"font-size:1em\">A paragraph inside a group</p></div>",
'font_size_value' => '1em',
'should_use_fluid_typography' => true,
'expected_output' => "<div class=\"wp-block-group\" style=\"font-size:clamp(0.75em, 0.75em + ((1vw - 0.48em) * 1.442), 1.5em);\"> \n \n<p style=\"font-size:1em\">A paragraph inside a group</p></div>",
),
);
}
}
1 change: 1 addition & 0 deletions tests/phpunit/tests/theme/themeDir.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ public function test_theme_list() {
'REST Theme',
'Block Theme',
'Block Theme Child Theme',
'Block Theme Child Theme With Fluid Typography',
'Block Theme [0.4.0]',
'Block Theme [1.0.0] in subdirectory',
'Block Theme Deprecated Path',
Expand Down