From db8dd971e88993b1d60d76f0437b47176c836bdc Mon Sep 17 00:00:00 2001 From: ramonjd Date: Sat, 15 Oct 2022 16:07:33 +1100 Subject: [PATCH 01/12] Initial commit: - Adds default minimum font size limits so that text does not become smaller than 14px/0.875rem/0.875em. The consequence will be that all fluid font sizes will be no smaller than 14px/0.875rem/0.875em in any viewport width. - Users may define font-sizes that are smaller than 14px/0.875rem/0.875em. In this case the user-defined font size becomes the minimum. For example if a user defines 9px for a block, then the minimum font size for that block will be 9px. - Min font size should not be greater than max font size. - Round to 3 decimal places (JS) - Rounding computed min and max values --- lib/block-supports/typography.php | 105 ++-- .../src/components/font-sizes/fluid-utils.js | 73 ++- .../components/font-sizes/test/fluid-utils.js | 10 +- .../global-styles/test/typography-utils.js | 463 +++++++++++------- phpunit/block-supports/typography-test.php | 134 +++-- 5 files changed, 524 insertions(+), 261 deletions(-) diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index 2126aaf847fdec..ddc7500889e32d 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -342,11 +342,11 @@ function gutenberg_get_typography_value_and_unit( $raw_value, $options = array() * @param array $args { * Optional. An associative array of values to calculate a fluid formula for font size. Default is empty array. * - * @type string $maximum_viewport_width Maximum size up to which type will have fluidity. - * @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity. - * @type string $maximum_font_size Maximum font size for any clamp() calculation. - * @type string $minimum_font_size Minimum font size for any clamp() calculation. - * @type int $scale_factor A scale factor to determine how fast a font scales within boundaries. + * @type string $maximum_viewport_width Maximum size up to which type will have fluidity. + * @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity. + * @type string $maximum_font_size Maximum font size for any clamp() calculation. + * @type string $minimum_font_size Minimum font size for any clamp() calculation. + * @type int $scale_factor A scale factor to determine how fast a font scales within boundaries. * } * @return string|null A font-size value using clamp(). */ @@ -357,11 +357,13 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { $minimum_font_size_raw = isset( $args['minimum_font_size'] ) ? $args['minimum_font_size'] : null; $scale_factor = isset( $args['scale_factor'] ) ? $args['scale_factor'] : null; - // Grab the minimum font size and normalize it in order to use the value for calculations. + // Grabs the minimum font size and normalize it in order to use the value for calculations. $minimum_font_size = gutenberg_get_typography_value_and_unit( $minimum_font_size_raw ); - // We get a 'preferred' unit to keep units consistent when calculating, - // otherwise the result will not be accurate. + /* + * We get a 'preferred' unit to keep units consistent when calculating, + * otherwise the result will not be accurate. + */ $font_size_unit = isset( $minimum_font_size['unit'] ) ? $minimum_font_size['unit'] : 'rem'; // Grab the maximum font size and normalize it in order to use the value for calculations. @@ -372,12 +374,17 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { ) ); - // Protect against unsupported units. + // Checks for mandatory min and max sizes, and protects against unsupported units. if ( ! $maximum_font_size || ! $minimum_font_size ) { return null; } - // Use rem for accessible fluid target font scaling. + // Min font size should not be greater than max font size. + if ( $minimum_font_size['value'] > $maximum_font_size['value'] ) { + return null; + } + + // Uses rem for accessible fluid target font scaling. $minimum_font_size_rem = gutenberg_get_typography_value_and_unit( $minimum_font_size_raw, array( @@ -413,8 +420,8 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { * Returns a font-size value based on a given font-size preset. * Takes into account fluid typography parameters and attempts to return a css formula depending on available, valid values. * - * @param array $preset { - * Required. fontSizes preset value as seen in theme.json. + * @param array $font_size { + * Required. fontSizes represented in the preset format 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. @@ -422,10 +429,10 @@ 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|null Font-size value or `null` if a size is not passed in $preset. + * @return string|null Font-size value or `null` if a size is not passed in $font_size. */ -function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_typography = false ) { - if ( ! isset( $preset['size'] ) ) { +function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid_typography = false ) { + if ( ! isset( $font_size['size'] ) ) { return null; } @@ -433,8 +440,8 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty * Catches empty values and 0/'0'. * Fluid calculations cannot be performed on 0. */ - if ( empty( $preset['size'] ) ) { - return $preset['size']; + if ( empty( $font_size['size'] ) ) { + return $font_size['size']; } // Check if fluid font sizes are activated. @@ -442,7 +449,7 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty $should_use_fluid_typography = isset( $typography_settings['fluid'] ) && true === $typography_settings['fluid'] ? true : $should_use_fluid_typography; if ( ! $should_use_fluid_typography ) { - return $preset['size']; + return $font_size['size']; } // Defaults. @@ -451,43 +458,77 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty $default_minimum_font_size_factor = 0.75; $default_maximum_font_size_factor = 1.5; $default_scale_factor = 1; + $default_minimum_font_size_limit = '14px'; // Font sizes. - $fluid_font_size_settings = isset( $preset['fluid'] ) ? $preset['fluid'] : null; + $fluid_font_size_settings = isset( $font_size['fluid'] ) ? $font_size['fluid'] : null; // A font size has explicitly bypassed fluid calculations. if ( false === $fluid_font_size_settings ) { - return $preset['size']; + return $font_size['size']; } // Try to grab explicit min and max fluid font sizes. $minimum_font_size_raw = isset( $fluid_font_size_settings['min'] ) ? $fluid_font_size_settings['min'] : null; $maximum_font_size_raw = isset( $fluid_font_size_settings['max'] ) ? $fluid_font_size_settings['max'] : null; - // Font sizes. - $preferred_size = gutenberg_get_typography_value_and_unit( $preset['size'] ); + // Parses default font size. + $preferred_size = gutenberg_get_typography_value_and_unit( $font_size['size'] ); // Protect against unsupported units. if ( empty( $preferred_size['unit'] ) ) { - return $preset['size']; + return $font_size['size']; } - // If no fluid min or max font sizes are available, create some using min/max font size factors. + // If no fluid min font size is available, create one using min font size factor. if ( ! $minimum_font_size_raw ) { - $minimum_font_size_raw = ( $preferred_size['value'] * $default_minimum_font_size_factor ) . $preferred_size['unit']; + $minimum_font_size_raw = round( $preferred_size['value'] * $default_minimum_font_size_factor, 3 ) . $preferred_size['unit']; } + // Parses the minimum font size limit, so we can perform checks using it. + $minimum_font_size_limit = gutenberg_get_typography_value_and_unit( + $default_minimum_font_size_limit, + array( + 'coerce_to' => $preferred_size['unit'], + ) + ); + + /* + * Checks if a user-defined font size is lower than $minimum_font_size_limit. If so than it should become the minimum font size. + * Otherwise, if the minimum font size is lower than $minimum_font_size_limit + * use $minimum_font_size_limit instead. + */ + if ( ! empty( $minimum_font_size_limit ) ) { + // @TODO check if there was no min size value passed! + if ( $preferred_size['value'] < $minimum_font_size_limit['value'] ) { + $minimum_font_size_raw = implode( '', $preferred_size ); + } else { + $minimum_font_size_parsed = gutenberg_get_typography_value_and_unit( + $minimum_font_size_raw, + array( + 'coerce_to' => $preferred_size['unit'], + ) + ); + + if ( ! empty( $minimum_font_size_parsed ) && $minimum_font_size_parsed['value'] < $minimum_font_size_limit['value'] ) { + $minimum_font_size_raw = implode( '', $minimum_font_size_limit ); + } + } + } + + // If no fluid max font size is available, create one using max font size factor. if ( ! $maximum_font_size_raw ) { - $maximum_font_size_raw = ( $preferred_size['value'] * $default_maximum_font_size_factor ) . $preferred_size['unit']; + $maximum_font_size_raw = round( $preferred_size['value'] * $default_maximum_font_size_factor, 3 ) . $preferred_size['unit']; } $fluid_font_size_value = gutenberg_get_computed_fluid_typography_value( array( - 'minimum_viewport_width' => $default_minimum_viewport_width, - 'maximum_viewport_width' => $default_maximum_viewport_width, - 'minimum_font_size' => $minimum_font_size_raw, - 'maximum_font_size' => $maximum_font_size_raw, - 'scale_factor' => $default_scale_factor, + 'minimum_viewport_width' => $default_minimum_viewport_width, + 'maximum_viewport_width' => $default_maximum_viewport_width, + 'minimum_font_size' => $minimum_font_size_raw, + 'maximum_font_size' => $maximum_font_size_raw, + 'scale_factor' => $default_scale_factor, + 'minimum_font_size_limit' => $default_minimum_font_size_limit, ) ); @@ -495,7 +536,7 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty return $fluid_font_size_value; } - return $preset['size']; + return $font_size['size']; } // Register the block support. diff --git a/packages/block-editor/src/components/font-sizes/fluid-utils.js b/packages/block-editor/src/components/font-sizes/fluid-utils.js index 7294a83da106f8..4d7d5203da87a0 100644 --- a/packages/block-editor/src/components/font-sizes/fluid-utils.js +++ b/packages/block-editor/src/components/font-sizes/fluid-utils.js @@ -10,6 +10,7 @@ const DEFAULT_MINIMUM_VIEWPORT_WIDTH = '768px'; const DEFAULT_SCALE_FACTOR = 1; const DEFAULT_MINIMUM_FONT_SIZE_FACTOR = 0.75; const DEFAULT_MAXIMUM_FONT_SIZE_FACTOR = 1.5; +const DEFAULT_MINIMUM_FONT_SIZE_LIMIT = '14px'; /** * Computes a fluid font-size value that uses clamp(). A minimum and maxinmum @@ -53,11 +54,12 @@ export function getComputedFluidTypographyValue( { scaleFactor = DEFAULT_SCALE_FACTOR, minimumFontSizeFactor = DEFAULT_MINIMUM_FONT_SIZE_FACTOR, maximumFontSizeFactor = DEFAULT_MAXIMUM_FONT_SIZE_FACTOR, + minimumFontSizeLimit = DEFAULT_MINIMUM_FONT_SIZE_LIMIT, } ) { // Calculate missing minimumFontSize and maximumFontSize from // defaultFontSize if provided. - if ( fontSize && ( ! minimumFontSize || ! maximumFontSize ) ) { - // Parse default font size. + if ( fontSize ) { + // Parses default font size. const fontSizeParsed = getTypographyValueAndUnit( fontSize ); // Protect against invalid units. @@ -68,15 +70,54 @@ export function getComputedFluidTypographyValue( { // If no minimumFontSize is provided, derive using min scale factor. if ( ! minimumFontSize ) { minimumFontSize = - fontSizeParsed.value * minimumFontSizeFactor + - fontSizeParsed.unit; + roundToPrecision( + fontSizeParsed.value * minimumFontSizeFactor, + 3 + ) + fontSizeParsed.unit; + } + + // Parses the minimum font size limit, so we can perform checks using it. + const minimumFontSizeLimitParsed = getTypographyValueAndUnit( + minimumFontSizeLimit, + { + coerceTo: fontSizeParsed.unit, + } + ); + + /* + * Checks if a user-defined font size is lower than $minimum_font_size_limit. If so than it should become the minimum font size. + * Otherwise, if the minimum font size is lower than $minimum_font_size_limit + * use $minimum_font_size_limit instead. + */ + if ( !! minimumFontSizeLimitParsed?.value ) { + // @TODO check if there was no min size value passed! + if ( fontSizeParsed.value < minimumFontSizeLimitParsed.value ) { + minimumFontSize = `${ fontSizeParsed.value }${ fontSizeParsed.unit }`; + } else { + const minimumFontSizeParsed = getTypographyValueAndUnit( + minimumFontSize, + { + coerceTo: fontSizeParsed.unit, + } + ); + + if ( + !! minimumFontSizeParsed?.value && + minimumFontSizeParsed.value < + minimumFontSizeLimitParsed.value + ) { + minimumFontSize = `${ minimumFontSizeLimitParsed.value }${ minimumFontSizeLimitParsed.unit }`; + } + } } // If no maximumFontSize is provided, derive using max scale factor. if ( ! maximumFontSize ) { maximumFontSize = - fontSizeParsed.value * maximumFontSizeFactor + - fontSizeParsed.unit; + roundToPrecision( + fontSizeParsed.value * maximumFontSizeFactor, + 3 + ) + fontSizeParsed.unit; } } @@ -97,11 +138,16 @@ export function getComputedFluidTypographyValue( { coerceTo: fontSizeUnit, } ); - // Protect against unsupported units. + // Checks for mandatory min and max sizes, and protects against unsupported units. if ( ! minimumFontSizeParsed || ! maximumFontSizeParsed ) { return null; } + // Max font size should not be greater than min font size. + if ( minimumFontSizeParsed.value > maximumFontSizeParsed.value ) { + return null; + } + // Use rem for accessible fluid target font scaling. const minimumFontSizeRem = getTypographyValueAndUnit( minimumFontSize, { coerceTo: 'rem', @@ -133,14 +179,17 @@ export function getComputedFluidTypographyValue( { 3 ); - const viewPortWidthOffset = minViewPortWidthOffsetValue + fontSizeUnit; - let linearFactor = + const viewPortWidthOffset = + roundToPrecision( minViewPortWidthOffsetValue, 3 ) + fontSizeUnit; + const linearFactor = 100 * ( ( maximumFontSizeParsed.value - minimumFontSizeParsed.value ) / ( maximumViewPortWidthParsed.value - minumumViewPortWidthParsed.value ) ); - linearFactor = roundToPrecision( linearFactor, 3 ) || 1; - const linearFactorScaled = linearFactor * scaleFactor; + const linearFactorScaled = roundToPrecision( + linearFactor * scaleFactor, + 3 + ); const fluidTargetFontSize = `${ minimumFontSizeRem.value }${ minimumFontSizeRem.unit } + ((1vw - ${ viewPortWidthOffset }) * ${ linearFactorScaled })`; return `clamp(${ minimumFontSize }, ${ fluidTargetFontSize }, ${ maximumFontSize })`; @@ -200,7 +249,7 @@ export function getTypographyValueAndUnit( rawValue, options = {} ) { } return { - value: returnValue, + value: roundToPrecision( returnValue, 3 ), unit, }; } diff --git a/packages/block-editor/src/components/font-sizes/test/fluid-utils.js b/packages/block-editor/src/components/font-sizes/test/fluid-utils.js index cd45c3593e1a48..aa268d04d7f1f2 100644 --- a/packages/block-editor/src/components/font-sizes/test/fluid-utils.js +++ b/packages/block-editor/src/components/font-sizes/test/fluid-utils.js @@ -33,7 +33,7 @@ describe( 'getComputedFluidTypographyValue()', () => { fontSize: '30px', } ); expect( fluidTypographyValues ).toBe( - 'clamp(22.5px, 1.40625rem + ((1vw - 7.68px) * 2.704), 45px)' + 'clamp(22.5px, 1.406rem + ((1vw - 7.68px) * 2.704), 45px)' ); } ); @@ -42,7 +42,7 @@ describe( 'getComputedFluidTypographyValue()', () => { fontSize: '30px', } ); expect( fluidTypographyValues ).toBe( - 'clamp(22.5px, 1.40625rem + ((1vw - 7.68px) * 2.704), 45px)' + 'clamp(22.5px, 1.406rem + ((1vw - 7.68px) * 2.704), 45px)' ); } ); @@ -53,7 +53,7 @@ describe( 'getComputedFluidTypographyValue()', () => { maximumViewPortWidth: '1000px', } ); expect( fluidTypographyValues ).toBe( - 'clamp(22.5px, 1.40625rem + ((1vw - 5px) * 4.5), 45px)' + 'clamp(22.5px, 1.406rem + ((1vw - 5px) * 4.5), 45px)' ); } ); @@ -63,7 +63,7 @@ describe( 'getComputedFluidTypographyValue()', () => { scaleFactor: '2', } ); expect( fluidTypographyValues ).toBe( - 'clamp(22.5px, 1.40625rem + ((1vw - 7.68px) * 5.408), 45px)' + 'clamp(22.5px, 1.406rem + ((1vw - 7.68px) * 5.409), 45px)' ); } ); @@ -74,7 +74,7 @@ describe( 'getComputedFluidTypographyValue()', () => { maximumFontSizeFactor: '2', } ); expect( fluidTypographyValues ).toBe( - 'clamp(15px, 0.9375rem + ((1vw - 7.68px) * 5.409), 60px)' + 'clamp(15px, 0.938rem + ((1vw - 7.68px) * 5.409), 60px)' ); } ); diff --git a/packages/edit-site/src/components/global-styles/test/typography-utils.js b/packages/edit-site/src/components/global-styles/test/typography-utils.js index 97ebeb583e497f..e32c0e3d36fbc7 100644 --- a/packages/edit-site/src/components/global-styles/test/typography-utils.js +++ b/packages/edit-site/src/components/global-styles/test/typography-utils.js @@ -5,206 +5,309 @@ import { getTypographyFontSizeValue } from '../typography-utils'; describe( 'typography utils', () => { describe( 'getTypographyFontSizeValue', () => { - it( 'should return the expected values', () => { - [ - // Default return non-fluid value. - { - preset: { - size: '28px', - }, - typographySettings: undefined, - expected: '28px', + [ + { + message: 'Default return non-fluid value.', + preset: { + size: '28px', }, - // Default return value where font size is 0. - { - preset: { - size: 0, - }, - typographySettings: undefined, - expected: 0, + typographySettings: undefined, + expected: '28px', + }, + + { + message: 'Default return value where font size is 0.', + preset: { + size: 0, }, - // Default return value where font size is '0'. - { - preset: { - size: '0', - }, - typographySettings: undefined, - expected: '0', + typographySettings: undefined, + expected: 0, + }, + + { + message: "Default return value where font size is '0'.", + preset: { + size: '0', }, + typographySettings: undefined, + expected: '0', + }, - // Default return non-fluid value where `size` is undefined. - { - preset: { - size: undefined, - }, - typographySettings: undefined, - expected: undefined, - }, - // Should return non-fluid value when fluid is `false`. - { - preset: { - size: '28px', - fluid: false, - }, - typographySettings: { - fluid: true, - }, - expected: '28px', + { + message: + 'Default return non-fluid value where `size` is undefined.', + preset: { + size: undefined, }, - // Should coerce integer to `px` and return fluid value. - { - preset: { - size: 33, - fluid: true, - }, - typographySettings: { - fluid: true, - }, - expected: - 'clamp(24.75px, 1.546875rem + ((1vw - 7.68px) * 2.975), 49.5px)', + typographySettings: undefined, + expected: undefined, + }, + + { + message: 'return non-fluid value when fluid is `false`.', + preset: { + size: '28px', + fluid: false, + }, + typographySettings: { + fluid: true, }, + expected: '28px', + }, - // Should coerce float to `px` and return fluid value. - { - preset: { - size: 100.23, - fluid: true, - }, - typographySettings: { - fluid: true, - }, - expected: - 'clamp(75.1725px, 4.69828125rem + ((1vw - 7.68px) * 9.035), 150.345px)', - }, - // Should return incoming value when already clamped. - { - preset: { - size: 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)', - fluid: false, - }, - typographySettings: { - fluid: true, - }, - expected: - 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)', - }, - // Should return incoming value with unsupported unit. - { - preset: { - size: '1000%', - fluid: false, - }, - typographySettings: { - fluid: true, - }, - expected: '1000%', + { + message: + 'Should coerce integer to `px` and return fluid value.', + preset: { + size: 33, + fluid: true, }, - // Should return fluid value. - { - preset: { - size: '1.75rem', - }, - typographySettings: { - fluid: true, - }, - expected: - 'clamp(1.3125rem, 1.3125rem + ((1vw - 0.48rem) * 2.524), 2.625rem)', + typographySettings: { + fluid: true, }, - // Should return fluid value for floats with units. - { - preset: { - size: '100.175px', - }, - typographySettings: { - fluid: true, - }, - expected: - 'clamp(75.13125px, 4.695703125rem + ((1vw - 7.68px) * 9.03), 150.2625px)', - }, - // Should return default fluid values with empty fluid array. - { - preset: { - size: '28px', - fluid: [], - }, - typographySettings: { - fluid: true, - }, - expected: - 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)', + expected: + 'clamp(24.75px, 1.547rem + ((1vw - 7.68px) * 2.975), 49.5px)', + }, + + { + message: 'coerce float to `px` and return fluid value.', + preset: { + size: 100.23, + fluid: true, + }, + typographySettings: { + fluid: true, }, + expected: + 'clamp(75.172px, 4.698rem + ((1vw - 7.68px) * 9.035), 150.345px)', + }, - // Should return default fluid values with null values. - { - preset: { - size: '28px', - fluid: null, - }, - typographySettings: { - fluid: true, - }, - expected: - 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)', - }, - - // Should return size with invalid fluid units. - { - preset: { - size: '10em', - fluid: { - min: '20vw', - max: '50%', - }, + { + message: 'return incoming value when already clamped.', + preset: { + size: 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', + fluid: false, + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', + }, + + { + message: 'return incoming value with unsupported unit.', + preset: { + size: '1000%', + fluid: false, + }, + typographySettings: { + fluid: true, + }, + expected: '1000%', + }, + + { + message: 'return fluid value.', + preset: { + size: '1.75rem', + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(1.313rem, 1.313rem + ((1vw - 0.48rem) * 2.523), 2.625rem)', + }, + + { + message: 'return fluid value for floats with units.', + preset: { + size: '100.175px', + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(75.131px, 4.696rem + ((1vw - 7.68px) * 9.03), 150.262px)', + }, + + { + message: + 'Should return default fluid values with empty fluid array.', + preset: { + size: '28px', + fluid: [], + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', + }, + + { + message: 'return default fluid values with null value.', + preset: { + size: '28px', + fluid: null, + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', + }, + + { + message: + 'Should return default value if min font size is greater than max.', + preset: { + size: '3rem', + fluid: { + min: '5rem', + max: '32px', }, - typographySettings: { - fluid: true, + }, + typographySettings: { + fluid: true, + }, + expected: '3rem', + }, + + { + message: 'return size with invalid fluid units.', + preset: { + size: '10em', + fluid: { + min: '20vw', + max: '50%', }, - expected: '10em', - }, - // Should return fluid clamp value. - { - preset: { - size: '28px', - fluid: { - min: '20px', - max: '50rem', - }, + }, + typographySettings: { + fluid: true, + }, + expected: '10em', + }, + + { + message: 'return fluid clamp value.', + preset: { + size: '28px', + fluid: { + min: '20px', + max: '50rem', }, - typographySettings: { - fluid: true, + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(20px, 1.25rem + ((1vw - 7.68px) * 93.75), 50rem)', + }, + // + { + message: + ' Should return clamp value with default fluid max value.', + preset: { + size: '28px', + fluid: { + min: '2.6rem', }, - expected: - 'clamp(20px, 1.25rem + ((1vw - 7.68px) * 93.75), 50rem)', - }, - // Should return clamp value with default fluid max value. - { - preset: { - size: '28px', - fluid: { - min: '2.6rem', - }, + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(2.6rem, 2.6rem + ((1vw - 0.48rem) * 0.048), 42px)', + }, + + { + message: + 'Should return clamp value with default fluid min value.', + preset: { + size: '28px', + fluid: { + max: '80px', }, - typographySettings: { - fluid: true, + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 7.091), 80px)', + }, + + { + message: 'adjust computed min in px to min limit.', + preset: { + size: '14px', + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(14px, 0.875rem + ((1vw - 7.68px) * 0.841), 21px)', + }, + + { + message: 'adjust computed min in rem to min limit.', + preset: { + size: '1.1rem', + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 1.49), 1.65rem)', + }, + + { + message: 'adjust fluid min value in px to min limit', + preset: { + size: '20px', + fluid: { + min: '12px', }, - expected: - 'clamp(2.6rem, 2.6rem + ((1vw - 0.48rem) * 0.048), 42px)', - }, - // Should return clamp value with default fluid min value. - { - preset: { - size: '28px', - fluid: { - max: '80px', - }, + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(14px, 0.875rem + ((1vw - 7.68px) * 1.923), 30px)', + }, + + { + message: 'adjust fluid min value in rem to min limit.', + preset: { + size: '1.5rem', + fluid: { + min: '0.5rem', }, - typographySettings: { - fluid: true, + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 2.644), 2.25rem)', + }, + + { + message: 'adjust fluid min value but honor max value.', + preset: { + size: '1.5rem', + fluid: { + min: '0.5rem', + max: '5rem', }, - expected: - 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 7.091), 80px)', }, - ].forEach( ( { preset, typographySettings, expected } ) => { + typographySettings: { + fluid: true, + }, + expected: + 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 7.933), 5rem)', + }, + ].forEach( ( { message, preset, typographySettings, expected } ) => { + it( `should ${ message }`, () => { expect( getTypographyFontSizeValue( preset, typographySettings ) ).toBe( expected ); diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php index 606904de72bf0b..ae286ddaac9154 100644 --- a/phpunit/block-supports/typography-test.php +++ b/phpunit/block-supports/typography-test.php @@ -292,8 +292,8 @@ public function test_should_generate_classname_for_font_family() { * * @dataProvider data_generate_font_size_preset_fixtures * - * @param array $font_size_preset { - * Required. fontSizes preset value as seen in theme.json. + * @param array $font_size { + * Required. fontSizes represented in the preset format 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. @@ -302,8 +302,8 @@ public function test_should_generate_classname_for_font_family() { * @param bool $should_use_fluid_typography An override to switch fluid typography "on". Can be used for unit testing. * @param string $expected_output Expected output of gutenberg_get_typography_font_size_value(). */ - public function test_gutenberg_get_typography_font_size_value( $font_size_preset, $should_use_fluid_typography, $expected_output ) { - $actual = gutenberg_get_typography_font_size_value( $font_size_preset, $should_use_fluid_typography ); + public function test_gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid_typography, $expected_output ) { + $actual = gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid_typography ); $this->assertSame( $expected_output, $actual ); } @@ -316,7 +316,7 @@ public function test_gutenberg_get_typography_font_size_value( $font_size_preset public function data_generate_font_size_preset_fixtures() { return array( 'default_return_value' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '28px', ), 'should_use_fluid_typography' => false, @@ -324,7 +324,7 @@ public function data_generate_font_size_preset_fixtures() { ), 'size: int 0' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => 0, ), 'should_use_fluid_typography' => true, @@ -332,7 +332,7 @@ public function data_generate_font_size_preset_fixtures() { ), 'size: string 0' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '0', ), 'should_use_fluid_typography' => true, @@ -340,7 +340,7 @@ public function data_generate_font_size_preset_fixtures() { ), 'default_return_value_when_size_is_undefined' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => null, ), 'should_use_fluid_typography' => false, @@ -348,7 +348,7 @@ public function data_generate_font_size_preset_fixtures() { ), 'default_return_value_when_fluid_is_false' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '28px', 'fluid' => false, ), @@ -357,16 +357,16 @@ public function data_generate_font_size_preset_fixtures() { ), 'default_return_value_when_value_is_already_clamped' => array( - 'font_size_preset' => array( - 'size' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)', + 'font_size' => array( + 'size' => 'clamp(21px, 1.313rem + ((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)', + 'expected_output' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', ), 'default_return_value_with_unsupported_unit' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '1000%', 'fluid' => false, ), @@ -375,15 +375,15 @@ public function data_generate_font_size_preset_fixtures() { ), 'return_fluid_value' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '1.75rem', ), 'should_use_fluid_typography' => true, - 'expected_output' => 'clamp(1.3125rem, 1.3125rem + ((1vw - 0.48rem) * 2.524), 2.625rem)', + 'expected_output' => 'clamp(1.313rem, 1.313rem + ((1vw - 0.48rem) * 2.524), 2.625rem)', ), 'return_fluid_value_with_floats_with_units' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '100.175px', ), 'should_use_fluid_typography' => true, @@ -391,41 +391,53 @@ public function data_generate_font_size_preset_fixtures() { ), 'return_fluid_value_with_integer_coerced_to_px' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => 33, ), 'should_use_fluid_typography' => true, - 'expected_output' => 'clamp(24.75px, 1.546875rem + ((1vw - 7.68px) * 2.975), 49.5px)', + 'expected_output' => 'clamp(24.75px, 1.547rem + ((1vw - 7.68px) * 2.975), 49.5px)', ), 'return_fluid_value_with_float_coerced_to_px' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => 100.23, ), 'should_use_fluid_typography' => true, - 'expected_output' => 'clamp(75.1725px, 4.69828125rem + ((1vw - 7.68px) * 9.035), 150.345px)', + 'expected_output' => 'clamp(75.1725px, 4.698rem + ((1vw - 7.68px) * 9.035), 150.345px)', ), 'return_default_fluid_values_with_empty_fluid_array' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '28px', 'fluid' => array(), ), 'should_use_fluid_typography' => true, - 'expected_output' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)', + 'expected_output' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', ), 'return_default_fluid_values_with_null_value' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '28px', 'fluid' => null, ), 'should_use_fluid_typography' => true, - 'expected_output' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)', + 'expected_output' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', + ), + + 'return_default_value_if_min_font_size_is_greater_than_max' => array( + 'font_size' => array( + 'size' => '3rem', + 'fluid' => array( + 'min' => '5rem', + 'max' => '32px', + ), + ), + 'should_use_fluid_typography' => true, + 'expected_output' => '3rem', ), 'return_size_with_invalid_fluid_units' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '10em', 'fluid' => array( 'min' => '20vw', @@ -437,7 +449,7 @@ public function data_generate_font_size_preset_fixtures() { ), 'return_fluid_clamp_value' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '28px', 'fluid' => array( 'min' => '20px', @@ -449,7 +461,7 @@ public function data_generate_font_size_preset_fixtures() { ), 'return_clamp_value_with_default_fluid_max_value' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '28px', 'fluid' => array( 'min' => '2.6rem', @@ -460,14 +472,72 @@ public function data_generate_font_size_preset_fixtures() { ), 'default_return_clamp_value_with_default_fluid_min_value' => array( - 'font_size_preset' => array( + 'font_size' => array( 'size' => '28px', 'fluid' => array( 'max' => '80px', ), ), 'should_use_fluid_typography' => true, - 'expected_output' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 7.091), 80px)', + 'expected_output' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 7.091), 80px)', + ), + + 'should_adjust_computed_min_in_px_to_min_limit' => array( + 'font_size' => array( + 'size' => '14px', + ), + 'should_use_fluid_typography' => true, + 'expected_output' => 'clamp(14px, 0.875rem + ((1vw - 7.68px) * 0.841), 21px)', + ), + + 'should_adjust_computed_min_in_rem_to_min_limit' => array( + 'font_size' => array( + 'size' => '1.1rem', + ), + 'should_use_fluid_typography' => true, + 'expected_output' => 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 1.49), 1.65rem)', + ), +// @TODO check that $fluid_target_font_size should use `rem` when `em` font size value is passed. +// 'default_return_clamp_value_with_replaced_fluid_min_value_in_em' => array( +// 'font_size' => array( +// 'size' => '1.1em', +// ), +// 'should_use_fluid_typography' => true, +// 'expected_output' => 'clamp(0.875em, 0.875em + ((1vw - 0.48em) * 1.49), 1.65em)', +// ), + + 'should_adjust_fluid_min_value_in_px_to_min_limit' => array( + 'font_size' => array( + 'size' => '20px', + 'fluid' => array( + 'min' => '12px', + ), + ), + 'should_use_fluid_typography' => true, + 'expected_output' => 'clamp(14px, 0.875rem + ((1vw - 7.68px) * 1.923), 30px)', + ), + + 'should_adjust_fluid_min_value_in_rem_to_min_limit' => array( + 'font_size' => array( + 'size' => '1.5rem', + 'fluid' => array( + 'min' => '0.5rem', + ), + ), + 'should_use_fluid_typography' => true, + 'expected_output' => 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 2.644), 2.25rem)', + ), + + 'should_adjust_fluid_min_value_but_honor_max_value' => array( + 'font_size' => array( + 'size' => '1.5rem', + 'fluid' => array( + 'min' => '0.5rem', + 'max' => '5rem', + ), + ), + 'should_use_fluid_typography' => true, + 'expected_output' => 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 7.933), 5rem)', ), ); } @@ -619,10 +689,10 @@ public function data_generate_replace_inline_font_styles_with_fluid_values_fixtu 'expected_output' => '

A paragraph inside a group

', ), 'return_content_with_first_match_replace_only' => array( - 'block_content' => "
\n \n

A paragraph inside a group

", - 'font_size_value' => '1em', + 'block_content' => "
\n \n

A paragraph inside a group

", + 'font_size_value' => '1.5em', 'should_use_fluid_typography' => true, - 'expected_output' => "
\n \n

A paragraph inside a group

", + 'expected_output' => "
\n \n

A paragraph inside a group

", ), ); } From 70279252eb82ca80933a0380cd0aefbe9ad7caa9 Mon Sep 17 00:00:00 2001 From: ramonjd Date: Sun, 16 Oct 2022 12:14:27 +1100 Subject: [PATCH 02/12] Rounding parsed min and max values --- lib/block-supports/typography.php | 2 +- .../components/global-styles/test/typography-utils.js | 1 + phpunit/block-supports/typography-test.php | 10 +++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index ddc7500889e32d..d3a77103a9e219 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -329,7 +329,7 @@ function gutenberg_get_typography_value_and_unit( $raw_value, $options = array() } return array( - 'value' => $value, + 'value' => round( $value, 3 ), 'unit' => $unit, ); } diff --git a/packages/edit-site/src/components/global-styles/test/typography-utils.js b/packages/edit-site/src/components/global-styles/test/typography-utils.js index e32c0e3d36fbc7..ee26151a1819ca 100644 --- a/packages/edit-site/src/components/global-styles/test/typography-utils.js +++ b/packages/edit-site/src/components/global-styles/test/typography-utils.js @@ -128,6 +128,7 @@ describe( 'typography utils', () => { fluid: true, }, expected: + // @TODO this is not the same as the PHP output: 150.263px 'clamp(75.131px, 4.696rem + ((1vw - 7.68px) * 9.03), 150.262px)', }, diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php index ae286ddaac9154..e5ca3bfa94e349 100644 --- a/phpunit/block-supports/typography-test.php +++ b/phpunit/block-supports/typography-test.php @@ -379,7 +379,7 @@ public function data_generate_font_size_preset_fixtures() { 'size' => '1.75rem', ), 'should_use_fluid_typography' => true, - 'expected_output' => 'clamp(1.313rem, 1.313rem + ((1vw - 0.48rem) * 2.524), 2.625rem)', + 'expected_output' => 'clamp(1.313rem, 1.313rem + ((1vw - 0.48rem) * 2.523), 2.625rem)', ), 'return_fluid_value_with_floats_with_units' => array( @@ -387,7 +387,7 @@ public function data_generate_font_size_preset_fixtures() { 'size' => '100.175px', ), 'should_use_fluid_typography' => true, - 'expected_output' => 'clamp(75.13125px, 4.695703125rem + ((1vw - 7.68px) * 9.03), 150.2625px)', + 'expected_output' => 'clamp(75.131px, 4.696rem + ((1vw - 7.68px) * 9.03), 150.263px)', ), 'return_fluid_value_with_integer_coerced_to_px' => array( @@ -403,7 +403,7 @@ public function data_generate_font_size_preset_fixtures() { 'size' => 100.23, ), 'should_use_fluid_typography' => true, - 'expected_output' => 'clamp(75.1725px, 4.698rem + ((1vw - 7.68px) * 9.035), 150.345px)', + 'expected_output' => 'clamp(75.173px, 4.698rem + ((1vw - 7.68px) * 9.035), 150.345px)', ), 'return_default_fluid_values_with_empty_fluid_array' => array( @@ -610,7 +610,7 @@ public function data_generate_block_supports_font_size_fixtures() { '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);', + 'expected_output' => 'font-size:clamp(37.5px, 2.344rem + ((1vw - 7.68px) * 4.507), 75px);', ), ); } @@ -686,7 +686,7 @@ public function data_generate_replace_inline_font_styles_with_fluid_values_fixtu 'block_content' => '

A paragraph inside a group

', 'font_size_value' => '20px', 'should_use_fluid_typography' => true, - 'expected_output' => '

A paragraph inside a group

', + 'expected_output' => '

A paragraph inside a group

', ), 'return_content_with_first_match_replace_only' => array( 'block_content' => "
\n \n

A paragraph inside a group

", From 7e29b5fada227254d59a039cebfabdb4c887aa2f Mon Sep 17 00:00:00 2001 From: ramonjd Date: Sun, 16 Oct 2022 12:30:34 +1100 Subject: [PATCH 03/12] Updating JS rounding function so that values are rounded --- .../block-editor/src/components/font-sizes/fluid-utils.js | 3 ++- .../src/components/global-styles/test/typography-utils.js | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/font-sizes/fluid-utils.js b/packages/block-editor/src/components/font-sizes/fluid-utils.js index 4d7d5203da87a0..5b8afe81f88896 100644 --- a/packages/block-editor/src/components/font-sizes/fluid-utils.js +++ b/packages/block-editor/src/components/font-sizes/fluid-utils.js @@ -264,7 +264,8 @@ export function getTypographyValueAndUnit( rawValue, options = {} ) { * @return {number|undefined} Value rounded to standard precision. */ export function roundToPrecision( value, digits = 3 ) { + const base = Math.pow( 10, Number( digits ) + 1 ); return Number.isFinite( value ) - ? parseFloat( value.toFixed( digits ) ) + ? parseFloat( ( Number( value ) + 1 / base ).toFixed( digits ) ) : undefined; } diff --git a/packages/edit-site/src/components/global-styles/test/typography-utils.js b/packages/edit-site/src/components/global-styles/test/typography-utils.js index ee26151a1819ca..b05dbc284dc343 100644 --- a/packages/edit-site/src/components/global-styles/test/typography-utils.js +++ b/packages/edit-site/src/components/global-styles/test/typography-utils.js @@ -79,7 +79,7 @@ describe( 'typography utils', () => { fluid: true, }, expected: - 'clamp(75.172px, 4.698rem + ((1vw - 7.68px) * 9.035), 150.345px)', + 'clamp(75.173px, 4.698rem + ((1vw - 7.68px) * 9.035), 150.345px)', }, { @@ -128,8 +128,7 @@ describe( 'typography utils', () => { fluid: true, }, expected: - // @TODO this is not the same as the PHP output: 150.263px - 'clamp(75.131px, 4.696rem + ((1vw - 7.68px) * 9.03), 150.262px)', + 'clamp(75.131px, 4.696rem + ((1vw - 7.68px) * 9.03), 150.263px)', }, { From 08b890334b182aea010d6b18ac66059fd0864b66 Mon Sep 17 00:00:00 2001 From: ramonjd Date: Sun, 16 Oct 2022 12:36:06 +1100 Subject: [PATCH 04/12] Removing type coercion --- .../block-editor/src/components/font-sizes/fluid-utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/font-sizes/fluid-utils.js b/packages/block-editor/src/components/font-sizes/fluid-utils.js index 5b8afe81f88896..b8d0fd69d7d23c 100644 --- a/packages/block-editor/src/components/font-sizes/fluid-utils.js +++ b/packages/block-editor/src/components/font-sizes/fluid-utils.js @@ -264,8 +264,8 @@ export function getTypographyValueAndUnit( rawValue, options = {} ) { * @return {number|undefined} Value rounded to standard precision. */ export function roundToPrecision( value, digits = 3 ) { - const base = Math.pow( 10, Number( digits ) + 1 ); + const base = Math.pow( 10, digits + 1 ); return Number.isFinite( value ) - ? parseFloat( ( Number( value ) + 1 / base ).toFixed( digits ) ) + ? parseFloat( ( value + 1 / base ).toFixed( digits ) ) : undefined; } From 087f78aef8053226caea6ad9c862217317e0db7d Mon Sep 17 00:00:00 2001 From: ramonjd Date: Sun, 16 Oct 2022 12:37:49 +1100 Subject: [PATCH 05/12] Updating failing test --- .../components/global-styles/test/use-global-styles-output.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/test/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/test/use-global-styles-output.js index 48f21603ad78e8..a6bd55ff86ec8f 100644 --- a/packages/edit-site/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/edit-site/src/components/global-styles/test/use-global-styles-output.js @@ -782,7 +782,7 @@ describe( 'global styles renderer', () => { 'padding-bottom: 33px', 'padding-left: 33px', 'font-family: sans-serif', - 'font-size: clamp(10.5px, 0.65625rem + ((1vw - 7.68px) * 1.262), 21px)', + 'font-size: clamp(14px, 0.875rem + ((1vw - 7.68px) * 0.841), 21px)', ] ); } ); From c8d80b45235badf2b9d25e74cbc08b119c6c6de1 Mon Sep 17 00:00:00 2001 From: ramonjd Date: Sun, 16 Oct 2022 12:40:28 +1100 Subject: [PATCH 06/12] Remove reference to preset in favour of "fontSize" --- .../global-styles/typography-utils.js | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/typography-utils.js b/packages/edit-site/src/components/global-styles/typography-utils.js index 6e26a3155ed543..af71a96210ed9a 100644 --- a/packages/edit-site/src/components/global-styles/typography-utils.js +++ b/packages/edit-site/src/components/global-styles/typography-utils.js @@ -10,31 +10,32 @@ import { getComputedFluidTypographyValue } from '@wordpress/block-editor'; /** - * @typedef {Object} FluidPreset + * @typedef {Object} FluidValues * @property {string|undefined} max A maximum font size value. * @property {?string|undefined} min A minimum font size value. */ /** - * @typedef {Object} Preset + * @typedef {Object} FontSize * @property {?string|?number} size A default font size. * @property {string} name A font size name, displayed in the UI. * @property {string} slug A font size slug - * @property {boolean|FluidPreset|undefined} fluid A font size slug + * @property {boolean|FluidValues|undefined} fluid A font size slug */ /** - * Returns a font-size value based on a given font-size preset. + * Returns a font-size value based on a given fontSize. + * The fontSize is represented in the preset format as seen in theme.json. * Takes into account fluid typography parameters and attempts to return a css formula depending on available, valid values. * - * @param {Preset} preset - * @param {Object} typographySettings - * @param {boolean} typographySettings.fluid Whether fluid typography is enabled. + * @param {FontSize} fontSize + * @param {Object} typographySettings + * @param {boolean} typographySettings.fluid Whether fluid typography is enabled. * - * @return {string|*} A font-size value or the value of preset.size. + * @return {string|*} A font-size value or the value of fontSize.size. */ -export function getTypographyFontSizeValue( preset, typographySettings ) { - const { size: defaultSize } = preset; +export function getTypographyFontSizeValue( fontSize, typographySettings ) { + const { size: defaultSize } = fontSize; /* * Catches falsy values and 0/'0'. @@ -49,13 +50,13 @@ export function getTypographyFontSizeValue( preset, typographySettings ) { } // A font size has explicitly bypassed fluid calculations. - if ( false === preset?.fluid ) { + if ( false === fontSize?.fluid ) { return defaultSize; } const fluidFontSizeValue = getComputedFluidTypographyValue( { - minimumFontSize: preset?.fluid?.min, - maximumFontSize: preset?.fluid?.max, + minimumFontSize: fontSize?.fluid?.min, + maximumFontSize: fontSize?.fluid?.max, fontSize: defaultSize, } ); From f45b4a5d94cfe5a8692fa86b138ba3d420e17f2a Mon Sep 17 00:00:00 2001 From: ramonjd Date: Mon, 17 Oct 2022 11:12:34 +1100 Subject: [PATCH 07/12] Ensure that rem units are used when calculating min and max boundaries in em This is to keep it consistent with the original formula and ensure the fluid argument in clamp is working off a size relative to :root Fixing formatting and grammar Rolling back renaming $preset to $font_size in preference to a follow up. Do not clamp value if there is no min size and the font size is less than 14px --- lib/block-supports/typography.php | 69 ++++++++------- .../src/components/font-sizes/fluid-utils.js | 86 ++++++++++++------- .../global-styles/test/typography-utils.js | 27 +++++- .../global-styles/typography-utils.js | 27 +++--- phpunit/block-supports/typography-test.php | 30 ++++--- 5 files changed, 152 insertions(+), 87 deletions(-) diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index d3a77103a9e219..9a226241ea9ec5 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -328,6 +328,15 @@ function gutenberg_get_typography_value_and_unit( $raw_value, $options = array() $unit = $options['coerce_to']; } + /* + * No calculation is required if swapping between em and rem yet, + * since we assume a root size value. Later we might like to differentiate between + * :root font size (rem) and parent element font size (em) relativity. + */ + if ( ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) && ( 'em' === $unit || 'rem' === $unit ) ) { + $unit = $options['coerce_to']; + } + return array( 'value' => round( $value, 3 ), 'unit' => $unit, @@ -342,11 +351,11 @@ function gutenberg_get_typography_value_and_unit( $raw_value, $options = array() * @param array $args { * Optional. An associative array of values to calculate a fluid formula for font size. Default is empty array. * - * @type string $maximum_viewport_width Maximum size up to which type will have fluidity. - * @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity. - * @type string $maximum_font_size Maximum font size for any clamp() calculation. - * @type string $minimum_font_size Minimum font size for any clamp() calculation. - * @type int $scale_factor A scale factor to determine how fast a font scales within boundaries. + * @type string $maximum_viewport_width Maximum size up to which type will have fluidity. + * @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity. + * @type string $maximum_font_size Maximum font size for any clamp() calculation. + * @type string $minimum_font_size Minimum font size for any clamp() calculation. + * @type int $scale_factor A scale factor to determine how fast a font scales within boundaries. * } * @return string|null A font-size value using clamp(). */ @@ -357,7 +366,7 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { $minimum_font_size_raw = isset( $args['minimum_font_size'] ) ? $args['minimum_font_size'] : null; $scale_factor = isset( $args['scale_factor'] ) ? $args['scale_factor'] : null; - // Grabs the minimum font size and normalize it in order to use the value for calculations. + // Normalizes the minimum font size in order to use the value for calculations. $minimum_font_size = gutenberg_get_typography_value_and_unit( $minimum_font_size_raw ); /* @@ -420,8 +429,8 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { * Returns a font-size value based on a given font-size preset. * Takes into account fluid typography parameters and attempts to return a css formula depending on available, valid values. * - * @param array $font_size { - * Required. fontSizes represented in the preset format as seen in theme.json. + * @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. @@ -429,10 +438,10 @@ 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|null Font-size value or `null` if a size is not passed in $font_size. + * @return string|null Font-size value or `null` if a size is not passed in $preset. */ -function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid_typography = false ) { - if ( ! isset( $font_size['size'] ) ) { +function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_typography = false ) { + if ( ! isset( $preset['size'] ) ) { return null; } @@ -440,8 +449,8 @@ function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid * Catches empty values and 0/'0'. * Fluid calculations cannot be performed on 0. */ - if ( empty( $font_size['size'] ) ) { - return $font_size['size']; + if ( empty( $preset['size'] ) ) { + return $preset['size']; } // Check if fluid font sizes are activated. @@ -449,7 +458,7 @@ function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid $should_use_fluid_typography = isset( $typography_settings['fluid'] ) && true === $typography_settings['fluid'] ? true : $should_use_fluid_typography; if ( ! $should_use_fluid_typography ) { - return $font_size['size']; + return $preset['size']; } // Defaults. @@ -461,23 +470,23 @@ function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid $default_minimum_font_size_limit = '14px'; // Font sizes. - $fluid_font_size_settings = isset( $font_size['fluid'] ) ? $font_size['fluid'] : null; + $fluid_font_size_settings = isset( $preset['fluid'] ) ? $preset['fluid'] : null; // A font size has explicitly bypassed fluid calculations. if ( false === $fluid_font_size_settings ) { - return $font_size['size']; + return $preset['size']; } // Try to grab explicit min and max fluid font sizes. $minimum_font_size_raw = isset( $fluid_font_size_settings['min'] ) ? $fluid_font_size_settings['min'] : null; $maximum_font_size_raw = isset( $fluid_font_size_settings['max'] ) ? $fluid_font_size_settings['max'] : null; - // Parses default font size. - $preferred_size = gutenberg_get_typography_value_and_unit( $font_size['size'] ); + // Font sizes. + $preferred_size = gutenberg_get_typography_value_and_unit( $preset['size'] ); // Protect against unsupported units. if ( empty( $preferred_size['unit'] ) ) { - return $font_size['size']; + return $preset['size']; } // If no fluid min font size is available, create one using min font size factor. @@ -493,15 +502,14 @@ function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid ) ); - /* - * Checks if a user-defined font size is lower than $minimum_font_size_limit. If so than it should become the minimum font size. - * Otherwise, if the minimum font size is lower than $minimum_font_size_limit - * use $minimum_font_size_limit instead. - */ if ( ! empty( $minimum_font_size_limit ) ) { - // @TODO check if there was no min size value passed! - if ( $preferred_size['value'] < $minimum_font_size_limit['value'] ) { - $minimum_font_size_raw = implode( '', $preferred_size ); + /* + * If a minimum size was not passed to this function + * and the user-defined font size is lower than $minimum_font_size_limit, + * then do not fluidify. + */ + if ( ! isset( $fluid_font_size_settings['min'] ) && $preferred_size['value'] < $minimum_font_size_limit['value'] ) { + return $preset['size']; } else { $minimum_font_size_parsed = gutenberg_get_typography_value_and_unit( $minimum_font_size_raw, @@ -510,6 +518,10 @@ function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid ) ); + /* + * Otherwise, if the passed or calculated minimum font size is lower than $minimum_font_size_limit + * use $minimum_font_size_limit instead. + */ if ( ! empty( $minimum_font_size_parsed ) && $minimum_font_size_parsed['value'] < $minimum_font_size_limit['value'] ) { $minimum_font_size_raw = implode( '', $minimum_font_size_limit ); } @@ -528,7 +540,6 @@ function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid 'minimum_font_size' => $minimum_font_size_raw, 'maximum_font_size' => $maximum_font_size_raw, 'scale_factor' => $default_scale_factor, - 'minimum_font_size_limit' => $default_minimum_font_size_limit, ) ); @@ -536,7 +547,7 @@ function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid return $fluid_font_size_value; } - return $font_size['size']; + return $preset['size']; } // Register the block support. diff --git a/packages/block-editor/src/components/font-sizes/fluid-utils.js b/packages/block-editor/src/components/font-sizes/fluid-utils.js index b8d0fd69d7d23c..da48b2586774c6 100644 --- a/packages/block-editor/src/components/font-sizes/fluid-utils.js +++ b/packages/block-editor/src/components/font-sizes/fluid-utils.js @@ -56,8 +56,16 @@ export function getComputedFluidTypographyValue( { maximumFontSizeFactor = DEFAULT_MAXIMUM_FONT_SIZE_FACTOR, minimumFontSizeLimit = DEFAULT_MINIMUM_FONT_SIZE_LIMIT, } ) { - // Calculate missing minimumFontSize and maximumFontSize from - // defaultFontSize if provided. + /* + * Caches minimumFontSize in minimumFontSizeValue + * so we can check if minimumFontSize exists later. + */ + let minimumFontSizeValue = minimumFontSize; + + /* + * Calculates missing minimumFontSize and maximumFontSize from + * defaultFontSize if provided. + */ if ( fontSize ) { // Parses default font size. const fontSizeParsed = getTypographyValueAndUnit( fontSize ); @@ -68,8 +76,8 @@ export function getComputedFluidTypographyValue( { } // If no minimumFontSize is provided, derive using min scale factor. - if ( ! minimumFontSize ) { - minimumFontSize = + if ( ! minimumFontSizeValue ) { + minimumFontSizeValue = roundToPrecision( fontSizeParsed.value * minimumFontSizeFactor, 3 @@ -84,30 +92,28 @@ export function getComputedFluidTypographyValue( { } ); - /* - * Checks if a user-defined font size is lower than $minimum_font_size_limit. If so than it should become the minimum font size. - * Otherwise, if the minimum font size is lower than $minimum_font_size_limit - * use $minimum_font_size_limit instead. - */ if ( !! minimumFontSizeLimitParsed?.value ) { - // @TODO check if there was no min size value passed! - if ( fontSizeParsed.value < minimumFontSizeLimitParsed.value ) { - minimumFontSize = `${ fontSizeParsed.value }${ fontSizeParsed.unit }`; - } else { - const minimumFontSizeParsed = getTypographyValueAndUnit( - minimumFontSize, - { - coerceTo: fontSizeParsed.unit, - } - ); - - if ( - !! minimumFontSizeParsed?.value && - minimumFontSizeParsed.value < - minimumFontSizeLimitParsed.value - ) { - minimumFontSize = `${ minimumFontSizeLimitParsed.value }${ minimumFontSizeLimitParsed.unit }`; + if ( + ! minimumFontSize && + fontSizeParsed?.value < minimumFontSizeLimitParsed?.value + ) { + return null; + } + const minimumFontSizeParsed = getTypographyValueAndUnit( + minimumFontSizeValue, + { + coerceTo: fontSizeParsed.unit, } + ); + /* + * Otherwise, if the passed or calculated minimum font size is lower than $minimum_font_size_limit + * use $minimum_font_size_limit instead. + */ + if ( + !! minimumFontSizeParsed?.value && + minimumFontSizeParsed.value < minimumFontSizeLimitParsed.value + ) { + minimumFontSizeValue = `${ minimumFontSizeLimitParsed.value }${ minimumFontSizeLimitParsed.unit }`; } } @@ -122,12 +128,13 @@ export function getComputedFluidTypographyValue( { } // Return early if one of the provided inputs is not provided. - if ( ! minimumFontSize || ! maximumFontSize ) { + if ( ! minimumFontSizeValue || ! maximumFontSize ) { return null; } // Grab the minimum font size and normalize it in order to use the value for calculations. - const minimumFontSizeParsed = getTypographyValueAndUnit( minimumFontSize ); + const minimumFontSizeParsed = + getTypographyValueAndUnit( minimumFontSizeValue ); // We get a 'preferred' unit to keep units consistent when calculating, // otherwise the result will not be accurate. @@ -149,9 +156,12 @@ export function getComputedFluidTypographyValue( { } // Use rem for accessible fluid target font scaling. - const minimumFontSizeRem = getTypographyValueAndUnit( minimumFontSize, { - coerceTo: 'rem', - } ); + const minimumFontSizeRem = getTypographyValueAndUnit( + minimumFontSizeValue, + { + coerceTo: 'rem', + } + ); // Viewport widths defined for fluid typography. Normalize units const maximumViewPortWidthParsed = getTypographyValueAndUnit( @@ -192,7 +202,7 @@ export function getComputedFluidTypographyValue( { ); const fluidTargetFontSize = `${ minimumFontSizeRem.value }${ minimumFontSizeRem.unit } + ((1vw - ${ viewPortWidthOffset }) * ${ linearFactorScaled })`; - return `clamp(${ minimumFontSize }, ${ fluidTargetFontSize }, ${ maximumFontSize })`; + return `clamp(${ minimumFontSizeValue }, ${ fluidTargetFontSize }, ${ maximumFontSize })`; } /** @@ -248,6 +258,18 @@ export function getTypographyValueAndUnit( rawValue, options = {} ) { unit = coerceTo; } + /* + * No calculation is required if swapping between em and rem yet, + * since we assume a root size value. Later we might like to differentiate between + * :root font size (rem) and parent element font size (em) relativity. + */ + if ( + ( 'em' === coerceTo || 'rem' === coerceTo ) && + ( 'em' === unit || 'rem' === unit ) + ) { + unit = coerceTo; + } + return { value: roundToPrecision( returnValue, 3 ), unit, diff --git a/packages/edit-site/src/components/global-styles/test/typography-utils.js b/packages/edit-site/src/components/global-styles/test/typography-utils.js index b05dbc284dc343..7014538ce8ce9a 100644 --- a/packages/edit-site/src/components/global-styles/test/typography-utils.js +++ b/packages/edit-site/src/components/global-styles/test/typography-utils.js @@ -190,7 +190,20 @@ describe( 'typography utils', () => { }, { - message: 'return fluid clamp value.', + message: + 'return size where no min is give and size is less than default min size.', + preset: { + size: '3px', + }, + typographySettings: { + fluid: true, + }, + expected: '3px', + }, + + { + message: + 'return fluid clamp value with different min max units.', preset: { size: '28px', fluid: { @@ -261,6 +274,18 @@ describe( 'typography utils', () => { 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 1.49), 1.65rem)', }, + { + message: 'adjust computed min in em to min limit.', + preset: { + size: '1.1em', + }, + typographySettings: { + fluid: true, + }, + expected: + 'clamp(0.875em, 0.875rem + ((1vw - 0.48em) * 1.49), 1.65em)', + }, + { message: 'adjust fluid min value in px to min limit', preset: { diff --git a/packages/edit-site/src/components/global-styles/typography-utils.js b/packages/edit-site/src/components/global-styles/typography-utils.js index af71a96210ed9a..6e26a3155ed543 100644 --- a/packages/edit-site/src/components/global-styles/typography-utils.js +++ b/packages/edit-site/src/components/global-styles/typography-utils.js @@ -10,32 +10,31 @@ import { getComputedFluidTypographyValue } from '@wordpress/block-editor'; /** - * @typedef {Object} FluidValues + * @typedef {Object} FluidPreset * @property {string|undefined} max A maximum font size value. * @property {?string|undefined} min A minimum font size value. */ /** - * @typedef {Object} FontSize + * @typedef {Object} Preset * @property {?string|?number} size A default font size. * @property {string} name A font size name, displayed in the UI. * @property {string} slug A font size slug - * @property {boolean|FluidValues|undefined} fluid A font size slug + * @property {boolean|FluidPreset|undefined} fluid A font size slug */ /** - * Returns a font-size value based on a given fontSize. - * The fontSize is represented in the preset format as seen in theme.json. + * Returns a font-size value based on a given font-size preset. * Takes into account fluid typography parameters and attempts to return a css formula depending on available, valid values. * - * @param {FontSize} fontSize - * @param {Object} typographySettings - * @param {boolean} typographySettings.fluid Whether fluid typography is enabled. + * @param {Preset} preset + * @param {Object} typographySettings + * @param {boolean} typographySettings.fluid Whether fluid typography is enabled. * - * @return {string|*} A font-size value or the value of fontSize.size. + * @return {string|*} A font-size value or the value of preset.size. */ -export function getTypographyFontSizeValue( fontSize, typographySettings ) { - const { size: defaultSize } = fontSize; +export function getTypographyFontSizeValue( preset, typographySettings ) { + const { size: defaultSize } = preset; /* * Catches falsy values and 0/'0'. @@ -50,13 +49,13 @@ export function getTypographyFontSizeValue( fontSize, typographySettings ) { } // A font size has explicitly bypassed fluid calculations. - if ( false === fontSize?.fluid ) { + if ( false === preset?.fluid ) { return defaultSize; } const fluidFontSizeValue = getComputedFluidTypographyValue( { - minimumFontSize: fontSize?.fluid?.min, - maximumFontSize: fontSize?.fluid?.max, + minimumFontSize: preset?.fluid?.min, + maximumFontSize: preset?.fluid?.max, fontSize: defaultSize, } ); diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php index e5ca3bfa94e349..740aadd2366681 100644 --- a/phpunit/block-supports/typography-test.php +++ b/phpunit/block-supports/typography-test.php @@ -293,7 +293,7 @@ public function test_should_generate_classname_for_font_family() { * @dataProvider data_generate_font_size_preset_fixtures * * @param array $font_size { - * Required. fontSizes represented in the preset format as seen in theme.json. + * Required. A font size as represented in the fontSizes preset format 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. @@ -448,7 +448,15 @@ public function data_generate_font_size_preset_fixtures() { 'expected_output' => '10em', ), - 'return_fluid_clamp_value' => array( + 'return_size_where_no_min_is_given_and_less_than_default_min_size' => array( + 'font_size' => array( + 'size' => '3px', + ), + 'should_use_fluid_typography' => true, + 'expected_output' => '3px', + ), + + 'return_fluid_clamp_value_with_different_min_max_units' => array( 'font_size' => array( 'size' => '28px', 'fluid' => array( @@ -497,14 +505,14 @@ public function data_generate_font_size_preset_fixtures() { 'should_use_fluid_typography' => true, 'expected_output' => 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 1.49), 1.65rem)', ), -// @TODO check that $fluid_target_font_size should use `rem` when `em` font size value is passed. -// 'default_return_clamp_value_with_replaced_fluid_min_value_in_em' => array( -// 'font_size' => array( -// 'size' => '1.1em', -// ), -// 'should_use_fluid_typography' => true, -// 'expected_output' => 'clamp(0.875em, 0.875em + ((1vw - 0.48em) * 1.49), 1.65em)', -// ), + + 'default_return_clamp_value_with_replaced_fluid_min_value_in_em' => array( + 'font_size' => array( + 'size' => '1.1em', + ), + 'should_use_fluid_typography' => true, + 'expected_output' => 'clamp(0.875em, 0.875rem + ((1vw - 0.48em) * 1.49), 1.65em)', + ), 'should_adjust_fluid_min_value_in_px_to_min_limit' => array( 'font_size' => array( @@ -692,7 +700,7 @@ public function data_generate_replace_inline_font_styles_with_fluid_values_fixtu 'block_content' => "
\n \n

A paragraph inside a group

", 'font_size_value' => '1.5em', 'should_use_fluid_typography' => true, - 'expected_output' => "
\n \n

A paragraph inside a group

", + 'expected_output' => "
\n \n

A paragraph inside a group

", ), ); } From 9222dce27a9cf448a8c31530e4dbcf8f83872666 Mon Sep 17 00:00:00 2001 From: ramonjd Date: Mon, 17 Oct 2022 13:40:53 +1100 Subject: [PATCH 08/12] Oh Linter! You persistent crank. --- lib/block-supports/typography.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index 9a226241ea9ec5..4c943895e25234 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -535,11 +535,11 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty $fluid_font_size_value = gutenberg_get_computed_fluid_typography_value( array( - 'minimum_viewport_width' => $default_minimum_viewport_width, - 'maximum_viewport_width' => $default_maximum_viewport_width, - 'minimum_font_size' => $minimum_font_size_raw, - 'maximum_font_size' => $maximum_font_size_raw, - 'scale_factor' => $default_scale_factor, + 'minimum_viewport_width' => $default_minimum_viewport_width, + 'maximum_viewport_width' => $default_maximum_viewport_width, + 'minimum_font_size' => $minimum_font_size_raw, + 'maximum_font_size' => $maximum_font_size_raw, + 'scale_factor' => $default_scale_factor, ) ); From df6c71b88da5ab164ec185fab90ff24a760f2330 Mon Sep 17 00:00:00 2001 From: ramonjd Date: Tue, 18 Oct 2022 13:52:20 +1100 Subject: [PATCH 09/12] For font sizes of < 14px that have no defined minimum sizes, use the font size to set the floor of the clamp() value. --- lib/block-supports/typography.php | 6 +-- .../src/components/font-sizes/fluid-utils.js | 40 +++++++++++-------- .../global-styles/test/typography-utils.js | 5 ++- phpunit/block-supports/typography-test.php | 4 +- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index 4c943895e25234..21ad167c127083 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -453,7 +453,7 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty return $preset['size']; } - // Check if fluid font sizes are activated. + // Checks 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; @@ -506,10 +506,10 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty /* * If a minimum size was not passed to this function * and the user-defined font size is lower than $minimum_font_size_limit, - * then do not fluidify. + * then uses the user-defined font size as the minimum font-size. */ if ( ! isset( $fluid_font_size_settings['min'] ) && $preferred_size['value'] < $minimum_font_size_limit['value'] ) { - return $preset['size']; + $minimum_font_size_raw = implode( '', $preferred_size ); } else { $minimum_font_size_parsed = gutenberg_get_typography_value_and_unit( $minimum_font_size_raw, diff --git a/packages/block-editor/src/components/font-sizes/fluid-utils.js b/packages/block-editor/src/components/font-sizes/fluid-utils.js index da48b2586774c6..39b7cae29bc406 100644 --- a/packages/block-editor/src/components/font-sizes/fluid-utils.js +++ b/packages/block-editor/src/components/font-sizes/fluid-utils.js @@ -93,27 +93,35 @@ export function getComputedFluidTypographyValue( { ); if ( !! minimumFontSizeLimitParsed?.value ) { + /* + * If a minimum size was not passed to this function + * and the user-defined font size is lower than $minimum_font_size_limit, + * then uses the user-defined font size as the minimum font-size. + */ if ( ! minimumFontSize && fontSizeParsed?.value < minimumFontSizeLimitParsed?.value ) { - return null; - } - const minimumFontSizeParsed = getTypographyValueAndUnit( - minimumFontSizeValue, - { - coerceTo: fontSizeParsed.unit, + minimumFontSizeValue = `${ fontSizeParsed.value }${ fontSizeParsed.unit }`; + } else { + const minimumFontSizeParsed = getTypographyValueAndUnit( + minimumFontSizeValue, + { + coerceTo: fontSizeParsed.unit, + } + ); + + /* + * Otherwise, if the passed or calculated minimum font size is lower than $minimum_font_size_limit + * use $minimum_font_size_limit instead. + */ + if ( + !! minimumFontSizeParsed?.value && + minimumFontSizeParsed.value < + minimumFontSizeLimitParsed.value + ) { + minimumFontSizeValue = `${ minimumFontSizeLimitParsed.value }${ minimumFontSizeLimitParsed.unit }`; } - ); - /* - * Otherwise, if the passed or calculated minimum font size is lower than $minimum_font_size_limit - * use $minimum_font_size_limit instead. - */ - if ( - !! minimumFontSizeParsed?.value && - minimumFontSizeParsed.value < minimumFontSizeLimitParsed.value - ) { - minimumFontSizeValue = `${ minimumFontSizeLimitParsed.value }${ minimumFontSizeLimitParsed.unit }`; } } diff --git a/packages/edit-site/src/components/global-styles/test/typography-utils.js b/packages/edit-site/src/components/global-styles/test/typography-utils.js index 7014538ce8ce9a..ae40fcffdea7c4 100644 --- a/packages/edit-site/src/components/global-styles/test/typography-utils.js +++ b/packages/edit-site/src/components/global-styles/test/typography-utils.js @@ -191,14 +191,15 @@ describe( 'typography utils', () => { { message: - 'return size where no min is give and size is less than default min size.', + 'return clamped using font size where no min is given and size is less than default min size.', preset: { size: '3px', }, typographySettings: { fluid: true, }, - expected: '3px', + expected: + 'clamp(3px, 0.188rem + ((1vw - 7.68px) * 0.18), 4.5px)', }, { diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php index 740aadd2366681..5a39c158de1b44 100644 --- a/phpunit/block-supports/typography-test.php +++ b/phpunit/block-supports/typography-test.php @@ -448,12 +448,12 @@ public function data_generate_font_size_preset_fixtures() { 'expected_output' => '10em', ), - 'return_size_where_no_min_is_given_and_less_than_default_min_size' => array( + 'return_clamped_size_where_no_min_is_given_and_less_than_default_min_size' => array( 'font_size' => array( 'size' => '3px', ), 'should_use_fluid_typography' => true, - 'expected_output' => '3px', + 'expected_output' => 'clamp(3px, 0.188rem + ((1vw - 7.68px) * 0.18), 4.5px)', ), 'return_fluid_clamp_value_with_different_min_max_units' => array( From aa2ddf75430a5bb438dfbf2c1cfe00176941341e Mon Sep 17 00:00:00 2001 From: ramonjd Date: Tue, 18 Oct 2022 15:05:03 +1100 Subject: [PATCH 10/12] Removing max < min check. It wasn't there before. It can be a follow up if required as it requires extra logic. --- lib/block-supports/typography.php | 19 +++++++------------ .../src/components/font-sizes/fluid-utils.js | 9 ++------- .../global-styles/test/typography-utils.js | 5 +++-- phpunit/block-supports/typography-test.php | 4 ++-- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index 21ad167c127083..62d3232b76df57 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -375,7 +375,7 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { */ $font_size_unit = isset( $minimum_font_size['unit'] ) ? $minimum_font_size['unit'] : 'rem'; - // Grab the maximum font size and normalize it in order to use the value for calculations. + // Grabs the maximum font size and normalize it in order to use the value for calculations. $maximum_font_size = gutenberg_get_typography_value_and_unit( $maximum_font_size_raw, array( @@ -388,11 +388,6 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { return null; } - // Min font size should not be greater than max font size. - if ( $minimum_font_size['value'] > $maximum_font_size['value'] ) { - return null; - } - // Uses rem for accessible fluid target font scaling. $minimum_font_size_rem = gutenberg_get_typography_value_and_unit( $minimum_font_size_raw, @@ -489,6 +484,11 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty return $preset['size']; } + // If no fluid max font size is available, create one using max font size factor. + if ( ! $maximum_font_size_raw ) { + $maximum_font_size_raw = round( $preferred_size['value'] * $default_maximum_font_size_factor, 3 ) . $preferred_size['unit']; + } + // If no fluid min font size is available, create one using min font size factor. if ( ! $minimum_font_size_raw ) { $minimum_font_size_raw = round( $preferred_size['value'] * $default_minimum_font_size_factor, 3 ) . $preferred_size['unit']; @@ -519,7 +519,7 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty ); /* - * Otherwise, if the passed or calculated minimum font size is lower than $minimum_font_size_limit + * If the passed or calculated minimum font size is lower than $minimum_font_size_limit * use $minimum_font_size_limit instead. */ if ( ! empty( $minimum_font_size_parsed ) && $minimum_font_size_parsed['value'] < $minimum_font_size_limit['value'] ) { @@ -528,11 +528,6 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty } } - // If no fluid max font size is available, create one using max font size factor. - if ( ! $maximum_font_size_raw ) { - $maximum_font_size_raw = round( $preferred_size['value'] * $default_maximum_font_size_factor, 3 ) . $preferred_size['unit']; - } - $fluid_font_size_value = gutenberg_get_computed_fluid_typography_value( array( 'minimum_viewport_width' => $default_minimum_viewport_width, diff --git a/packages/block-editor/src/components/font-sizes/fluid-utils.js b/packages/block-editor/src/components/font-sizes/fluid-utils.js index 39b7cae29bc406..6bac4900a281b0 100644 --- a/packages/block-editor/src/components/font-sizes/fluid-utils.js +++ b/packages/block-editor/src/components/font-sizes/fluid-utils.js @@ -148,7 +148,7 @@ export function getComputedFluidTypographyValue( { // otherwise the result will not be accurate. const fontSizeUnit = minimumFontSizeParsed?.unit || 'rem'; - // Grab the maximum font size and normalize it in order to use the value for calculations. + // Grabs the maximum font size and normalize it in order to use the value for calculations. const maximumFontSizeParsed = getTypographyValueAndUnit( maximumFontSize, { coerceTo: fontSizeUnit, } ); @@ -158,12 +158,7 @@ export function getComputedFluidTypographyValue( { return null; } - // Max font size should not be greater than min font size. - if ( minimumFontSizeParsed.value > maximumFontSizeParsed.value ) { - return null; - } - - // Use rem for accessible fluid target font scaling. + // Uses rem for accessible fluid target font scaling. const minimumFontSizeRem = getTypographyValueAndUnit( minimumFontSizeValue, { diff --git a/packages/edit-site/src/components/global-styles/test/typography-utils.js b/packages/edit-site/src/components/global-styles/test/typography-utils.js index ae40fcffdea7c4..798ea06648c5b5 100644 --- a/packages/edit-site/src/components/global-styles/test/typography-utils.js +++ b/packages/edit-site/src/components/global-styles/test/typography-utils.js @@ -160,7 +160,7 @@ describe( 'typography utils', () => { { message: - 'Should return default value if min font size is greater than max.', + 'return clamped value if min font size is greater than max.', preset: { size: '3rem', fluid: { @@ -171,7 +171,8 @@ describe( 'typography utils', () => { typographySettings: { fluid: true, }, - expected: '3rem', + expected: + 'clamp(5rem, 5rem + ((1vw - 0.48rem) * -5.769), 32px)', }, { diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php index 5a39c158de1b44..e18f8e58c87284 100644 --- a/phpunit/block-supports/typography-test.php +++ b/phpunit/block-supports/typography-test.php @@ -424,7 +424,7 @@ public function data_generate_font_size_preset_fixtures() { 'expected_output' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)', ), - 'return_default_value_if_min_font_size_is_greater_than_max' => array( + 'return_clamped_value_if_min_font_size_is_greater_than_max' => array( 'font_size' => array( 'size' => '3rem', 'fluid' => array( @@ -433,7 +433,7 @@ public function data_generate_font_size_preset_fixtures() { ), ), 'should_use_fluid_typography' => true, - 'expected_output' => '3rem', + 'expected_output' => 'clamp(5rem, 5rem + ((1vw - 0.48rem) * -5.769), 32px)', ), 'return_size_with_invalid_fluid_units' => array( From b65a8b6b55f4dd4e0cb6ac561cebdb59e179857c Mon Sep 17 00:00:00 2001 From: ramonjd Date: Tue, 18 Oct 2022 18:14:48 +1100 Subject: [PATCH 11/12] Checking for a zero-based linear factor. If we find one, default to `1` --- lib/block-supports/typography.php | 5 +++-- .../src/components/font-sizes/fluid-utils.js | 6 +++--- .../global-styles/test/typography-utils.js | 16 ++++++++++++++++ phpunit/block-supports/typography-test.php | 12 ++++++++++++ 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index 62d3232b76df57..b1adaf1a679b81 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -414,8 +414,9 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) { // Borrowed from https://websemantics.uk/tools/responsive-font-calculator/. $view_port_width_offset = round( $minimum_viewport_width['value'] / 100, 3 ) . $font_size_unit; $linear_factor = 100 * ( ( $maximum_font_size['value'] - $minimum_font_size['value'] ) / ( $maximum_viewport_width['value'] - $minimum_viewport_width['value'] ) ); - $linear_factor = round( $linear_factor, 3 ) * $scale_factor; - $fluid_target_font_size = implode( '', $minimum_font_size_rem ) . " + ((1vw - $view_port_width_offset) * $linear_factor)"; + $linear_factor_scaled = round( $linear_factor * $scale_factor, 3 ); + $linear_factor_scaled = empty( $linear_factor_scaled ) ? 1 : $linear_factor_scaled; + $fluid_target_font_size = implode( '', $minimum_font_size_rem ) . " + ((1vw - $view_port_width_offset) * $linear_factor_scaled)"; return "clamp($minimum_font_size_raw, $fluid_target_font_size, $maximum_font_size_raw)"; } diff --git a/packages/block-editor/src/components/font-sizes/fluid-utils.js b/packages/block-editor/src/components/font-sizes/fluid-utils.js index 6bac4900a281b0..c4ae1e1893599c 100644 --- a/packages/block-editor/src/components/font-sizes/fluid-utils.js +++ b/packages/block-editor/src/components/font-sizes/fluid-utils.js @@ -200,7 +200,7 @@ export function getComputedFluidTypographyValue( { ( maximumViewPortWidthParsed.value - minumumViewPortWidthParsed.value ) ); const linearFactorScaled = roundToPrecision( - linearFactor * scaleFactor, + ( linearFactor || 1 ) * scaleFactor, 3 ); const fluidTargetFontSize = `${ minimumFontSizeRem.value }${ minimumFontSizeRem.unit } + ((1vw - ${ viewPortWidthOffset }) * ${ linearFactorScaled })`; @@ -289,8 +289,8 @@ export function getTypographyValueAndUnit( rawValue, options = {} ) { * @return {number|undefined} Value rounded to standard precision. */ export function roundToPrecision( value, digits = 3 ) { - const base = Math.pow( 10, digits + 1 ); + const base = Math.pow( 10, digits ); return Number.isFinite( value ) - ? parseFloat( ( value + 1 / base ).toFixed( digits ) ) + ? parseFloat( Math.round( value * base ) / base ) : undefined; } diff --git a/packages/edit-site/src/components/global-styles/test/typography-utils.js b/packages/edit-site/src/components/global-styles/test/typography-utils.js index 798ea06648c5b5..e0c29a37ea9811 100644 --- a/packages/edit-site/src/components/global-styles/test/typography-utils.js +++ b/packages/edit-site/src/components/global-styles/test/typography-utils.js @@ -333,6 +333,22 @@ describe( 'typography utils', () => { expected: 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 7.933), 5rem)', }, + + { + message: + 'return a fluid font size a min and max font sizes are equal.', + preset: { + size: '4rem', + fluid: { + min: '30px', + max: '30px', + }, + }, + typographySettings: { + fluid: true, + }, + expected: 'clamp(30px, 1.875rem + ((1vw - 7.68px) * 1), 30px)', + }, ].forEach( ( { message, preset, typographySettings, expected } ) => { it( `should ${ message }`, () => { expect( diff --git a/phpunit/block-supports/typography-test.php b/phpunit/block-supports/typography-test.php index e18f8e58c87284..6ecac215b0f61c 100644 --- a/phpunit/block-supports/typography-test.php +++ b/phpunit/block-supports/typography-test.php @@ -547,6 +547,18 @@ public function data_generate_font_size_preset_fixtures() { 'should_use_fluid_typography' => true, 'expected_output' => 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 7.933), 5rem)', ), + + 'should_return_fluid_value_when_min_and_max_font_sizes_are_equal' => array( + 'font_size' => array( + 'size' => '4rem', + 'fluid' => array( + 'min' => '30px', + 'max' => '30px', + ), + ), + 'should_use_fluid_typography' => true, + 'expected_output' => 'clamp(30px, 1.875rem + ((1vw - 7.68px) * 1), 30px)', + ), ); } From b7a01f828bffd211078db3d03f432ba82bc4881f Mon Sep 17 00:00:00 2001 From: ramonjd Date: Tue, 18 Oct 2022 18:16:29 +1100 Subject: [PATCH 12/12] Refer to correct JS var in JS file --- .../block-editor/src/components/font-sizes/fluid-utils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/font-sizes/fluid-utils.js b/packages/block-editor/src/components/font-sizes/fluid-utils.js index c4ae1e1893599c..2c6540f89d0494 100644 --- a/packages/block-editor/src/components/font-sizes/fluid-utils.js +++ b/packages/block-editor/src/components/font-sizes/fluid-utils.js @@ -95,7 +95,7 @@ export function getComputedFluidTypographyValue( { if ( !! minimumFontSizeLimitParsed?.value ) { /* * If a minimum size was not passed to this function - * and the user-defined font size is lower than $minimum_font_size_limit, + * and the user-defined font size is lower than `minimumFontSizeLimit`, * then uses the user-defined font size as the minimum font-size. */ if ( @@ -112,8 +112,8 @@ export function getComputedFluidTypographyValue( { ); /* - * Otherwise, if the passed or calculated minimum font size is lower than $minimum_font_size_limit - * use $minimum_font_size_limit instead. + * Otherwise, if the passed or calculated minimum font size is lower than `minimumFontSizeLimit` + * use `minimumFontSizeLimit` instead. */ if ( !! minimumFontSizeParsed?.value &&